6892 lines
256 KiB
Plaintext
6892 lines
256 KiB
Plaintext
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
|
|
<External>null</External>
|
|
<External>nil</External>
|
|
<Item class="Tool" referent="RBX0">
|
|
<Properties>
|
|
<bool name="Enabled">true</bool>
|
|
<CoordinateFrame name="Grip">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0.349999994</Z>
|
|
<R00>1</R00>
|
|
<R01>0</R01>
|
|
<R02>0</R02>
|
|
<R10>0</R10>
|
|
<R11>1</R11>
|
|
<R12>0</R12>
|
|
<R20>0</R20>
|
|
<R21>0</R21>
|
|
<R22>1</R22>
|
|
</CoordinateFrame>
|
|
<string name="Name">StamperTool</string>
|
|
<Content name="TextureId"><url>http://www.roblox.com/asset/?id=59102781</url></Content>
|
|
</Properties>
|
|
<Item class="Part" referent="RBX1">
|
|
<Properties>
|
|
<bool name="Anchored">false</bool>
|
|
<float name="BackParamA">-0.5</float>
|
|
<float name="BackParamB">0.5</float>
|
|
<token name="BackSurface">0</token>
|
|
<token name="BackSurfaceInput">0</token>
|
|
<float name="BottomParamA">-0.5</float>
|
|
<float name="BottomParamB">0.5</float>
|
|
<token name="BottomSurface">4</token>
|
|
<token name="BottomSurfaceInput">0</token>
|
|
<int name="BrickColor">194</int>
|
|
<CoordinateFrame name="CFrame">
|
|
<X>0.0988349915</X>
|
|
<Y>0.274166554</Y>
|
|
<Z>-0.195800781</Z>
|
|
<R00>0.995120585</R00>
|
|
<R01>-7.11792454e-005</R01>
|
|
<R02>0.0986662284</R02>
|
|
<R10>-1.0218595e-005</R10>
|
|
<R11>0.999999642</R11>
|
|
<R12>0.000824476127</R12>
|
|
<R20>-0.0986662582</R20>
|
|
<R21>-0.000821461435</R21>
|
|
<R22>0.995120227</R22>
|
|
</CoordinateFrame>
|
|
<bool name="CanCollide">true</bool>
|
|
<float name="Elasticity">0.5</float>
|
|
<float name="Friction">0.300000012</float>
|
|
<float name="FrontParamA">-0.5</float>
|
|
<float name="FrontParamB">0.5</float>
|
|
<token name="FrontSurface">0</token>
|
|
<token name="FrontSurfaceInput">0</token>
|
|
<float name="LeftParamA">-0.5</float>
|
|
<float name="LeftParamB">0.5</float>
|
|
<token name="LeftSurface">0</token>
|
|
<token name="LeftSurfaceInput">0</token>
|
|
<bool name="Locked">true</bool>
|
|
<token name="Material">256</token>
|
|
<string name="Name">Handle</string>
|
|
<float name="Reflectance">0</float>
|
|
<float name="RightParamA">-0.5</float>
|
|
<float name="RightParamB">0.5</float>
|
|
<token name="RightSurface">0</token>
|
|
<token name="RightSurfaceInput">0</token>
|
|
<Vector3 name="RotVelocity">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0</Z>
|
|
</Vector3>
|
|
<float name="TopParamA">-0.5</float>
|
|
<float name="TopParamB">0.5</float>
|
|
<token name="TopSurface">3</token>
|
|
<token name="TopSurfaceInput">0</token>
|
|
<float name="Transparency">0</float>
|
|
<Vector3 name="Velocity">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0</Z>
|
|
</Vector3>
|
|
<token name="formFactorRaw">1</token>
|
|
<token name="shape">1</token>
|
|
<Vector3 name="size">
|
|
<X>1</X>
|
|
<Y>0.400000006</Y>
|
|
<Z>1</Z>
|
|
</Vector3>
|
|
</Properties>
|
|
<Item class="SpecialMesh" referent="RBX2">
|
|
<Properties>
|
|
<token name="LODX">2</token>
|
|
<token name="LODY">2</token>
|
|
<Content name="MeshId"><url>http://www.roblox.com/asset/?id=42163552</url></Content>
|
|
<token name="MeshType">5</token>
|
|
<string name="Name">Mesh</string>
|
|
<Vector3 name="Offset">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0</Z>
|
|
</Vector3>
|
|
<Vector3 name="Scale">
|
|
<X>0.899999976</X>
|
|
<Y>0.899999976</Y>
|
|
<Z>0.899999976</Z>
|
|
</Vector3>
|
|
<Content name="TextureId"><url>http://www.roblox.com/asset/?id=42163513</url></Content>
|
|
<Vector3 name="VertexColor">
|
|
<X>1</X>
|
|
<Y>1</Y>
|
|
<Z>1</Z>
|
|
</Vector3>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="ObjectValue" referent="RBX3">
|
|
<Properties>
|
|
<string name="Name">PlayerOwner</string>
|
|
<Ref name="Value">null</Ref>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ObjectValue" referent="RBX4">
|
|
<Properties>
|
|
<string name="Name">SavedState</string>
|
|
<Ref name="Value">null</Ref>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Model" referent="RBX5">
|
|
<Properties>
|
|
<CoordinateFrame name="ModelInPrimary">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0</Z>
|
|
<R00>1</R00>
|
|
<R01>0</R01>
|
|
<R02>0</R02>
|
|
<R10>0</R10>
|
|
<R11>1</R11>
|
|
<R12>0</R12>
|
|
<R20>0</R20>
|
|
<R21>0</R21>
|
|
<R22>1</R22>
|
|
</CoordinateFrame>
|
|
<string name="Name">LuaGlobalVariables</string>
|
|
<Ref name="PrimaryPart">null</Ref>
|
|
</Properties>
|
|
<Item class="Model" referent="RBX6">
|
|
<Properties>
|
|
<CoordinateFrame name="ModelInPrimary">
|
|
<X>0</X>
|
|
<Y>0</Y>
|
|
<Z>0</Z>
|
|
<R00>1</R00>
|
|
<R01>0</R01>
|
|
<R02>0</R02>
|
|
<R10>0</R10>
|
|
<R11>1</R11>
|
|
<R12>0</R12>
|
|
<R20>0</R20>
|
|
<R21>0</R21>
|
|
<R22>1</R22>
|
|
</CoordinateFrame>
|
|
<string name="Name">InsertAsset</string>
|
|
<Ref name="PrimaryPart">null</Ref>
|
|
</Properties>
|
|
<Item class="StringValue" referent="RBX7">
|
|
<Properties>
|
|
<string name="Name">AssetName</string>
|
|
<string name="Value"></string>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="IntValue" referent="RBX8">
|
|
<Properties>
|
|
<string name="Name">AssetId</string>
|
|
<int name="Value">0</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="StringValue" referent="RBX9">
|
|
<Properties>
|
|
<string name="Name">Image</string>
|
|
<string name="Value"></string>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX10">
|
|
<Properties>
|
|
<string name="Name">StampMode</string>
|
|
<bool name="Value">true</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX11">
|
|
<Properties>
|
|
<string name="Name">Updated</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX12">
|
|
<Properties>
|
|
<string name="Name">SwitchLoaderToDialog</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
<Item class="StringValue" referent="RBX13">
|
|
<Properties>
|
|
<string name="Name">DialogType</string>
|
|
<string name="Value">Stamp</string>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="StringValue" referent="RBX14">
|
|
<Properties>
|
|
<string name="Name">AssetImage</string>
|
|
<string name="Value">nil</string>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX15">
|
|
<Properties>
|
|
<string name="Name">ShowInvalidPlacement</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX16">
|
|
<Properties>
|
|
<string name="Name">ShowMaxedOut</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX17">
|
|
<Properties>
|
|
<string name="Name">SwitchMode</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
<Item class="StringValue" referent="RBX18">
|
|
<Properties>
|
|
<string name="Name">Mode</string>
|
|
<string name="Value"></string>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX19">
|
|
<Properties>
|
|
<string name="Name">Stamped</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX20">
|
|
<Properties>
|
|
<string name="Name">Moving</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX21">
|
|
<Properties>
|
|
<string name="Name">ShowAdminCategories</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="IntValue" referent="RBX22">
|
|
<Properties>
|
|
<string name="Name">userIDs</string>
|
|
<int name="Value">1</int>
|
|
</Properties>
|
|
<Item class="IntValue" referent="RBX23">
|
|
<Properties>
|
|
<string name="Name">userID</string>
|
|
<int name="Value">11744447</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX24">
|
|
<Properties>
|
|
<string name="Name">ReloadCurrentAsset</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX25">
|
|
<Properties>
|
|
<string name="Name">ReloadCurrentAsset</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="BoolValue" referent="RBX26">
|
|
<Properties>
|
|
<string name="Name">MouseClick</string>
|
|
<bool name="Value">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX27">
|
|
<Properties>
|
|
<bool name="Disabled">true</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">BasePlateGuide</string>
|
|
<ProtectedString name="Source">local pointDirection = nil
|
|
|
|
local tailLength = 2 -- 2 or 7
|
|
--local dSize = -.05 -- .01 or .005
|
|
local dSize = 0 -- because we want the targets to all be the same size (tail isn't larger anymore; just "ghost" effect)
|
|
local dTime = .04 --.025
|
|
|
|
-- old targetLock pic (square): 48972746
|
|
|
|
local targetLockSize = .2
|
|
local arrowSize = .1
|
|
|
|
local arrowScreenProportionSize = .95
|
|
local arrowMoveFactor = .025
|
|
|
|
local targetMoveFactor = targetLockSize / 2 - .025
|
|
|
|
local halfDSize = dSize / 2
|
|
|
|
local r = game:service("RunService")
|
|
|
|
local vChar = script.Parent
|
|
if vChar == nil then script.Parent = nil end
|
|
|
|
local vPlay = game.Players:GetPlayerFromCharacter(vChar)
|
|
if vPlay == nil then script.Parent = nil end
|
|
|
|
local arrowGui = vPlay.PlayerGui:FindFirstChild("GuideArrowGui")
|
|
if arrowGui == nil then
|
|
	arrowGui = script.GuideArrowGui
|
|
	arrowGui.Parent = vPlay.PlayerGui
|
|
else
|
|
	script.GuideArrowGui:remove()
|
|
end
|
|
|
|
local upArrow = arrowGui.UpArrow
|
|
local downArrow = arrowGui.DownArrow
|
|
local leftArrow = arrowGui.LeftArrow
|
|
local rightArrow = arrowGui.RightArrow
|
|
local targetLock = arrowGui.TargetLock
|
|
local arrowList = {upArrow, downArrow, leftArrow, rightArrow, targetLock}
|
|
|
|
local goAway = arrowGui.GoAwayButton
|
|
goAway.Visible = true
|
|
goAway.Active = true
|
|
local keepShowing = true
|
|
goAway.MouseButton1Click:connect(function () keepShowing = false end)
|
|
|
|
|
|
local arrowHeightAugment = 0.0
|
|
local arrowWidthAugment = 0.0
|
|
local targetHeightAugment = 0.0
|
|
local targetWidthAugment = 0.0
|
|
|
|
|
|
local targetLockList = {targetLock}
|
|
for i = 1, tailLength do table.insert(targetLockList, targetLock:Clone()) end
|
|
|
|
targetLockList[1].Size = UDim2.new(targetLockSize, 0, targetLockSize, 0)
|
|
for i = 1, #targetLockList-1 do
|
|
	targetLockList[i+1].Parent = arrowGui
|
|
	--targetLockList[i+1].Size = UDim2.new(targetLockSize-i*dSize, 0, targetLockSize-i*dSize, 0)
|
|
end
|
|
-- switching over to a "ghost-like" transparency effect, but this means we have to upload separate images :(
|
|
-- if our tail is turned on, manually apply the ghosting to the next two images
|
|
if tailLength > 0 then targetLockList[2].Image = "http://www.roblox.com/asset/?id=49324811" end
|
|
if tailLength > 1 then targetLockList[3].Image = "http://www.roblox.com/asset/?id=49324846" end
|
|
|
|
|
|
function onResize() -- force arrows into a square resolution
|
|
	xSize = arrowGui.AbsoluteSize.X
|
|
	ySize = arrowGui.AbsoluteSize.Y
|
|
|
|
	if xSize >= ySize then
|
|
		arrowHeightAugment = 0.0
|
|
|
|
		-- calculate arrowWidthAugment and new arrow ratio here
|
|
		newArrowUDim = UDim2.new(ySize / xSize * arrowSize, 0, arrowSize, 0)
|
|
		rightArrow.Size = newArrowUDim
|
|
		leftArrow.Size = newArrowUDim
|
|
		upArrow.Size = newArrowUDim
|
|
		downArrow.Size = newArrowUDim
|
|
|
|
		for tli = 1, #targetLockList do
|
|
			targetLockList[tli].Size = UDim2.new(ySize / xSize * (targetLockSize-tli*dSize), 0, targetLockSize-tli*dSize, 0)
|
|
		end
|
|
|
|
		arrowWidthAugment = (xSize - ySize)*arrowSize*.5 / xSize
|
|
	else
|
|
		arrowWidthAugment = 0.0
|
|
|
|
		-- calculate arrowHeightAugment here
|
|
		newArrowUDim = UDim2.new(arrowSize, 0, xSize / ySize * arrowSize, 0)
|
|
		rightArrow.Size = newArrowUDim
|
|
		leftArrow.Size = newArrowUDim
|
|
		upArrow.Size = newArrowUDim
|
|
		downArrow.Size = newArrowUDim
|
|
|
|
		for tli = 1, #targetLockList do
|
|
			targetLockList[tli].Size = UDim2.new(targetLockSize-tli*dSize, 0, xSize / ySize * (targetLockSize-tli*dSize), 0)
|
|
		end
|
|
|
|
		arrowHeightAugment = (ySize - xSize)*arrowSize*.5 / ySize
|
|
	end
|
|
|
|
	targetWidthAugment = targetLock.Size.X.Scale / 2 - .025
|
|
	targetHeightAugment = targetLock.Size.Y.Scale / 2 - .025
|
|
end
|
|
|
|
arrowGui.Changed:connect(onResize) -- dynamically resize the arrows on screen resize
|
|
|
|
function findMyBasePlate()
|
|
	--if true then return game.Workspace.Base end -- for testing purposes
|
|
|
|
	local buildingAreas = game.Workspace.BuildingAreas:GetChildren()
|
|
	for i = 1, #buildingAreas do
|
|
		if buildingAreas[i].Player.Value == script.Parent.Name then
|
|
			return buildingAreas[i]:FindFirstChild("BasePlate") or buildingAreas[i].PlayerArea:FindFirstChild("BasePlate")
|
|
		end
|
|
	end
|
|
end
|
|
|
|
local myBase = findMyBasePlate()
|
|
if myBase == nil then
|
|
	print("BasePlateGuide script error: no base plate found!")
|
|
	-- abort if no BasePlate found
|
|
	arrowGui:remove()
|
|
	script:remove()
|
|
end
|
|
|
|
function setVisible(whichArrow)
|
|
	for i = 1, #arrowList do
|
|
		if arrowList[i] == whichArrow then
|
|
			arrowList[i].Visible = true
|
|
		else
|
|
			arrowList[i].Visible = false
|
|
		end
|
|
	end
|
|
end
|
|
|
|
function truncate(number, augmentation)
|
|
	if number+augmentation < 0 then return 0
|
|
elseif number > (1 - arrowSize)+augmentation then return (1 - arrowSize)+2*augmentation -- furthest extent we want the arrows to reach is .95 - arrowSize
|
|
	else return number+augmentation end
|
|
end
|
|
|
|
|
|
function notInBasePlate(myPos, base)
|
|
	local corner1 = base.Position - base.Size/2
|
|
	local corner2 = base.Position + base.Size/2
|
|
	if myPos.X > corner1.X and myPos.Y > corner1.Y and myPos.Z > corner1.Z and myPos.X < corner2.X and myPos.Z < corner2.Z then -- we only care they're somewhere above baseplate
|
|
		return false
|
|
	else
|
|
		return true
|
|
	end
|
|
end
|
|
|
|
local lastTime = 0
|
|
local camera = game.Workspace.CurrentCamera
|
|
while notInBasePlate(script.Parent.Torso.Position, myBase) and keepShowing do
|
|
	--pointDirection = (myBase.Position - script.Parent.Torso.Position) * Vector3.new(1, 0, 1)
|
|
	camFrame = camera.CoordinateFrame
|
|
	pointDirection = camFrame:vectorToObjectSpace(myBase.Position - camFrame.p)
|
|
	camZ = pointDirection.Z
|
|
	camX = pointDirection.X/math.abs(camZ)
|
|
	camY = pointDirection.Y/math.abs(camZ)
|
|
	--print(camX, camY, camZ)
|
|
|
|
	-- was .55 for 610 (Y) and 1.15 for 1286 (X), so seems like scaling factor is universally 1114 on both axes	
|
|
	-- nvm: at 1662 x 666, we have ... and .55, so seems like .55 always for Y, then X is scaled according to its proportion to Y
|
|
|
|
	local xThreshold = arrowGui.AbsoluteSize.X / arrowGui.AbsoluteSize.Y * .55
|
|
	local yThreshold = .55
|
|
|
|
	local nCamX = camX / xThreshold
|
|
	local nCamY = camY / yThreshold
|
|
|
|
	if (math.abs(nCamX) > 1 or math.abs(nCamY) > 1) or (camZ > 0) then -- camZ test makes sure we only lock on if facing right direction
|
|
		for j = 2, #targetLockList do
|
|
			targetLockList[j].Visible = false
|
|
		end
|
|
	
|
|
		if math.abs(nCamX) > math.abs(nCamY) then
|
|
			--if nCamY > 1 then nCamY = 1
|
|
			--elseif nCamY < -1 then nCamY = -1 end
|
|
|
|
			if camX > 0 then
|
|
				-- should go right
|
|
				rightArrow.Position = UDim2.new(arrowScreenProportionSize - arrowMoveFactor - .025 + 2*arrowWidthAugment, 0, truncate(arrowScreenProportionSize*(1-nCamY)/2 - arrowMoveFactor, arrowHeightAugment), 0)
|
|
				setVisible(rightArrow)
|
|
			else
|
|
				-- should go left
|
|
				leftArrow.Position = UDim2.new(0, 0, truncate(arrowScreenProportionSize*(1-nCamY)/2 - arrowMoveFactor, arrowHeightAugment), 0)
|
|
				setVisible(leftArrow)
|
|
			end
|
|
		else
|
|
			--if nCamX > 1 then nCamX = 1
|
|
			--elseif nCamX < -1 then nCamX = -1 end
|
|
|
|
			if camY > 0 then
|
|
				-- should go up
|
|
				upArrow.Position = UDim2.new(truncate(arrowScreenProportionSize*(nCamX+1)/2 - arrowMoveFactor, arrowWidthAugment), 0, 0, 0)
|
|
				setVisible(upArrow)
|
|
			else
|
|
				-- should go down
|
|
				downArrow.Position = UDim2.new(truncate(arrowScreenProportionSize*(nCamX+1)/2 - arrowMoveFactor, arrowWidthAugment), 0, arrowScreenProportionSize - arrowMoveFactor -.025 + 2*arrowHeightAugment, 0)
|
|
				setVisible(downArrow)
|
|
			end
|
|
		end
|
|
	else
|
|
		-- locked on target
|
|
		--for j = 2, #targetLockList do
|
|
			--targetLockList[j].Visible = true
|
|
		--end
|
|
		--targetLock.Position = UDim2.new(.95*(nCamX+1)/2 - targetMoveFactor, 0, .95*(1-nCamY)/2 - targetMoveFactor, 0)
|
|
		targetLock.Position = UDim2.new(.95*(nCamX+1)/2 - targetWidthAugment, 0, .95*(1-nCamY)/2 - targetHeightAugment, 0)
|
|
		setVisible(targetLock)
|
|
	end
|
|
|
|
	--wait()
|
|
	
|
|
	-- update every dTime seconds
|
|
|
|
	-- ok to do it this way instead of a ring array, because even though it's less efficient, it's less efficient by only one or two commands [since only have 2 "tails"]
|
|
|
|
	local t = r.Stepped:wait()
|
|
	if t - lastTime > dTime then
|
|
		lastTime = t
|
|
		for j = #targetLockList, 2, -1 do
|
|
			targetLockList[j].Position = targetLockList[j-1].Position + UDim2.new(halfDSize, 0, halfDSize, 0)
|
|
			targetLockList[j].Visible = targetLockList[j-1].Visible
|
|
		end
|
|
	end
|
|
end
|
|
|
|
--[[setVisible(nil)
|
|
for j = 2, #targetLockList do
|
|
	targetLockList[j].Visible = false
|
|
end
|
|
goAway.Visible = false
|
|
goAway.Active = false
|
|
]]--
|
|
arrowGui:remove()
|
|
script:remove()</ProtectedString>
|
|
</Properties>
|
|
<Item class="ScreenGui" referent="RBX28">
|
|
<Properties>
|
|
<string name="Name">GuideArrowGui</string>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX29">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset/?id=48972729 </url></Content>
|
|
<string name="Name">UpArrow</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.0500000007</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0500000007</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ImageLabel" referent="RBX30">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset/?id=48972703</url></Content>
|
|
<string name="Name">RightArrow</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.0500000007</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0500000007</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ImageLabel" referent="RBX31">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset/?id=48972653</url></Content>
|
|
<string name="Name">DownArrow</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.0500000007</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0500000007</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ImageLabel" referent="RBX32">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset/?id=48972682</url></Content>
|
|
<string name="Name">LeftArrow</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.0500000007</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0500000007</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ImageLabel" referent="RBX33">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset/?id=49321779</url></Content>
|
|
<string name="Name">TargetLock</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.0500000007</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0500000007</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX34">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4278255360</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">0</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">GoAwayButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>20</XO>
|
|
<YS>0</YS>
|
|
<YO>40</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>150</XO>
|
|
<YS>0</YS>
|
|
<YO>20</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<string name="Text">Hide Guide Arrows</string>
|
|
<Color3 name="TextColor3">4279970357</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="ScreenGui" referent="RBX35">
|
|
<Properties>
|
|
<string name="Name">StampGUI</string>
|
|
</Properties>
|
|
<Item class="Frame" referent="RBX36">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">InsertPanel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.200000003</XS>
|
|
<XO>2</XO>
|
|
<YS>0.100000001</YS>
|
|
<YO>24</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.600000024</XS>
|
|
<XO>-20</XO>
|
|
<YS>0.639999986</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">3</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="Frame" referent="RBX37">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">ItemsFrame</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.239999995</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0850000009</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.540000021</XS>
|
|
<XO>0</XO>
|
|
<YS>0.800000012</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="Frame" referent="RBX38">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4294112243</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">InsertAssetButtonExample</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>128</XO>
|
|
<YS>0</YS>
|
|
<YO>64</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>64</XO>
|
|
<YS>0</YS>
|
|
<YO>64</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextButton" referent="RBX39">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4282861383</Color3>
|
|
<float name="BackgroundTransparency">0.100000001</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">0</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">Button</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.0250000004</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0250000004</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0.949999988</XS>
|
|
<XO>0</XO>
|
|
<YS>0.949999988</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4279970357</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0.100000001</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX40">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><null></null></Content>
|
|
<string name="Name">ButtonImage</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-8</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>16</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">2</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="IntValue" referent="RBX41">
|
|
<Properties>
|
|
<string name="Name">AssetId</string>
|
|
<int name="Value">209411115</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="StringValue" referent="RBX42">
|
|
<Properties>
|
|
<string name="Name">AssetName</string>
|
|
<string name="Value">Roof - Outer Corner</string>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ImageLabel" referent="RBX43">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4278190080</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54140547</url></Content>
|
|
<string name="Name">ConfigIcon</string>
|
|
<UDim2 name="Position">
|
|
<XS>1</XS>
|
|
<XO>-23</XO>
|
|
<YS>1</YS>
|
|
<YO>-24</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>16</XO>
|
|
<YS>0</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX44">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">CancelButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>1</XS>
|
|
<XO>-32</XO>
|
|
<YS>0</YS>
|
|
<YO>-2</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>34</XO>
|
|
<YS>0</YS>
|
|
<YO>34</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">1</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX45">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54135717</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-2</XO>
|
|
<YS>0</YS>
|
|
<YO>-2</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>16</XO>
|
|
<YS>0</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX46">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">SelectSetButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0.200000003</XS>
|
|
<XO>0</XO>
|
|
<YS>0.100000001</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">1</token>
|
|
<string name="Text">Select Set</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX47">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">PagingControls</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.239999995</XS>
|
|
<XO>0</XO>
|
|
<YS>0.899999976</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.540000021</XS>
|
|
<XO>0</XO>
|
|
<YS>0.100000001</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextButton" referent="RBX48">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">PreviousPageButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.5</XS>
|
|
<XO>-95</XO>
|
|
<YS>0.5</YS>
|
|
<YO>-20</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>60</XO>
|
|
<YS>0</YS>
|
|
<YO>40</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX49">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54138586</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>8</XO>
|
|
<YS>0</YS>
|
|
<YO>-1</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>18</XO>
|
|
<YS>0</YS>
|
|
<YO>18</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX50">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4284874854</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<string name="Name">PageText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.5</XS>
|
|
<XO>-30</XO>
|
|
<YS>0.5</YS>
|
|
<YO>-20</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>60</XO>
|
|
<YS>0</YS>
|
|
<YO>40</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">1 / 3</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX51">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">NextPageButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.5</XS>
|
|
<XO>35</XO>
|
|
<YS>0.5</YS>
|
|
<YO>-20</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>60</XO>
|
|
<YS>0</YS>
|
|
<YO>40</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX52">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54138563</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>10</XO>
|
|
<YS>0</YS>
|
|
<YO>-1</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>18</XO>
|
|
<YS>0</YS>
|
|
<YO>18</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX53">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4294901862</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">Sets</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>5</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.230000004</XS>
|
|
<XO>0</XO>
|
|
<YS>1</YS>
|
|
<YO>-5</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="Frame" referent="RBX54">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4294967295</Color3>
|
|
<float name="BackgroundTransparency">0.699999988</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">Line</string>
|
|
<UDim2 name="Position">
|
|
<XS>1</XS>
|
|
<XO>-3</XO>
|
|
<YS>0.0599999987</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>3</XO>
|
|
<YS>0.899999976</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX55">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<string name="Name">SetsHeader</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>47</XO>
|
|
<YS>0</YS>
|
|
<YO>24</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Sets</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX56">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4291559577</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">SetsLists</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0599999987</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>-6</XO>
|
|
<YS>0.939999998</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextButton" referent="RBX57">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">false</bool>
|
|
<Color3 name="BackgroundColor3">4294967295</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">1</token>
|
|
<token name="FontSize">6</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">SetButtonExample</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>5</XO>
|
|
<YS>0</YS>
|
|
<YO>18</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>-5</XO>
|
|
<YS>0</YS>
|
|
<YO>18</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<string name="Text">House Decorations</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX58">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4284874803</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">ItemPreview</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.790000021</XS>
|
|
<XO>0</XO>
|
|
<YS>0.0850000009</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0.209999993</XS>
|
|
<XO>0</XO>
|
|
<YS>0.899999976</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX59">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4278190080</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><null></null></Content>
|
|
<string name="Name">LargePreview</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>170</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">3</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX60">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4286578816</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">TextPanel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0.449999988</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0.550000012</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextLabel" referent="RBX61">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4291624857</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<string name="Name">RolloverText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Window - Diagonal</string>
|
|
<Color3 name="TextColor3">4294112243</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX62">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">ConfigureText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>1</YS>
|
|
<YO>-48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextLabel" referent="RBX63">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4294901862</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">Configure</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Configure:</string>
|
|
<Color3 name="TextColor3">4294112243</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX64">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">1</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">Configure1</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Speed</string>
|
|
<Color3 name="TextColor3">4294112243</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX65">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">1</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">Configure2</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>28</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Damage</string>
|
|
<Color3 name="TextColor3">4294112243</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX66">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">1</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">Configure3</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>42</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Delay</string>
|
|
<Color3 name="TextColor3">4294112243</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX67">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">StamperPanel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.5</XS>
|
|
<XO>-175</XO>
|
|
<YS>1</YS>
|
|
<YO>-135</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>350</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">3</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">2</int>
|
|
</Properties>
|
|
<Item class="TextButton" referent="RBX68">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">MinimizeButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>1</XS>
|
|
<XO>-32</XO>
|
|
<YS>0</YS>
|
|
<YO>-2</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>34</XO>
|
|
<YS>0</YS>
|
|
<YO>34</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">1</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">3</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX69">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54932670</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-3</XO>
|
|
<YS>0</YS>
|
|
<YO>-4</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>16</XO>
|
|
<YS>0</YS>
|
|
<YO>20</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX70">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">StamperButtons</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>1</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="Frame" referent="RBX71">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">RecentFrame</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>103</XO>
|
|
<YS>0</YS>
|
|
<YO>-6</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>192</XO>
|
|
<YS>0</YS>
|
|
<YO>44</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">3</int>
|
|
</Properties>
|
|
<Item class="TextButton" referent="RBX72">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4282861383</Color3>
|
|
<float name="BackgroundTransparency">0.100000001</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">0</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">Button1</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>-2</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>48</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0.100000001</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">0</token>
|
|
<token name="TextYAlignment">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX73">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://gametest.roblox.com/Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=209434543</url></Content>
|
|
<string name="Name">ButtonImage</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-8</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>16</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">5</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX74">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">ShortcutText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>7</XO>
|
|
<YS>0</YS>
|
|
<YO>12</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">F</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">8</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX75">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4282861383</Color3>
|
|
<float name="BackgroundTransparency">0.100000001</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">0</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">Button2</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>48</XO>
|
|
<YS>0</YS>
|
|
<YO>-2</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>48</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4279970357</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0.100000001</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX76">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://gametest.roblox.com/Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=209434543</url></Content>
|
|
<string name="Name">ButtonImage</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-8</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>16</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">5</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX77">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">ShortcutText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>7</XO>
|
|
<YS>0</YS>
|
|
<YO>12</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">G</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">8</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX78">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4282861383</Color3>
|
|
<float name="BackgroundTransparency">0.100000001</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">0</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">Button3</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>95</XO>
|
|
<YS>0</YS>
|
|
<YO>-3</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>48</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4279970357</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0.100000001</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX79">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://gametest.roblox.com/Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=209434543</url></Content>
|
|
<string name="Name">ButtonImage</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-8</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>16</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">5</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX80">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">ShortcutText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>7</XO>
|
|
<YS>0</YS>
|
|
<YO>12</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">H</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">8</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX81">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4282861383</Color3>
|
|
<float name="BackgroundTransparency">0.100000001</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">0</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">Button4</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>142</XO>
|
|
<YS>0</YS>
|
|
<YO>-3</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>48</XO>
|
|
<YS>0</YS>
|
|
<YO>48</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4279970357</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0.100000001</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX82">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://gametest.roblox.com/Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=209434543</url></Content>
|
|
<string name="Name">ButtonImage</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-8</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>16</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">5</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX83">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">ShortcutText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>7</XO>
|
|
<YS>0</YS>
|
|
<YO>12</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">J</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">8</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX84">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">CloneButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>-6</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>45</XO>
|
|
<YS>0</YS>
|
|
<YO>45</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">3</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX85">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=51641555</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-7</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>14</XO>
|
|
<YS>1</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX86">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">CloneShortcut</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>8</XO>
|
|
<YS>0</YS>
|
|
<YO>12</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">E</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">5</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX87">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">PartsButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>45</XO>
|
|
<YS>0</YS>
|
|
<YO>-6</YO>
|
|
</UDim2>
|
|
<bool name="Selected">true</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>45</XO>
|
|
<YS>0</YS>
|
|
<YO>45</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">3</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX88">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54966682</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-7</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>14</XO>
|
|
<YS>1</YS>
|
|
<YO>14</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextLabel" referent="RBX89">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">PartsShortcut</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-7</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>8</XO>
|
|
<YS>0</YS>
|
|
<YO>12</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Q</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">0</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">5</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX90">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">ClonePanel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>80</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">2</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextLabel" referent="RBX91">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">5</token>
|
|
<string name="Name">ClonePanelText</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-6</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>12</XO>
|
|
<YS>1</YS>
|
|
<YO>16</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Click on a part to clone it</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">true</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX92">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">7</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">RestoreButton</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-25</XO>
|
|
<YS>0</YS>
|
|
<YO>-20</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>50</XO>
|
|
<YS>0</YS>
|
|
<YO>25</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">1</token>
|
|
<string name="Text"></string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">3</int>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX93">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">0</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><url>http://www.roblox.com/asset?id=54933540</url></Content>
|
|
<string name="Name">ImageLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>-4</XO>
|
|
<YS>0</YS>
|
|
<YO>-4</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>8</XO>
|
|
<YS>1</YS>
|
|
<YO>8</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">4</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX94">
|
|
<Properties>
|
|
<bool name="Disabled">false</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">StampGuiController</string>
|
|
<ProtectedString name="Source">local stampGui = script.Parent
|
|
local insertPanel = stampGui.InsertPanel
|
|
local stamperPanel = stampGui.StamperPanel
|
|
|
|
local itemPreview = insertPanel.ItemPreview
|
|
|
|
function handleResize()
|
|
	wait() -- neccessary to insure heartbeat happened
|
|
	itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
|
|
	itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
|
|
	itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
|
|
	itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
|
|
end
|
|
|
|
stampGui.Changed:connect(function(prop)
|
|
	if prop == "AbsoluteSize" then
|
|
		handleResize()
|
|
	end
|
|
end)
|
|
|
|
handleResize()</ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="Frame" referent="RBX95">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">LoadDialog</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.5</XS>
|
|
<XO>-175</XO>
|
|
<YS>0.5</YS>
|
|
<YO>-25</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>350</XO>
|
|
<YS>0</YS>
|
|
<YO>50</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">1</token>
|
|
<token name="Style">3</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="TextLabel" referent="RBX96">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">2</token>
|
|
<token name="FontSize">8</token>
|
|
<string name="Name">LoadLabel</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>-8</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>155</XO>
|
|
<YS>0.5</YS>
|
|
<YO>36</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<string name="Text">Loading...</string>
|
|
<Color3 name="TextColor3">4294506744</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
<Item class="SelectionBox" referent="RBX97">
|
|
<Properties>
|
|
<Ref name="Adornee">null</Ref>
|
|
<int name="Color">21</int>
|
|
<string name="Name">ErrorBox</string>
|
|
<float name="Transparency">0</float>
|
|
<bool name="Visible">false</bool>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX98">
|
|
<Properties>
|
|
<bool name="Disabled">false</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">GuiScript</string>
|
|
<ProtectedString name="Source">-- This script is responsible for working the gui
|
|
|
|
-- basic functions
|
|
function waitForChild(instance, name)
|
|
	while not instance:findFirstChild(name) do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForProperty(instance, name)
|
|
	while not instance[name] do
|
|
		instance.Changed:wait()
|
|
	end
|
|
end
|
|
|
|
|
|
-- Locals
|
|
local Tool = script.Parent
|
|
|
|
waitForChild(Tool, "LuaGlobalVariables")
|
|
local variables = Tool.LuaGlobalVariables
|
|
waitForChild(variables, "InsertAsset")
|
|
local insertAsset = variables.InsertAsset
|
|
waitForChild(variables, "SwitchMode")
|
|
local switchMode = variables.SwitchMode
|
|
waitForChild(variables, "ShowAdminCategories")
|
|
local showAdminCategories = variables.ShowAdminCategories
|
|
|
|
waitForChild(variables, "ReloadCurrentAsset")
|
|
waitForChild(variables,"userIDs")
|
|
|
|
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=42163425")
|
|
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=42563487")
|
|
|
|
local BaseUrl = game:GetService("ContentProvider").BaseUrl
|
|
|
|
local buttonHeight = 64
|
|
local buttonWidth = buttonHeight
|
|
|
|
local waypointShowing = false
|
|
local showingPartPicker = true
|
|
local firstEquip = true
|
|
|
|
local Window
|
|
local Data
|
|
local loading = false
|
|
|
|
local startTime = 0
|
|
|
|
local SetCache = {}
|
|
|
|
local lastEnter = nil
|
|
|
|
-- For Restricting Stamper Tool
|
|
local buildingPlate
|
|
local partModel
|
|
|
|
-- wait for all of our set ids to load
|
|
local userIdsForStamperParts = variables.userIDs -- 7502714 This is UsabilityMan (on gametest)
|
|
|
|
function giveNewUserId(id)
|
|
	local newUserId = Instance.new("IntValue")
|
|
	newUserId.Name = "userID"
|
|
	newUserId.Value = id
|
|
	newUserId.Parent = userIdsForStamperParts
|
|
	userIdsForStamperParts.Value = userIdsForStamperParts.Value + 1
|
|
end
|
|
|
|
BaseUrl = BaseUrl:lower()
|
|
|
|
local isRestricted = Instance.new("BoolValue")
|
|
isRestricted.Name = "IsRestricted"
|
|
isRestricted.Value = false
|
|
|
|
function isLocalWTRB()
|
|
	waitForChild(game,"StarterGui")
|
|
	if game.StarterGui:FindFirstChild("VersionGui") then
|
|
		if game.StarterGui.VersionGui:FindFirstChild("VersionText", true) then
|
|
			return true
|
|
		end
|
|
	end
|
|
	return false
|
|
end
|
|
|
|
waitForProperty(game,"PlaceId")
|
|
if game.PlaceId == 41324860 or isLocalWTRB() then
|
|
	isRestricted.Value = true
|
|
end
|
|
isRestricted.Parent = variables
|
|
|
|
giveNewUserId(18881789)
|
|
giveNewUserId(18881808)
|
|
if not isRestricted.Value then
|
|
	giveNewUserId(18881829)
|
|
	giveNewUserId(18881853)
|
|
	giveNewUserId(18881866)
|
|
else
|
|
	giveNewUserId(2409156)
|
|
	giveNewUserId(19238067)
|
|
	giveNewUserId(19238114)
|
|
end
|
|
|
|
while #userIdsForStamperParts:GetChildren() < userIdsForStamperParts.Value do userIdsForStamperParts.ChildAdded:wait() end
|
|
userIdsForStamperParts = userIdsForStamperParts:GetChildren()
|
|
|
|
local useAssetVersionId = false
|
|
local LargeThumbnailUrl
|
|
local SmallThumbnailUrl
|
|
|
|
local InsertRows = 0
|
|
local InsertColumns = 0
|
|
local insertButtons = {}
|
|
|
|
local CancelDuringLoad
|
|
|
|
local prevPart = {AssetNameValue = "",AssetIdValue = 0 ,InsertFrameButtonImage = ""}
|
|
local recentPartStack = {}
|
|
|
|
-- Connection Managers
|
|
local guiChangedCon = nil
|
|
local cloneButtonCon = nil
|
|
local partListClickCon = nil
|
|
local itemFrameChangedCon = nil
|
|
local setsNextPageCon = nil
|
|
local setsPrevPageCon = nil
|
|
local insertPanelCloseCon = nil
|
|
local minimizeCon = nil
|
|
local restoreCon = nil
|
|
local setButtonCons = {}
|
|
local insertButtonCons = {}
|
|
local recentPartStackCons = {}
|
|
|
|
local Mouse = nil
|
|
local currSetPage = 1
|
|
|
|
local mode = 0 -- 0 = main dialog, 1 = stamper, 2 = eyedropper
|
|
|
|
waitForChild(script.Parent,"StampGUI")
|
|
local stamperGui = script.Parent.StampGUI
|
|
waitForChild(stamperGui,"InsertPanel")
|
|
waitForChild(stamperGui.InsertPanel, "CancelButton")
|
|
local currStampGui = nil
|
|
|
|
local maxRecentParts = 4
|
|
for i = 1, maxRecentParts do
|
|
	recentPartStack[i] = {AssetNameValue,AssetIdValue,InsertFrameButtonImage}
|
|
	recentPartStack[i].AssetNameValue = ""
|
|
	recentPartStack[i].AssetIdValue = ""
|
|
	recentPartStack[i].InsertFrameButtonImage = ""
|
|
end
|
|
----------------------------------------------------------------------------------------
|
|
|
|
|
|
-- functions
|
|
function showBaseplateGuideArrows()
|
|
	playerCharacter = Tool.Parent
|
|
	if playerCharacter:FindFirstChild("Humanoid") and not playerCharacter:FindFirstChild("BasePlateGuide") then
|
|
		newGuide = Tool.BasePlateGuide:Clone()
|
|
		newGuide.Parent = playerCharacter
|
|
		newGuide.Disabled = false
|
|
	end
|
|
end
|
|
|
|
function setAssetUrls()
|
|
	if useAssetVersionId then
|
|
		LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
|
|
		SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
|
|
	else
|
|
		LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
|
|
		SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
|
|
	end
|
|
end
|
|
|
|
function signalSwitchMode(mode)
|
|
	switchMode.Mode.Value = mode
|
|
	switchMode.Value = true
|
|
end
|
|
|
|
function goToClone()
|
|
	cancelLoadingWindow()
|
|
	closeInsertPanel()
|
|
	cancelAssetPlacement()
|
|
|
|
	mode = 2
|
|
	--signalStamperScript("",0,"","",false)
|
|
	signalSwitchMode("Clone")
|
|
|
|
	currStampGui.StamperPanel.StamperButtons.ClonePanel.Visible = true
|
|
	currStampGui.StamperPanel.StamperButtons.CloneButton.Selected = true
|
|
	if currStampGui.Parent ~= nil then
|
|
		currStampGui.StamperPanel.StamperButtons.ClonePanel:TweenPosition(UDim2.new(0, -88, 0, -8),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.35,true)
|
|
		delay(0.3,function() currStampGui.StamperPanel.StamperButtons.ClonePanel.ClonePanelText.Visible = true end)
|
|
	end
|
|
end
|
|
|
|
function goToStamp()
|
|
	mode = 1
|
|
	cancelLoadingWindow()
|
|
	closeInsertPanel()
|
|
	closeClonePanel()
|
|
end
|
|
|
|
function goToInsertPanel()
|
|
	cancelLoadingWindow()
|
|
	closeClonePanel()
|
|
	pcall(function() currStampGui.InsertPanel.CancelButton.Modal = true end)
|
|
	currStampGui.StamperPanel.StamperButtons.PartsButton.Selected = true
|
|
|
|
	if not showingPartPicker then
|
|
		showingPartPicker = true
|
|
		if currStampGui.Parent ~= nil then
|
|
			currStampGui.InsertPanel:TweenPosition(UDim2.new(0.2, 2, 0.1, 24),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.35,true)
|
|
		end
|
|
	else
|
|
		closeInsertPanel()
|
|
		reloadCurrentAsset()
|
|
	end
|
|
end
|
|
|
|
function closeInsertPanel()
|
|
	pcall(function() currStampGui.InsertPanel.CancelButton.Modal = false end)
|
|
	currStampGui.StamperPanel.StamperButtons.PartsButton.Selected = false
|
|
|
|
	showingPartPicker = false
|
|
	if currStampGui.Parent ~= nil then
|
|
		currStampGui.InsertPanel:TweenPosition(UDim2.new(0.2, 2, 1, 24),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.35,true)
|
|
	end
|
|
end
|
|
|
|
function closeClonePanel()
|
|
	currStampGui.StamperPanel.StamperButtons.ClonePanel.ClonePanelText.Visible = false
|
|
	currStampGui.StamperPanel.StamperButtons.CloneButton.Selected = false
|
|
	if currStampGui.Parent ~= nil then
|
|
		currStampGui.StamperPanel.StamperButtons.ClonePanel:TweenPosition(UDim2.new(0, 0, 0, -8),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.35,true)
|
|
		delay(0.3,function() currStampGui.StamperPanel.StamperButtons.ClonePanel.Visible = false end)
|
|
	end
|
|
end
|
|
|
|
function cancelAssetPlacement()
|
|
	gInitial90DegreeRotations = 0
|
|
	Data.Stamp.Cancelled = true
|
|
	Data.Stamp.Dragger = nil
|
|
	if Data.Stamp.Model then
|
|
		Data.Stamp.Model:Remove()
|
|
		Data.Stamp.Model = nil
|
|
	end
|
|
	if Data.Stamp.CurrentParts then
|
|
		for index, object in pairs(Data.Stamp.CurrentParts) do
|
|
			object:Remove()
|
|
		end
|
|
		Data.Stamp.CurrentParts = nil
|
|
	end
|
|
|
|
	if Mouse then
|
|
		Mouse.Icon ="rbxasset://textures\\ArrowCursor.png"
|
|
	end
|
|
	game.JointsService:ClearJoinAfterMoveJoints()
|
|
|
|
end
|
|
|
|
function hint(label)
|
|
|
|
	-- Pass in a string, it shows a top hint. (Replaces previous hint, if exists)
|
|
	_player = game.Players:GetPlayerFromCharacter(Tool.Parent)
|
|
	if(_player.PlayerGui:FindFirstChild("topHint")~=nil) then
|
|
		local topHint = _player.PlayerGui.topHint
|
|
		topHint.Add.Label.Value = label
|
|
		topHint.Add.Width.Value = 3 -- widest width
|
|
		topHint.Add.Time.Value = 5
|
|
		topHint.Add.Disabled = true
|
|
		topHint.Add.Disabled = false
|
|
	end
|
|
|
|
end
|
|
|
|
function getPlayer()
|
|
	return game.Players:GetPlayerFromCharacter(script.Parent.Parent)
|
|
end
|
|
|
|
function getHumanoid()
|
|
	local player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
|
|
	if player then
|
|
		waitForProperty(player,"Character")
|
|
		waitForChild(player.Character,"Humanoid")
|
|
		return player.Character.Humanoid
|
|
	else
|
|
		return nil
|
|
	end
|
|
end
|
|
|
|
function buildSetButton(name, setId, setImageId, i, count)
|
|
|
|
	local button = currStampGui.InsertPanel.Sets.SetsLists.SetButtonExample:Clone()
|
|
	button.Text = name
|
|
	button.Name = "SetButton"
|
|
	button.Visible = true
|
|
|
|
	local setValue = Instance.new("IntValue")
|
|
	setValue.Name = "SetId"
|
|
	setValue.Value = setId
|
|
	setValue.Parent = button
|
|
|
|
	local setName = Instance.new("StringValue")
|
|
	setName.Name = "SetName"
|
|
	setName.Value = name
|
|
	setName.Parent = button
|
|
|
|
	return button
|
|
end
|
|
|
|
|
|
function previousSetPage()
|
|
	local newIndex = math.max(0, Data.Category[Data.CurrentCategory].Index - (InsertRows * InsertColumns))
|
|
	setSetIndex(newIndex)
|
|
end
|
|
|
|
|
|
function nextSetPage()
|
|
	local newIndex = math.max(0, Data.Category[Data.CurrentCategory].Index + (InsertRows * InsertColumns))
|
|
	setSetIndex(newIndex)
|
|
end
|
|
|
|
function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
|
|
	if visible then
|
|
		insertFrame.AssetName.Value = name
|
|
		insertFrame.AssetId.Value = assetId
|
|
		local newImageUrl = SmallThumbnailUrl .. assetId
|
|
		if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
|
|
			delay(0,function()
|
|
				game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
|
|
				insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
|
|
			end)
|
|
		end
|
|
		table.insert(insertButtonCons,
|
|
			insertFrame.Button.MouseButton1Click:connect(function()
|
|
				beginInsertAssetGui(insertFrame.AssetName.Value, insertFrame.AssetId.Value, insertFrame.Button.ButtonImage.Image, 1)
|
|
			end)
|
|
		)
|
|
		insertFrame.Visible = true
|
|
	else
|
|
		insertFrame.Visible = false
|
|
	end
|
|
end
|
|
|
|
function setSetIndex(dataOffset)
|
|
|
|
	Data.Category[Data.CurrentCategory].Index = dataOffset
|
|
|
|
	InsertRows = math.floor(currStampGui.InsertPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
|
|
	InsertColumns = math.floor(currStampGui.InsertPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
|
|
|
|
	local PageSize = InsertRows * InsertColumns
|
|
	local contents = Data.Category[Data.CurrentCategory].Contents
|
|
	if contents then
|
|
		
|
|
		local numOfPages = math.ceil((#contents)/(PageSize))
|
|
		local currPage = math.ceil((dataOffset/PageSize) + 1)
|
|
		currStampGui.InsertPanel.PagingControls.PageText.Text = tostring(currPage) .. "/" .. tostring(numOfPages)
|
|
		currStampGui.InsertPanel.PagingControls.PageText.Visible = (numOfPages > 1)
|
|
|
|
currStampGui.InsertPanel.PagingControls.PreviousPageButton.Visible = (numOfPages > 1) and dataOffset > 1
|
|
		currStampGui.InsertPanel.PagingControls.NextPageButton.Visible = (numOfPages > 1) and ((dataOffset - 1) + PageSize) < (#contents)
|
|
|
|
		-- remove our buttons and their connections
|
|
		for i = 1, #insertButtons do
|
|
			insertButtons[i]:remove()
|
|
		end
|
|
		for i = 1, #insertButtonCons do
|
|
			pcall(function() insertButtonCons[i]:disconnect() end)
|
|
		end
|
|
|
|
		insertButtonCons = {}
|
|
		insertButtons = {}
|
|
		local arrayPosition = 1
|
|
		for y = 1, InsertRows do
|
|
			for x = 1, InsertColumns do
|
|
				local buttonPosition = UDim2.new(0,(buttonWidth)*(x-1),0, (buttonHeight)*(y-1))
|
|
|
|
				local buttonCon
|
|
				insertButtons[arrayPosition], buttonCon = buildInsertButton(buttonPosition)
|
|
				table.insert(insertButtonCons,buttonCon)
|
|
				insertButtons[arrayPosition].Parent = currStampGui.InsertPanel.ItemsFrame
|
|
				arrayPosition = arrayPosition + 1
|
|
			end
|
|
		end
|
|
|
|
		Data.InsertButtons = insertButtons
|
|
|
|
		for index = 1, PageSize do
|
|
			if insertButtons[index] then
|
|
				if contents[index + dataOffset] then
|
|
					local assetId
|
|
					if useAssetVersionId then
|
|
						assetId = contents[index + dataOffset].AssetVersionId
|
|
					else
|
|
						assetId = contents[index + dataOffset].AssetId
|
|
					end
|
|
					setInsertButtonImageBehavior(insertButtons[index], true, contents[index + dataOffset].Name, assetId)
|
|
				else
|
|
					setInsertButtonImageBehavior(insertButtons[index], false)
|
|
				end
|
|
			end
|
|
		end
|
|
	else
|
|
		currStampGui.InsertPanel.PagingControls.PreviousPageButton.Visible = false
|
|
		currStampGui.InsertPanel.PagingControls.NextPageButton.Visible = false
|
|
	end
|
|
|
|
end
|
|
|
|
function moveLoadingLeft()
|
|
	if (tick() - startTime > 5) and (currStampGui.Parent ~= nil) then
|
|
		loading = false
|
|
		cancelAssetPlacement()
|
|
		goToInsertPanel()
|
|
	end
|
|
	if loading then
|
|
		currStampGui.LoadDialog.LoadLabel:TweenPosition(UDim2.new(0, 0, 0, -8),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.7,true,function() moveLoadingRight() end)
|
|
	end
|
|
end
|
|
|
|
function moveLoadingRight()
|
|
	if (tick() - startTime > 5) and (currStampGui.Parent ~= nil) then
|
|
		loading = false
|
|
		cancelAssetPlacement()
|
|
		goToInsertPanel()
|
|
	end
|
|
	if loading then
|
|
		currStampGui.LoadDialog.LoadLabel:TweenPosition(UDim2.new(0, 180, 0, -8),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.7,true,function() moveLoadingLeft() end)
|
|
	end
|
|
end
|
|
|
|
function moveLoadingWindow()
|
|
	startTime = tick()
|
|
	currStampGui.LoadDialog.Visible = true
|
|
	loading = true
|
|
	moveLoadingRight()
|
|
end
|
|
|
|
function cancelLoadingWindow()
|
|
	currStampGui.LoadDialog.Visible = false
|
|
	loading = false
|
|
end
|
|
|
|
|
|
function selectCategoryPage(buttons, page)
|
|
|
|
	if buttons ~= Data.CurrentCategory then
|
|
		if Data.CurrentCategory then
|
|
			for key, button in pairs(Data.CurrentCategory) do
|
|
				button.Visible = false
|
|
			end
|
|
		end
|
|
|
|
		Data.CurrentCategory = buttons
|
|
		if Data.Category[Data.CurrentCategory] == nil then
|
|
			Data.Category[Data.CurrentCategory] = {}
|
|
			if #buttons > 0 then
|
|
				selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
|
|
			end
|
|
		else
|
|
			Data.Category[Data.CurrentCategory].Button = nil
|
|
			selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
|
|
		end
|
|
		if Data.Main.FrameHeight then
|
|
			if Data.Category[Data.CurrentCategory].SetIndex then
|
|
				layoutSetButtons(Data.Main.FrameHeight, Data.Category[Data.CurrentCategory].SetIndex)
|
|
			else
|
|
				layoutSetButtons(Data.Main.FrameHeight, 1)
|
|
			end
|
|
		end
|
|
	end
|
|
|
|
end
|
|
|
|
function selectSet(button, setName, setId, setIndex)
|
|
|
|
	if button and Data.Category[Data.CurrentCategory] ~= nil then
|
|
		if button ~= Data.Category[Data.CurrentCategory].Button then
|
|
			Data.Category[Data.CurrentCategory].Button = button
|
|
|
|
			if SetCache[setId] == nil then
|
|
				SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
|
|
			end
|
|
			Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
|
|
|
|
			Data.Category[Data.CurrentCategory].SetName = setName
|
|
			Data.Category[Data.CurrentCategory].SetId = setId
|
|
		end
|
|
		setSetIndex(setIndex)
|
|
	end
|
|
|
|
end
|
|
|
|
|
|
function selectCategory(button, category)
|
|
	selectCategoryPage(category, 0)
|
|
end
|
|
|
|
|
|
function processCategory(sets, setPanel)
|
|
	local setButtons = {}
|
|
	local numSkipped = 0
|
|
	for index, object in pairs(sets) do
|
|
		if not showAdminCategories.Value and object.Name == "Beta" then
|
|
			-- skip this if not an admin
|
|
			numSkipped = numSkipped + 1
|
|
		else
|
|
			setButtons[index - numSkipped] = buildSetButton(object.Name, object.CategoryId, object.ImageAssetId, index - numSkipped, #sets)
|
|
			setButtons[index - numSkipped].Parent = setPanel
|
|
		end
|
|
	end
|
|
	return setButtons
|
|
end
|
|
|
|
|
|
function setsNextPageClick(totalSetPages, gridSize)
|
|
	-- set our logic/gui correctly
|
|
	if currSetPage >= totalSetPages then return end
|
|
|
|
	currSetPage = currSetPage + 1
|
|
	currStampGui.InsertPanel.PagingControls.PageText.Text = tostring(currSetPage) .. "/" .. tostring(totalSetPages)
|
|
	if currSetPage == totalSetPages then
|
|
		currStampGui.InsertPanel.PagingControls.NextPageButton.Visible = false
|
|
		currStampGui.InsertPanel.PagingControls.PreviousPageButton.Visible = true
|
|
	else
|
|
		Window.Sets.PagingControls.NextPageButton.Visible = true
|
|
	end
|
|
	
|
|
	-- actually update the items
|
|
	makeCurrentSetsPageVisible(gridSize)
|
|
end
|
|
|
|
function setsPrevPageClick(totalSetPages, gridSize)
|
|
	-- set our logic/gui correctly
|
|
	if currSetPage <= 1 then return end
|
|
|
|
	currSetPage = currSetPage - 1
|
|
	currStampGui.InsertPanel.PagingControls.PageText.Text = tostring(currSetPage) .. "/" .. tostring(totalSetPages)
|
|
	if currSetPage == 1 then
|
|
		currStampGui.InsertPanel.PagingControls.NextPageButton.Visible = true
|
|
		currStampGui.InsertPanel.PagingControls.PreviousPageButton.Visible = false
|
|
	else
|
|
		currStampGui.InsertPanel.PagingControls.PreviousPageButton.Visible = true
|
|
	end
|
|
|
|
	-- actually update the items
|
|
	makeCurrentSetsPageVisible(gridSize)
|
|
end
|
|
|
|
function resetAllSetButtonSelection()
|
|
	local setButtons = Window.Sets.SetsLists:GetChildren()
|
|
	for i = 1, #setButtons do
|
|
		setButtons[i].Selected = false
|
|
		setButtons[i].BackgroundTransparency = 1
|
|
		setButtons[i].TextColor3 = Color3.new(1,1,1)
|
|
		setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
|
|
	end
|
|
end
|
|
|
|
function populateSetsFrame()
|
|
	local categories = #Data.UserCategoryButtons
|
|
	local robloxMaxCat = categories
|
|
	
|
|
	-- don't do anything until window is visible (otherwise we won't layout anything!)
|
|
	while Window.Sets.SetsLists.AbsoluteSize.X <= 0 do
|
|
		Window.Sets.SetsLists.Changed:wait()
|
|
	end
|
|
	while Window.Sets.SetsLists.SetButtonExample.AbsoluteSize.X <= 0 do
|
|
		Window.Sets.SetsLists.SetButtonExample.Changed:wait()
|
|
	end
|
|
|
|
	local totalColumns = math.floor(Window.Sets.SetsLists.AbsoluteSize.X/Window.Sets.SetsLists.SetButtonExample.AbsoluteSize.X)
|
|
	local totalRows = math.floor(Window.Sets.SetsLists.AbsoluteSize.Y/Window.Sets.SetsLists.SetButtonExample.AbsoluteSize.Y)
|
|
	
|
|
	local currRow = 0
|
|
	local buttonVisible = true
|
|
|
|
	local masterCategory = 1
|
|
	for i = 1, categories do
|
|
		local userCategory = masterCategory -- needed to maintain local scope for categories in event listeners below
|
|
		local button = Window.Sets.SetsLists.SetButtonExample:clone()
|
|
|
|
		button.Name = "Set" .. tostring(Data.UserCategoryButtons[userCategory].SetName.Value) .. "Button"
|
|
		button.Parent = Window.Sets.SetsLists
|
|
		button.Position = UDim2.new(0,5,0,currRow * button.AbsoluteSize.Y)
|
|
		button.Visible = buttonVisible
|
|
		button.Text = tostring(Data.UserCategoryButtons[userCategory].SetName.Value)
|
|
|
|
		if i == 1 then
|
|
			button.Selected = true
|
|
			button.BackgroundColor3 = Color3.new(0,204/255,0)
|
|
			button.TextColor3 = Color3.new(0,0,0)
|
|
			button.BackgroundTransparency = 0
|
|
		end
|
|
|
|
		button.MouseEnter:connect(function()
|
|
			if not button.Selected then
|
|
				button.BackgroundTransparency = 0
|
|
				button.TextColor3 = Color3.new(0,0,0)
|
|
			end
|
|
		end)
|
|
		button.MouseLeave:connect(function()
|
|
			if not button.Selected then
|
|
				button.BackgroundTransparency = 1
|
|
				button.TextColor3 = Color3.new(1,1,1)
|
|
			end
|
|
		end)
|
|
		setButtonCons[i] = button.MouseButton1Click:connect(function()
|
|
			resetAllSetButtonSelection()
|
|
			button.Selected = not button.Selected
|
|
			button.BackgroundColor3 = Color3.new(0,204/255,0)
|
|
			button.TextColor3 = Color3.new(0,0,0)
|
|
			button.BackgroundTransparency = 0
|
|
|
|
			selectSet(button, button.Text, Data.UserCategoryButtons[userCategory].SetId.Value, 0)
|
|
		end)
|
|
		
|
|
		masterCategory = masterCategory + 1
|
|
|
|
		currRow = currRow + 1
|
|
	end
|
|
	
|
|
	-- don't use example button as the first set!
|
|
	local example = currStampGui.InsertPanel.Sets.SetsLists.SetButtonExample
|
|
	currStampGui.InsertPanel.Sets.SetsLists.SetButtonExample.Parent = nil
|
|
	local buttons = currStampGui.InsertPanel.Sets.SetsLists:GetChildren()
|
|
	example.Parent = currStampGui.InsertPanel.Sets.SetsLists
|
|
|
|
	-- set first category as loaded for default
|
|
	selectSet(buttons[1], buttons[1].Text, Data.UserCategoryButtons[1].SetId.Value, 0)
|
|
	selectCategory(buttons[1], Data.UserCategoryButtons)
|
|
end
|
|
|
|
|
|
function layoutSetButtons(frameHeight, setIndex)
|
|
	Data.Main.FrameHeight = frameHeight
|
|
	Data.Main.InsertSets = math.floor(frameHeight / (height*2))
|
|
	if #Data.CurrentCategory > Data.Main.InsertSets then
|
|
		--Steal one entry since we have too many things
|
|
		Data.Main.InsertSets = Data.Main.InsertSets - 1
|
|
	end
|
|
|
|
	Data.Category[Data.CurrentCategory].SetIndex = setIndex
|
|
end
|
|
|
|
|
|
function showLargePreview(insertButton)
|
|
	if insertButton:FindFirstChild("AssetId") then
|
|
		delay(0,function()
|
|
			game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
|
|
			currStampGui.InsertPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
|
|
		end)
|
|
	end
|
|
	if insertButton:FindFirstChild("AssetName") then
|
|
		currStampGui.InsertPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
|
|
	end
|
|
end
|
|
|
|
|
|
function buildInsertButton(buttonPosition)
|
|
	local insertButton = currStampGui.InsertPanel.ItemsFrame.InsertAssetButtonExample:clone()
|
|
	insertButton.Position = buttonPosition
|
|
	insertButton.Name = "InsertAssetButton"
|
|
	insertButton.Visible = true
|
|
|
|
	local mouseEnterCon = insertButton.MouseEnter:connect(function()
|
|
		lastEnter = insertButton
|
|
		delay(0.1,function()
|
|
			if lastEnter == insertButton then
|
|
				showLargePreview(insertButton)
|
|
			end
|
|
		end)
|
|
	end)
|
|
	return insertButton, mouseEnterCon
|
|
end
|
|
|
|
function minimizeStamperPanel()
|
|
	currStampGui.StamperPanel.StamperButtons.Visible = false
|
|
	currStampGui.StamperPanel.MinimizeButton.Visible = false
|
|
	if currStampGui.Parent ~= nil then
|
|
		currStampGui.StamperPanel:TweenSizeAndPosition(UDim2.new(0,0,0,0), UDim2.new(0.5,0,1,-92),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.5,true)
|
|
		delay(0.5,function()
|
|
			currStampGui.StamperPanel.RestoreButton.Visible = true
|
|
		end)
|
|
	end
|
|
end
|
|
|
|
function restoreStamperPanel()
|
|
	currStampGui.StamperPanel.RestoreButton.Visible = false
|
|
	if currStampGui.Parent ~= nil then
|
|
		currStampGui.StamperPanel:TweenSizeAndPosition(UDim2.new(0,350,0,48), UDim2.new(0.5,-175,1,-135), Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,0.5,true)
|
|
		delay(0.5,function()
|
|
			currStampGui.StamperPanel.StamperButtons.Visible = true
|
|
			currStampGui.StamperPanel.MinimizeButton.Visible = true
|
|
		end)
|
|
	end
|
|
end
|
|
|
|
function setUpStamperGui()
|
|
	pcall(function() currStampGui.InsertPanel.CancelButton.Modal = true end)
|
|
	Window.Sets = currStampGui.InsertPanel.Sets
|
|
|
|
	cloneButtonCon = currStampGui.StamperPanel.StamperButtons.CloneButton.MouseButton1Click:connect(goToClone)
|
|
	partListClickCon = currStampGui.StamperPanel.StamperButtons.PartsButton.MouseButton1Click:connect(goToInsertPanel)
|
|
|
|
	Data.Main = {}
|
|
	Data.Category = {}
|
|
	Data.Stamp = {}
|
|
|
|
	Data.BaseCategoryButtons = {}
|
|
	local userData = {}
|
|
	for id = 1, #userIdsForStamperParts do
|
|
		local newUserData = game:GetService("InsertService"):GetUserCategories(userIdsForStamperParts[id].Value)
|
|
		if newUserData and #newUserData > 2 then
|
|
			-- start at #3 to skip over My Decals and My Models for each account
|
|
			for category = 3, #newUserData do
|
|
				if newUserData[category].Name == "High Scalability" then
|
|
					table.insert(userData,1,newUserData[category])
|
|
				else
|
|
					table.insert(userData, newUserData[category])
|
|
				end
|
|
			end
|
|
		end
|
|
	end
|
|
	
|
|
	if userData then
|
|
		Data.UserCategoryButtons = processCategory(userData, setPanel)
|
|
	end
|
|
|
|
	guiChangedCon = currStampGui.Changed:connect(function(prop)
|
|
		if prop == "AbsoluteSize" then
|
|
			wait()
|
|
			setSetIndex(0)
|
|
		end
|
|
	end)
|
|
|
|
	InsertRows = math.floor(currStampGui.InsertPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
|
|
	InsertColumns = math.floor(currStampGui.InsertPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
|
|
|
|
	populateSetsFrame()
|
|
|
|
	setsPrevPageCon = currStampGui.InsertPanel.PagingControls.PreviousPageButton.MouseButton1Click:connect(function() previousSetPage() end)
|
|
	setsNextPageCon = currStampGui.InsertPanel.PagingControls.NextPageButton.MouseButton1Click:connect(function() nextSetPage() end)
|
|
|
|
	insertPanelCloseCon = currStampGui.InsertPanel.CancelButton.MouseButton1Click:connect(function()
|
|
		closeInsertPanel()
|
|
		closeClonePanel()
|
|
		reloadCurrentAsset()
|
|
	end)
|
|
|
|
	minimizeCon = currStampGui.StamperPanel.MinimizeButton.MouseButton1Click:connect(function() minimizeStamperPanel() end)
|
|
	restoreCon = currStampGui.StamperPanel.RestoreButton.MouseButton1Click:connect(function() restoreStamperPanel() end)
|
|
end
|
|
|
|
-- signal to scripts we are ready to start manipulating objects
|
|
function signalStamperScript(assetName, assetId, image, stampMode)
|
|
	insertAsset.AssetName.Value = assetName
|
|
	insertAsset.AssetId.Value = assetId
|
|
	insertAsset.Image.Value = image
|
|
	insertAsset.StampMode.Value = stampMode
|
|
	insertAsset.Updated.Value = true
|
|
end
|
|
|
|
function reloadCurrentAsset()
|
|
	variables.ReloadCurrentAsset.Value = true
|
|
end
|
|
|
|
|
|
function beginInsertAssetGui(assetName, assetId, image, stampMode)
|
|
	Data.Stamp.StampMode = stampMode
|
|
	closeInsertPanel()
|
|
	signalStamperScript("",0,"","",false)
|
|
	moveLoadingWindow()
|
|
	cancelAssetPlacement()
|
|
	signalStamperScript(assetName, assetId, image, stampMode)
|
|
end
|
|
|
|
|
|
function cancelAssetLoad()
|
|
	Data.Loading.Cancelled = true
|
|
	insertComplete()
|
|
	gInitial90DegreeRotations = 0
|
|
end
|
|
|
|
function inBounds2(part)
|
|
	-- part must have a position property
|
|
	local xOne= buildingPlate.Position.x + buildingPlate.Size.x/2
|
|
	local xTwo = buildingPlate.Position.x - buildingPlate.Size.x/2
|
|
	local zOne = buildingPlate.Position.z + buildingPlate.Size.z/2
|
|
	local zTwo = buildingPlate.Position.z - buildingPlate.Size.z/2
|
|
	if part.Position.x > xOne or part.Position.x < xTwo then return false end
|
|
	if part.Position.z > zOne or part.Position.z < zTwo then return false end
|
|
	return true
|
|
end
|
|
|
|
|
|
-- For Restricting Stamper Tool (isRestricted)
|
|
function showHelp_pointToBuildingplate()
|
|
|
|
	if(buildingPlate==nil) then
|
|
		hint("All building areas are taken. If you want to build, leave and join again.")
|
|
	else
|
|
		-- only show one waypoint at a time (because kids will click a million times outside their plate)
|
|
		hint("Stamper Tool only works in your area.")
|
|
		if(not waypointShowing) then
|
|
			waypointShowing = true
|
|
			local _character = Tool.Parent
|
|
			waitForChild(_character, "Torso")
|
|
			_player = game.Players:GetPlayerFromCharacter(_character)
|
|
			_player.PlayerGui.showBaseplateWaypoint.target.Value = buildingPlate
|
|
			_player.PlayerGui.showBaseplateWaypoint.Disabled = true
|
|
			_player.PlayerGui.showBaseplateWaypoint.Disabled = false
|
|
			-- Wait until character moves in bounds (check every 2 seconds)
|
|
			while(not inBounds2(_character.Torso) and isEquipped) do	wait(2) end
|
|
			-- Then hide the waypoint
|
|
			hideHelp_pointToBuildingplate()
|
|
		end
|
|
	end
|
|
|
|
end
|
|
|
|
|
|
function showHelp_tooManyParts()
|
|
	hint("You have reached maximum number of parts! Delete some to put more down.")
|
|
end
|
|
|
|
|
|
function hideHelp_pointToBuildingplate()
|
|
	waypointShowing = false
|
|
	_player.PlayerGui.hideBaseplateWaypoint.Disabled = true
|
|
	_player.PlayerGui.hideBaseplateWaypoint.Disabled = false		
|
|
end
|
|
|
|
|
|
function setUpRestrictions()
|
|
	playerModel = game.Workspace.ActiveParts:FindFirstChild(player.Name .. "'s parts")
|
|
|
|
	local takenAreas = game.Workspace.BuildingAreas:GetChildren()
|
|
|
|
	waitForChild(player, "playerNumber")
|
|
		
|
|
	if(player.playerNumber.Value == 0) then
|
|
	 buildingPlate = nil
|
|
	 partModel = nil
|
|
	else
|
|
	 waitForChild(game.Workspace, "BuildingAreas")
|
|
	 local buildingAreas = game.Workspace.BuildingAreas
|
|
	 waitForChild(buildingAreas, "Area"..tostring(player.playerNumber.Value))
|
|
	 local targetArea = buildingAreas:FindFirstChild("Area"..tostring(player.playerNumber.Value))
|
|
	 waitForChild(targetArea, "PlayerArea")
|
|
	 waitForChild(targetArea.PlayerArea, "BasePlate")
|
|
|
|
	 buildingPlate = targetArea.PlayerArea.BasePlate
|
|
	 partModel = targetArea.PlayerArea
|
|
			
|
|
	end
|
|
|
|
	-- Check if player is standing in bounds, if not show error
|
|
	local _character = Tool.Parent
|
|
	waitForChild(_character, "Torso")
|
|
	_player = game.Players:GetPlayerFromCharacter(_character)
|
|
	if(buildingPlate~=nil) then
|
|
		if(not inBounds2(_character.Torso)) then
|
|
			showHelp_pointToBuildingplate()
|
|
		end
|
|
	else
|
|
		-- You have no building plate.
|
|
		hint("All building areas are taken. If you want to build, leave and join again.")
|
|
	end
|
|
end
|
|
|
|
function onInsertKeyDown(key)
|
|
	if loading then return end -- don't try to switch while we're loading
|
|
|
|
	key = string.lower(key)
|
|
|
|
	-- go to mru buttons
|
|
	if key == 'f' then
|
|
		mruButtonClick(1)
|
|
	elseif key == 'g' then
|
|
		mruButtonClick(2)
|
|
	elseif key == 'h' then
|
|
		mruButtonClick(3)
|
|
	elseif key == 'j' then
|
|
		mruButtonClick(4)
|
|
	end
|
|
|
|
end
|
|
|
|
function onEquippedLocal(mouse)
|
|
	player = getPlayer()
|
|
	if not player then
|
|
		return
|
|
	end
|
|
	if Tool.PlayerOwner.Value and Tool.PlayerOwner.Value ~= player then return end
|
|
|
|
	-- For Restricting Stamper Tool
|
|
	if isRestricted.Value then
|
|
		setUpRestrictions()
|
|
	end
|
|
|
|
	Mouse = mouse
|
|
	if not firstEquip and currStampGui and Tool.SavedState.Value and Tool.PlayerOwner.Value == getPlayer() and Data and Data.FullyLoaded then
|
|
|
|
		currStampGui.Parent = getPlayer().PlayerGui
|
|
|
|
		if mode == 1 then -- if we were stamping, keep going
|
|
			-- if we signal a negative asset, then that means keep going using whatever was in recent memory [don't reload from insert service]
|
|
			signalStamperScript(insertAsset.AssetName.Value, -1, insertAsset.Image.Value, true)			
|
|
		elseif mode == 2 then -- time to clone
|
|
			goToClone()
|
|
		end
|
|
|
|
	else
|
|
		if firstEquip then
|
|
			Tool.PlayerOwner.Value = player
|
|
			firstEquip = false
|
|
		end
|
|
		CancelDuringLoad = false
|
|
		resetCons()
|
|
|
|
		Data = {}
|
|
		Data.FullyLoaded = false
|
|
				
|
|
		Window = {}
|
|
		Window.Sets = {}
|
|
|
|
		currStampGui = stamperGui:clone()
|
|
		currStampGui.Parent = getPlayer().PlayerGui
|
|
		wait()
|
|
		setUpStamperGui()
|
|
|
|
		if not(CancelDuringLoad) then
|
|
			currStampGui.Parent = getPlayer().PlayerGui
|
|
			Tool.SavedState.Value = currStampGui
|
|
		end
|
|
|
|
		Data.FullyLoaded = true
|
|
	end
|
|
|
|
	Mouse.KeyDown:connect(onInsertKeyDown)
|
|
end
|
|
|
|
|
|
function onUnequippedLocal()
|
|
	if currStampGui then
|
|
		Tool.SavedState.Value = currStampGui
|
|
		currStampGui.Parent = nil
|
|
	end
|
|
	
|
|
	pcall(function()
|
|
		cancelAssetPlacement()
|
|
		Data.Loading.Cancelled = true
|
|
	end)
|
|
	CancelDuringLoad = true
|
|
end
|
|
|
|
|
|
function killConnection(connection)
|
|
	if connection then connection:disconnect() end
|
|
end
|
|
|
|
|
|
function resetCons()
|
|
	killConnection(guiChangedCon)
|
|
	killConnection(cloneButtonCon)
|
|
	killConnection(partListClickCon)
|
|
	killConnection(itemFrameChangedCon)
|
|
	killConnection(setsPrevPageCon)
|
|
	killConnection(setsNextPageCon)
|
|
	killConnection(insertPanelCloseCon)
|
|
	killConnection(minimizeCon)
|
|
	killConnection(restoreCon)
|
|
end
|
|
|
|
|
|
function onAncestryChanged(child,parent)
|
|
	if Tool.PlayerOwner.Value and not Tool:IsDescendantOf(Tool.PlayerOwner.Value) and not Tool:IsDescendantOf(Tool.PlayerOwner.Value.Character) then
|
|
		--Tool was dropped in some way, so we need to nuke our external state
|
|
		Tool.SavedState.Value = nil
|
|
		resetCons()
|
|
	end
|
|
end
|
|
|
|
|
|
function getMaxNumOfRecentParts()
|
|
	return maxRecentParts
|
|
end
|
|
|
|
|
|
function pushRecentStackBack()
|
|
	for i = getMaxNumOfRecentParts() - 1, 1, -1 do
|
|
		recentPartStack[i + 1].AssetNameValue = recentPartStack[i].AssetNameValue
|
|
		recentPartStack[i + 1].AssetIdValue = recentPartStack[i].AssetIdValue
|
|
		recentPartStack[i + 1].InsertFrameButtonImage = recentPartStack[i].InsertFrameButtonImage
|
|
	end
|
|
end
|
|
|
|
|
|
function clearMRUList()
|
|
	local buttons = currStampGui.StamperPanel.StamperButtons.RecentFrame:GetChildren()
|
|
	for i = 1, #buttons do
|
|
		if recentPartStackCons[i] then recentPartStackCons[i]:disconnect() end
|
|
		buttons[i].Visible = false
|
|
	end
|
|
end
|
|
|
|
|
|
function mruButtonClick(position)
|
|
	if recentPartStack[position].AssetIdValue == insertAsset.AssetId.Value then return end -- already stamping part
|
|
	-- get rid of old part
|
|
	signalStamperScript("",0,"","",false)
|
|
|
|
	--Show the dialog window
|
|
	moveLoadingWindow()
|
|
	signalStamperScript(recentPartStack[position].AssetNameValue, recentPartStack[position].AssetIdValue, recentPartStack[position].InsertFrameButtonImage, true)
|
|
end
|
|
|
|
|
|
function insertMRUButton(position)
|
|
	local mruButton = currStampGui.StamperPanel.StamperButtons.RecentFrame:FindFirstChild("Button" .. tostring(position))
|
|
	mruButton.ButtonImage.Image = recentPartStack[position].InsertFrameButtonImage
|
|
	if mruButton.ButtonImage.Image == "" then
|
|
		mruButton.Text = recentPartStack[position].AssetNameValue
|
|
	end
|
|
|
|
	if recentPartStackCons[position] then pcall(function() recentPartStackCons[position]:Disconnect() end) end
|
|
	recentPartStackCons[position] = mruButton.MouseButton1Click:connect(function() mruButtonClick(position) end)
|
|
	mruButton.Visible = true
|
|
end
|
|
|
|
|
|
function refreshRecentParts()
|
|
	if insertAsset.Image.Value == "" then return end -- we don't have an asset, get out of here
|
|
	if not recentPartStack then return end -- if somehow not created yet (recentPartStack[i] calls below were nil somehow)
|
|
	
|
|
	local numOfRecentParts = getMaxNumOfRecentParts()
|
|
|
|
	for i = 1,numOfRecentParts do
|
|
		if insertAsset.AssetId and recentPartStack[i] and insertAsset.AssetId.Value == recentPartStack[i].AssetIdValue then -- already have part, don't push back
|
|
			return
|
|
		end
|
|
	end
|
|
|
|
	pushRecentStackBack()
|
|
|
|
	-- update our stack to show previously allocated part
|
|
	recentPartStack[1].AssetNameValue = insertAsset.AssetName.Value
|
|
	recentPartStack[1].AssetIdValue = insertAsset.AssetId.Value
|
|
	recentPartStack[1].InsertFrameButtonImage = insertAsset.Image.Value
|
|
|
|
	clearMRUList()
|
|
|
|
	for i = 1, numOfRecentParts do
|
|
		if recentPartStack[i] and recentPartStack[i].AssetIdValue ~= "" then
|
|
			insertMRUButton(i)
|
|
		end
|
|
	end
|
|
end
|
|
|
|
|
|
function updateGui(type)
|
|
	if type == "Main" then
|
|
		goToInsertPanel()
|
|
	elseif type == "EyeDropper" then
|
|
		goToClone()
|
|
	elseif type == "SideDialog" then
|
|
		goToStamp()
|
|
	end
|
|
end
|
|
----------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
-- Lua Start Execution
|
|
setAssetUrls()
|
|
|
|
Tool.Equipped:connect(onEquippedLocal)
|
|
Tool.Unequipped:connect(onUnequippedLocal)
|
|
Tool.AncestryChanged:connect(onAncestryChanged)
|
|
|
|
waitForChild(variables, "SwitchLoaderToDialog")
|
|
variables.SwitchLoaderToDialog.Changed:connect(function(prop)
|
|
	if variables.SwitchLoaderToDialog.Value == true then
|
|
		updateGui(variables.SwitchLoaderToDialog.DialogType.Value)
|
|
		variables.SwitchLoaderToDialog.Value = false
|
|
	end
|
|
|
|
end)
|
|
|
|
waitForChild(variables, "ShowInvalidPlacement")
|
|
variables.ShowInvalidPlacement.Changed:connect(function(prop)
|
|
	if variables.ShowInvalidPlacement.Value == true then
|
|
		showHelp_pointToBuildingplate()
|
|
		showBaseplateGuideArrows()
|
|
		variables.ShowInvalidPlacement.Value = false
|
|
	end
|
|
end)
|
|
|
|
waitForChild(variables, "ShowMaxedOut")
|
|
variables.ShowMaxedOut.Changed:connect(function(prop)
|
|
	if variables.ShowMaxedOut.Value == true then
|
|
		showHelp_tooManyParts()
|
|
		variables.ShowMaxedOut.Value = false
|
|
	end
|
|
end)
|
|
|
|
waitForChild(variables, "Stamped")
|
|
variables.Stamped.Changed:connect(function()
|
|
	if variables.Stamped.Value == true then
|
|
		refreshRecentParts()
|
|
	end
|
|
end)
|
|
----------------------------------------------------------------------------------------</ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX99">
|
|
<Properties>
|
|
<bool name="Disabled">true</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">Readme</string>
|
|
<ProtectedString name="Source">--[[
|
|
	Stamper Tool v1.0.0
|
|
	
|
|
|
|
	Welcome to the stamper tool readme!
|
|
	Currently, this doc only exists to show the Stamper Tool Version!
|
|
|
|
]] </ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX100">
|
|
<Properties>
|
|
<bool name="Disabled">false</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">StampScript</string>
|
|
<ProtectedString name="Source">-- basic functions
|
|
|
|
function waitForChild(instance, name)
|
|
	while not instance:findFirstChild(name) do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
----------------------------------------------------------------------------------------
|
|
|
|
-- Locals
|
|
|
|
local Tool = script.Parent
|
|
|
|
local Mouse
|
|
local mouseMoveCon
|
|
local mouseButton1DownCon
|
|
local mouseButton1UpCon
|
|
local cameraChangeCon
|
|
|
|
local walking = false
|
|
|
|
local pressedEsc = false
|
|
|
|
local billBoardOwnerGui = nil
|
|
|
|
local cluster = game.Workspace:FindFirstChild("Terrain")
|
|
|
|
local gInitial90DegreeRotations = 0
|
|
local gStaticTrans = 1
|
|
local gDesiredTrans = 0.7
|
|
local transFadeInTime = 0.5
|
|
local fadeInDelayTime = 0.5
|
|
local eyedropperOffGridTolerance = 0.01
|
|
|
|
local insertBoundingBoxOverlapVector = Vector3.new(1, 1, 1) -- we can still stamp if our character extrudes into the target stamping space by 1 or fewer units
|
|
|
|
local useAssetVersionId = false
|
|
|
|
|
|
-- for high-scalability display
|
|
local adornPart = Instance.new("Part")
|
|
adornPart.Parent = nil
|
|
adornPart.formFactor = "Custom"
|
|
adornPart.Size = Vector3.new(4, 4, 4)
|
|
adornPart.CFrame = CFrame.new()
|
|
|
|
local adorn = Instance.new("SelectionBox")
|
|
adorn.Color = BrickColor.new("Toothpaste")
|
|
adorn.Adornee = adornPart
|
|
adorn.Visible = true
|
|
adorn.Transparency = 0
|
|
adorn.Name = "HighScalabilityStamperLine"
|
|
adorn.Parent = nil
|
|
|
|
local terrainSelectionBox = Instance.new("Part")
|
|
terrainSelectionBox.Parent = nil
|
|
terrainSelectionBox.formFactor = "Custom"
|
|
terrainSelectionBox.Size = Vector3.new(4, 4, 4)
|
|
terrainSelectionBox.CFrame = CFrame.new()
|
|
|
|
local HighScalabilityLine = {}
|
|
HighScalabilityLine.Start = nil
|
|
HighScalabilityLine.End = nil
|
|
HighScalabilityLine.Adorn = adorn
|
|
HighScalabilityLine.AdornPart = adornPart
|
|
HighScalabilityLine.InternalLine = nil
|
|
HighScalabilityLine.NewHint = true
|
|
|
|
-- for higher dimensional megacluster part stamping
|
|
HighScalabilityLine.MorePoints = {nil, nil}
|
|
HighScalabilityLine.MoreLines = {nil, nil}
|
|
HighScalabilityLine.Dimensions = 1
|
|
|
|
waitForChild(Tool,"LuaGlobalVariables")
|
|
local variables = Tool.LuaGlobalVariables
|
|
waitForChild(variables,"ShowInvalidPlacement")
|
|
waitForChild(variables, "Stamped")
|
|
waitForChild(Tool,"ErrorBox")
|
|
waitForChild(variables, "ShowAdminCategories")
|
|
local errorBox = Tool.ErrorBox
|
|
|
|
waitForChild(variables, "IsRestricted")
|
|
waitForChild(variables, "MouseClick")
|
|
click = variables.MouseClick
|
|
|
|
local Data = {}
|
|
Data.Stamp = {}
|
|
Data.Loading = {}
|
|
|
|
local guiScriptIsLoadingSomething = false
|
|
local unstampableSurface = false
|
|
|
|
local eyeDropperConnection, eyeDropperMoveConnection
|
|
|
|
local playerModel
|
|
local player
|
|
|
|
local lastTargetCFrame = nil
|
|
local lastTargetTerrainOrientation = 0
|
|
|
|
-- For Restricting Stamper Tool
|
|
local isRestricted = variables.IsRestricted.Value
|
|
local adminAccess = variables.ShowAdminCategories.Value
|
|
|
|
-- For Delete highlighting
|
|
local selectionBox
|
|
local currentSelection
|
|
local currentSelectionColors = {}
|
|
|
|
if isRestricted then waitForChild(game.Workspace, "BaseplateBumpers") end
|
|
----------------------------------------------------------------------------------------
|
|
|
|
-- Functions
|
|
function hint(label)
|
|
	-- Pass in a string, it shows a top hint. (Replaces previous hint, if exists)
|
|
	_player = game.Players:GetPlayerFromCharacter(Tool.Parent)
|
|
	if(_player.PlayerGui:FindFirstChild("topHint")~=nil) then
|
|
		local topHint = _player.PlayerGui.topHint
|
|
		topHint.Add.Label.Value = label
|
|
		topHint.Add.Width.Value = 3 -- widest width
|
|
		topHint.Add.Time.Value = 5
|
|
		topHint.Add.Disabled = true
|
|
		topHint.Add.Disabled = false
|
|
	end
|
|
end
|
|
|
|
|
|
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("Medium stone grey")
|
|
	else
|
|
		return BrickColor.new("Bright green")
|
|
	end
|
|
end
|
|
|
|
|
|
local manualWeldTable = {}
|
|
local manualWeldParentTable = {}
|
|
function saveTheWelds(object)
|
|
	if object:IsA("ManualWeld") or object:IsA("Rotate") then
|
|
		table.insert(manualWeldTable, object)
|
|
		table.insert(manualWeldParentTable, object.Parent)
|
|
	else
|
|
		local children = object:GetChildren()
|
|
		for i = 1, #children do
|
|
			saveTheWelds(children[i])
|
|
		end
|
|
	end
|
|
end
|
|
|
|
function restoreTheWelds()
|
|
	for i = 1, #manualWeldTable do
|
|
		manualWeldTable[i].Parent = manualWeldParentTable[i]
|
|
	end
|
|
end
|
|
|
|
|
|
function findSeatsInModel(parent, seatTable)
|
|
	if not parent then return end
|
|
|
|
	if parent.className == "Seat" or parent.className == "VehicleSeat" then
|
|
		table.insert(seatTable, parent)
|
|
	end
|
|
	local myChildren = parent:GetChildren()
|
|
	for j = 1, #myChildren do
|
|
		findSeatsInModel(myChildren[j], seatTable)
|
|
	end
|
|
end
|
|
|
|
function setSeatEnabledStatus(model, isEnabled)
|
|
	local seatList = {}
|
|
	findSeatsInModel(model, seatList)
|
|
|
|
	if isEnabled then
|
|
		-- remove any welds called "SeatWeld" in seats
|
|
		for i = 1, #seatList do
|
|
			local nextSeat = seatList[i]:FindFirstChild("SeatWeld")
|
|
			while nextSeat do nextSeat:Remove() nextSeat = seatList[i]:FindFirstChild("SeatWeld") end
|
|
		end
|
|
	else
|
|
		-- put a weld called "SeatWeld" in every seat
|
|
		-- this tricks it into thinking there's already someone sitting there, and it won't make you sit XD
|
|
		for i = 1, #seatList do
|
|
			local fakeWeld = Instance.new("Weld")
|
|
			fakeWeld.Name = "SeatWeld"
|
|
			fakeWeld.Parent = seatList[i]
|
|
		end
|
|
	end
|
|
end
|
|
|
|
|
|
function UnlockInstances(object)
|
|
|
|
	if object:IsA("BasePart") then
|
|
		object.Locked = false
|
|
	end
|
|
	for index,child in pairs(object:GetChildren()) do
|
|
		UnlockInstances(child)
|
|
	end
|
|
|
|
end
|
|
|
|
function generateOwnerGui(playerName)
|
|
	local gui = Instance.new("BillboardGui")
|
|
	gui.Name = "PlayerStamperTagGui"
|
|
	gui.StudsOffset = Vector3.new(0,1,0)
|
|
	gui.ExtentsOffset = Vector3.new(0,1,0)
|
|
	gui.Size = UDim2.new(5,0,2,0)
|
|
	pcall(function() gui.PlayerToHideFrom = game.Players.LocalPlayer end)
|
|
|
|
	local frame = Instance.new("Frame")
|
|
	frame.BackgroundColor3 = Color3.new(0,0,0)
|
|
	frame.BackgroundTransparency = 0.5
|
|
	frame.Name = "OwnerFrame"
|
|
	frame.Size = UDim2.new(1,0,1,0)
|
|
	frame.Parent = gui
|
|
	
|
|
	local ownerName = Instance.new("TextLabel")
|
|
	ownerName.Name = "OwnerName"
|
|
	ownerName.Size = UDim2.new(1,0,1,0)
|
|
	ownerName.Text = playerName
|
|
	ownerName.Font = Enum.Font.ArialBold
|
|
	ownerName.FontSize = Enum.FontSize.Size14
|
|
	ownerName.TextWrap = true
|
|
	ownerName.TextColor3 = Color3.new(1,1,1)
|
|
	ownerName.TextStrokeTransparency = 0
|
|
	ownerName.BackgroundTransparency = 1
|
|
	ownerName.Parent = frame
|
|
|
|
	return gui
|
|
end
|
|
|
|
|
|
|
|
function getPlayer()
|
|
	return game.Players:GetPlayerFromCharacter(script.Parent.Parent)
|
|
end
|
|
|
|
function beginInsertAssetStamp(assetName, assetId, image, stampMode)
|
|
	-- trying to stop assets, gone back to Main Stamp Dialog
|
|
	if assetId == 0 then
|
|
		guiScriptIsLoadingSomething = true
|
|
		cancelAssetPlacement()
|
|
		return
|
|
	end
|
|
	if assetId < 0 then
|
|
		guiScriptIsLoadingSomething = true
|
|
		cancelAssetPlacement()
|
|
		setupDraggableClone()
|
|
		wait() -- need this so onInsertMouseMove() can sync up with setupDraggableClone()
|
|
		onInsertMouseMove()
|
|
		guiScriptIsLoadingSomething = false
|
|
		return
|
|
	end
|
|
	-- This call will cause a "wait" until the data comes back
|
|
	-- below we wait a max of 8 seconds before deciding to bail out on loading
|
|
	local root
|
|
	local loader
|
|
	loading = true
|
|
	if useAssetVersionId then
|
|
		loader = coroutine.create(function()	
|
|
			root = game:GetService("InsertService"):LoadAssetVersion(assetId)
|
|
			loading = false
|
|
		end)
|
|
		coroutine.resume(loader)
|
|
	else
|
|
		loader = coroutine.create(function()	
|
|
			root = game:GetService("InsertService"):LoadAsset(assetId)
|
|
			loading = false
|
|
		end)
|
|
		coroutine.resume(loader)
|
|
	end
|
|
|
|
	local lastGameTime = 0
|
|
	local totalTime = 0
|
|
	local maxWait = 8
|
|
	while loading and totalTime < maxWait do
|
|
		lastGameTime = tick()
|
|
		wait(1)
|
|
		totalTime = totalTime + tick() - lastGameTime
|
|
	end
|
|
	loading = false
|
|
|
|
	if totalTime >= maxWait or pressedEsc then
|
|
		Data.Loading.Cancelled = true
|
|
		pressedEsc = false
|
|
	else
|
|
		Data.Loading.Cancelled = false
|
|
	end
|
|
|
|
|
|
	if Data.Loading.Cancelled then
|
|
		--The user got bored and wandered off
|
|
		--Just delete the model from the world... a shame we loaded it when they got bored
|
|
		-- 12/28/2010: Putting this inside a pcall (on gametest, first time equipping stamper, this was being called with root=nil.) (Jahr)
|
|
		pcall(function() root:Remove() end)
|
|
		signalInsertComplete("Main")
|
|
	else
|
|
		if root == nil then
|
|
			signalInsertComplete("Main")
|
|
			return
|
|
		end
|
|
|
|
		if not root:IsA("Model") then
|
|
			signalInsertComplete("Main")
|
|
			return
|
|
		end
|
|
|
|
		local instances = root:GetChildren()
|
|
		if #instances == 0 then
|
|
			root:Remove()
|
|
			signalInsertComplete("Main")
|
|
			return
|
|
		end
|
|
|
|
		--Unlock all parts that are inserted, to make sure they are editable
|
|
		UnlockInstances(root)
|
|
|
|
		--Continue the insert process
|
|
		root.Name = "InsertedObject" .. assetId
|
|
|
|
		--Examine the contents and decide what it looks like
|
|
		for pos, instance in pairs(instances) do
|
|
			--Single instance objects might be treated special, decals/skyboxes
|
|
			if instance:IsA("Decal") then
|
|
				--Current system here stops after finding one Decal (and gives you Decal tool)
|
|
				--We should do the same (probably)
|
|
				beginInsertDecal(instance)
|
|
				root:Remove()
|
|
|
|
				Window.Stamp.Frame.Visible = true
|
|
				return
|
|
			elseif instance:IsA("Team") then
|
|
				instance.Parent = game:GetService("Teams")
|
|
			elseif instance:IsA("SpawnLocation") then
|
|
				-- uh.............
|
|
			elseif instance:IsA("HopperBin") then
|
|
				-- Must go into the starterPack, prompt user?
|
|
			elseif instance:IsA("Tool") then
|
|
				-- Ask them if it should go in StarterPack?
|
|
			elseif instance:IsA("Sky") then
|
|
				local lightingService = game:GetService("Lighting")
|
|
				for index,child in pairs(lightingService:GetChildren()) do
|
|
					if child:IsA("Sky") then
|
|
						child:Remove();
|
|
					end
|
|
				end
|
|
				instance.Parent = lightingService
|
|
				return
|
|
			else
|
|
|
|
			end
|
|
		end
|
|
|
|
		if #root:GetChildren() == 0 then
|
|
			root:Remove()
|
|
			signalInsertComplete("Main")
|
|
			return
|
|
		end
|
|
|
|
		signalInsertComplete("SideDialog")
|
|
		
|
|
		cancelAssetPlacement()
|
|
		Data.Stamp.Model = root
|
|
		setupDraggableClone()
|
|
		guiScriptIsLoadingSomething = false
|
|
	end
|
|
|
|
end
|
|
|
|
function beginInsertDecal(decal)
|
|
|
|
	Data.Stamp.DecalSelection = Instance.new("SurfaceSelection")
|
|
	Data.Stamp.DecalSelection.Color = BrickColor.new("Bright orange")
|
|
	Data.Stamp.DecalSelection.archivable = false
|
|
	Data.Stamp.DecalSelection.Parent = getPlayer().PlayerGui
|
|
|
|
	--Save the decal in our Lua code for later use
|
|
	Data.Stamp.Decal = decal
|
|
	Data.Stamp.Decal.Parent = nil
|
|
|
|
end
|
|
|
|
|
|
-- signal to gui to switch frames
|
|
function signalInsertComplete(type)
|
|
|
|
	if type == "SideDialog" then
|
|
		variables.SwitchLoaderToDialog.DialogType.Value = "SideDialog"
|
|
		variables.SwitchLoaderToDialog.Value = true
|
|
	elseif type == "Main" then
|
|
		variables.SwitchLoaderToDialog.DialogType.Value = "Main"
|
|
		variables.SwitchLoaderToDialog.Value = true
|
|
	elseif type == "EyeDropper" then
|
|
		variables.SwitchLoaderToDialog.DialogType.Value = "EyeDropper"
|
|
		variables.SwitchLoaderToDialog.Value = true
|
|
	end
|
|
|
|
	-- needed to make sure we disconnect eyedroper handler
|
|
	if type ~= "EyeDropper" then
|
|
		if eyeDropperConnection then
|
|
			eyeDropperConnection:disconnect()
|
|
			eyeDropperConnection = nil
|
|
		end
|
|
		if eyeDropperMoveConnection then eyeDropperMoveConnection:disconnect() end
|
|
|
|
		if Mouse and not mouseButton1UpCon then mouseButton1UpCon = Mouse.Button1Up:connect(onInsertMouseButton1Up) end
|
|
	end
|
|
	clearSelection()
|
|
|
|
end
|
|
|
|
|
|
function p(assetName, assetId, image, stampMode)
|
|
	-- trying to stop assets, gone back to Main Stamp Dialog
|
|
	if assetId == 0 then
|
|
		cancelAssetPlacement()
|
|
		return
|
|
	end
|
|
|
|
	-- This call will cause a "wait" until the data comes back
|
|
	-- below we wait a max of 8 seconds before deciding to bail out on loading
|
|
	local root
|
|
	local loader
|
|
	loading = true
|
|
	if useAssetVersionId then
|
|
		loader = coroutine.create(function()
|
|
			root = game:GetService("InsertService"):LoadAssetVersion(assetId)
|
|
			loading = false
|
|
		end)
|
|
		coroutine.resume(loader)
|
|
	else
|
|
		loader = coroutine.create(function()	
|
|
			root = game:GetService("InsertService"):LoadAsset(assetId)
|
|
			loading = false
|
|
		end)
|
|
		coroutine.resume(loader)
|
|
	end
|
|
|
|
	local lastGameTime = 0
|
|
	local totalTime = 0
|
|
	local maxWait = 8
|
|
	while loading and totalTime < maxWait do
|
|
		lastGameTime = tick()
|
|
		wait(1)
|
|
		totalTime = totalTime + tick() - lastGameTime
|
|
	end
|
|
	loading = false
|
|
|
|
	if totalTime >= maxWait or pressedEsc then
|
|
		Data.Loading.Cancelled = true
|
|
		pressedEsc = false
|
|
	else
|
|
		Data.Loading.Cancelled = false
|
|
	end
|
|
|
|
|
|
	if Data.Loading.Cancelled then
|
|
		--The user got bored and wandered off
|
|
		--Just delete the model from the world... a shame we loaded it when they got bored
|
|
		-- 12/28/2010: Putting this inside a pcall (on gametest, first time equipping stamper, this was being called with root=nil.) (Jahr)
|
|
		pcall(function() root:Remove() end)
|
|
		signalInsertComplete("Main")
|
|
	else
|
|
		local instances = root:GetChildren()
|
|
		if #instances == 0 then
|
|
			root:Remove()
|
|
			signalInsertComplete("Main")
|
|
			return
|
|
		end
|
|
|
|
		--Unlock all parts that are inserted, to make sure they are editable
|
|
		UnlockInstances(root)
|
|
|
|
		--Continue the insert process
|
|
		root.Name = "InsertedObject" .. assetId
|
|
|
|
		--Examine the contents and decide what it looks like
|
|
		for pos, instance in pairs(instances) do
|
|
			--Single instance objects might be treated special, decals/skyboxes
|
|
			if instance:IsA("Decal") then
|
|
				--Current system here stops after finding one Decal (and gives you Decal tool)
|
|
				--We should do the same (probably)
|
|
				beginInsertDecal(instance)
|
|
				root:Remove()
|
|
|
|
				Window.Stamp.Frame.Visible = true
|
|
				return
|
|
			elseif instance:IsA("Team") then
|
|
				instance.Parent = game:GetService("Teams")
|
|
			elseif instance:IsA("SpawnLocation") then
|
|
				-- uh.............
|
|
			elseif instance:IsA("HopperBin") then
|
|
				-- Must go into the starterPack, prompt user?
|
|
			elseif instance:IsA("Tool") then
|
|
				-- Ask them if it should go in StarterPack?
|
|
			elseif instance:IsA("Sky") then
|
|
				local lightingService = game:GetService("Lighting")
|
|
				for index,child in pairs(lightingService:GetChildren()) do
|
|
					if child:IsA("Sky") then
|
|
						child:Remove();
|
|
					end
|
|
				end
|
|
				instance.Parent = lightingService
|
|
				return
|
|
			else
|
|
|
|
			end
|
|
		end
|
|
|
|
		if #root:GetChildren() == 0 then
|
|
			root:Remove()
|
|
			signalInsertComplete("Main")
|
|
			return
|
|
		end
|
|
|
|
		signalInsertComplete("SideDialog")
|
|
		
|
|
		cancelAssetPlacement()
|
|
		Data.Stamp.Model = root
|
|
		setupDraggableClone()
|
|
	end
|
|
|
|
end
|
|
|
|
|
|
function positionPartsAtCFrame3(partOrModel, aCFrame)
|
|
|
|
	local insertCFrame
|
|
	if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then
|
|
		--insertCFrame = Data.Stamp.CurrentParts[1]:GetChildren()[1].CFrame
|
|
		-- we assume model has at least one part in it; need to find first part
|
|
		i = 1
|
|
		while (i < (#Data.Stamp.CurrentParts[1]:GetChildren()) and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("Part") and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("TrussPart") and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("WedgePart") and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("CornerWedgePart")) do
|
|
			i = i + 1
|
|
		end
|
|
		insertCFrame = Data.Stamp.CurrentParts[1]:GetChildren()[i].CFrame
|
|
|
|
		for i, object in pairs(Data.Stamp.CurrentParts[1]:GetChildren()) do
|
|
			if object:IsA("Flag") then object = object.Handle end
|
|
			if (object:IsA("Part") or object:IsA("WedgePart") or object:IsA("CornerWedgePart") or object:IsA("TrussPart") or object:IsA("Seat") or object:IsA("VehicleSeat")) 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
|
|
		Data.Stamp.CurrentParts[1].CFrame = aCFrame
|
|
	end
|
|
|
|
end
|
|
|
|
|
|
-- For Restricting Stamper Tool (isRestricted)
|
|
function inBounds(object)
|
|
|
|
	for part, transparency in pairs(object) do
|
|
		if part:IsA("Part") or part:IsA("WedgePart") or part:IsA("CornerWedgePart") or part:IsA("TrussPart") then
|
|
			if not partInBounds(part) then return false end
|
|
		elseif part:IsA("Model") then
|
|
			local primPart = object.PrimaryPart
|
|
			if not partInBounds(primPart) then return false end
|
|
		end
|
|
	end
|
|
	return true
|
|
|
|
end
|
|
|
|
function partInBounds(part)
|
|
|
|
	if part == nil then return false end
|
|
|
|
	local xOne= buildingPlate.Position.x + buildingPlate.Size.x/2
|
|
	local xTwo = buildingPlate.Position.x - buildingPlate.Size.x/2
|
|
	local zOne = buildingPlate.Position.z + buildingPlate.Size.z/2
|
|
	local zTwo = buildingPlate.Position.z - buildingPlate.Size.z/2
|
|
|
|
	if part.Position.x > xOne or part.Position.x < xTwo then return false end
|
|
	if part.Position.z > zOne or part.Position.z < zTwo then return false end
|
|
|
|
	return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function canSelectObject(part)
|
|
	return part and not (part.Locked) and part:IsA("BasePart") and (part.Position - Tool.Parent.Head.Position).Magnitude < 60
|
|
end
|
|
|
|
function canEyeDropperObject(part)
|
|
	local stamperTag = part.Parent:FindFirstChild("RobloxStamper")
|
|
	if stamperTag == nil then stamperTag = part:FindFirstChild("RobloxStamper") end
|
|
|
|
	return part and not (part.Locked) and part:IsA("BasePart") and (part.Position - Tool.Parent.Head.Position).Magnitude < 60 and stamperTag ~= nil
|
|
end
|
|
|
|
function isOnGrid(partOrModel)
|
|
	-- first check to see if off-grid, and if so, prevent eyedropperage
|
|
		local modelExtentsInWorldCoords
|
|
		if partOrModel:IsA("Model") then
|
|
			modelExtentsInWorldCoords = partOrModel:GetModelCFrame():vectorToWorldSpace(partOrModel:GetModelSize())
|
|
		else
|
|
			modelExtentsInWorldCoords = partOrModel.CFrame:vectorToWorldSpace(partOrModel.Size)
|
|
		end
|
|
|
|
		-- we now simply check to see if the above property fits in a 4x4x4 gridspace
|
|
		offX = math.fmod(math.abs(modelExtentsInWorldCoords.X), 4)
|
|
		offY = math.fmod(math.abs(modelExtentsInWorldCoords.Y), 4)
|
|
		offZ = math.fmod(math.abs(modelExtentsInWorldCoords.Z), 4)
|
|
|
|
		local numberOfAxesOffGrid = 0
|
|
		if math.min(offX, 4 - offX) > eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
|
|
		if math.min(offY, 4 - offY) > eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
|
|
		if math.min(offZ, 4 - offZ) > eyedropperOffGridTolerance then numberOfAxesOffGrid = numberOfAxesOffGrid + 1 end
|
|
|
|
		if numberOfAxesOffGrid > 1 then return false -- we allow one axis to be not fit to grid, since any rotation must necessarily affect >= 2 axes (some of the models are like 4x4x6 :( ).
|
|
		else return true end
|
|
end
|
|
|
|
|
|
-- below is a helper function to help get the model surface instead of the part surface [for allowing a side to elect out of making joints automatically]
|
|
function calcRayHitTime(rayStart, raySlope, intersectionPlane)
|
|
	if math.abs(raySlope) < .01 then return 0 end -- 0 slope --> we just say intersection time is 0, and sidestep this dimension
|
|
	-- rayStart + t*raySlope = intersectionPlane, so t = (intersectionPlane - rayStart) / raySlope
|
|
	return (intersectionPlane - rayStart) / raySlope
|
|
end
|
|
|
|
|
|
function modelTargetSurface(partOrModel, rayStart, rayEnd)
|
|
	if not partOrModel then
|
|
		return 0
|
|
	end
|
|
|
|
	local modelCFrame = nil
|
|
	local modelSize = nil
|
|
	if partOrModel:IsA("Model") then
|
|
		modelCFrame = partOrModel:GetModelCFrame()
|
|
		modelSize = partOrModel:GetModelSize()
|
|
	else
|
|
		modelCFrame = partOrModel.CFrame
|
|
		modelSize = partOrModel.Size
|
|
	end
|
|
|
|
	local mouseRayStart = modelCFrame:pointToObjectSpace(rayStart)
|
|
	local mouseRayEnd = modelCFrame:pointToObjectSpace(rayEnd)
|
|
	local mouseSlope = mouseRayEnd - mouseRayStart
|
|
|
|
	local xPositive = 1
|
|
	local yPositive = 1
|
|
	local zPositive = 1
|
|
	if mouseSlope.X > 0 then xPositive = -1 end
|
|
	if mouseSlope.Y > 0 then yPositive = -1 end
|
|
	if mouseSlope.Z > 0 then zPositive = -1 end
|
|
|
|
	-- find which surface the transformed mouse ray hits (using modelSize):
|
|
	local xHitTime = calcRayHitTime(mouseRayStart.X, mouseSlope.X, modelSize.X/2 * xPositive)
|
|
	local yHitTime = calcRayHitTime(mouseRayStart.Y, mouseSlope.Y, modelSize.Y/2 * yPositive)
|
|
	local zHitTime = calcRayHitTime(mouseRayStart.Z, mouseSlope.Z, modelSize.Z/2 * zPositive)
|
|
|
|
	local hitFace = 0
|
|
|
|
	--if xHitTime >= 0 and yHitTime >= 0 and zHitTime >= 0 then
|
|
	if xHitTime > yHitTime then
|
|
		if xHitTime > zHitTime then
|
|
			-- xFace is hit
|
|
			hitFace = 1*xPositive
|
|
		else
|
|
			-- zFace is hit
|
|
			hitFace = 3*zPositive
|
|
		end
|
|
	else
|
|
		if yHitTime > zHitTime then
|
|
			-- yFace is hit
|
|
			hitFace = 2*yPositive
|
|
		else
|
|
			-- zFace is hit
|
|
			hitFace = 3*zPositive
|
|
		end
|
|
	end
|
|
|
|
	return hitFace
|
|
end
|
|
|
|
|
|
-- helper function for truncating to 45-degree angles on a 2D plane
|
|
function truncateToCircleEighth(bigValue, littleValue)
|
|
	local big = math.abs(bigValue)
|
|
	local little = math.abs(littleValue)
|
|
	local hypotenuse = math.sqrt(big*big + little*little)
|
|
	local frac = little / hypotenuse
|
|
|
|
	local bigSign = 1
|
|
	local littleSign = 1
|
|
	if bigValue < 0 then bigSign = -1 end
|
|
	if littleValue < 0 then littleSign = -1 end
|
|
|
|
	if frac > .382683432 then
|
|
		-- between 22.5 and 45 degrees, so truncate to 45-degree tilt
|
|
		return .707106781 * hypotenuse * bigSign, .707106781 * hypotenuse * littleSign
|
|
	else
|
|
		-- between 0 and 22.5 degrees, so truncate to 0-degree tilt
|
|
		return hypotenuse * bigSign, 0
|
|
	end
|
|
end
|
|
|
|
function onInsertMouseMove()
|
|
|
|
	if Data.Stamp.MovingLock then
|
|
		return
|
|
	end
|
|
|
|
	-- check to see if mouse is still active, and return otherwise!
|
|
	if not pcall(function () if Mouse and Mouse.Target and Mouse.Target.Parent:FindFirstChild("RobloxModel") == nil then return true else return false end end) then print("ERRORED OUT") game.JointsService:SetJoinAfterMoveTarget(nil) Mouse = nil return end
|
|
|
|
	if isRestricted and Mouse then
|
|
		Mouse.TargetFilter = game.Workspace.BaseplateBumpers
|
|
	end
|
|
|
|
	Data.Stamp.MovingLock = true
|
|
	if Data.Stamp.Dragger == nil then
|
|
		if Data.Stamp.Model ~= nil then
|
|
			if isRestricted then
|
|
				if checkPartLimit() then
|
|
					setupDraggableClone()
|
|
				else
|
|
					variables.ShowMaxedOut.Value = true
|
|
				end
|
|
			else
|
|
				setupDraggableClone()
|
|
			end
|
|
		end
|
|
	else
|
|
		-- REM TL: Data.Stamp.Dragger:MouseMove(Mouse.UnitRay)
|
|
		-- don't move with dragger - will move in one step on mouse down
|
|
		-- draw ghost at acceptable positions
|
|
		configFound, targetCFrame, targetSurface = findConfigAtMouseTarget(Data.Stamp.TransparencyTable)
|
|
		if configFound then
|
|
|
|
				if autoAlignToFace() and targetSurface ~= 1 and targetSurface ~= 4 then
|
|
				-- pre-rotate the flag or portrait so it's aligned correctly
|
|
				--local currCFrame
|
|
				--if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then currCFrame = Data.Stamp.CurrentParts[1]:GetModelCFrame()
|
|
				--else currCFrame = Data.Stamp.CurrentParts[1].CFrame end
|
|
|
|
				local numRotations = 0 -- update this according to how many rotations you need to get it to target surface
|
|
				if targetSurface == 3 then numRotations = 0 - gInitial90DegreeRotations + autoAlignToFace()
|
|
				elseif targetSurface == 0 then numRotations = 2 - gInitial90DegreeRotations + autoAlignToFace()
|
|
				elseif targetSurface == 5 then numRotations = 3 - gInitial90DegreeRotations + autoAlignToFace()
|
|
				elseif targetSurface == 2 then numRotations = 1 - gInitial90DegreeRotations + autoAlignToFace() end
|
|
				
|
|
|
|
				local ry = math.pi/2
|
|
				local rotCF = CFrame.fromEulerAnglesXYZ(0, ry*numRotations, 0)
|
|
				gInitial90DegreeRotations = gInitial90DegreeRotations + numRotations
|
|
				if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then
|
|
					for i, object in pairs(Data.Stamp.CurrentParts[1]:GetChildren()) do
|
|
						if object:IsA("Flag") then object = object.Handle end
|
|
						if object:IsA("Part") or object:IsA("TrussPart") or object:IsA("WedgePart") or object:IsA("CornerWedgePart") or object:IsA("Seat") or object:IsA("VehicleSeat") then
|
|
							object.CFrame = rotCF * object.CFrame
|
|
						end
|
|
					end
|
|
				else
|
|
					Data.Stamp.CurrentParts[1].CFrame = rotCF * Data.Stamp.CurrentParts[1].CFrame
|
|
				end
|
|
			end
|
|
|
|
|
|
|
|
			-- CODE TO CHECK FOR DRAGGING GHOST PART INTO A COLLIDING STATE
|
|
			local minBB, maxBB = getBoundingBoxInWorldCoordinates(Data.Stamp.CurrentParts[1])
|
|
	
|
|
			-- need to offset by distance to be dragged
|
|
			local currModelCFrame
|
|
			if Data.Stamp.CurrentParts[1]:IsA("Model") then
|
|
				-- we assume model has at least one part in it; need to find first part
|
|
				i = 1
|
|
				while i < (#Data.Stamp.CurrentParts[1]:GetChildren()) and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("BasePart") do
|
|
					i = i + 1
|
|
				end
|
|
				currModelCFrame = Data.Stamp.CurrentParts[1]:GetChildren()[i].CFrame
|
|
			else currModelCFrame = Data.Stamp.CurrentParts[1].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)
|
|
					if (Data.Stamp.CurrentParts[1].Name == "MegaClusterCube") and (Data.Stamp.CurrentParts[1]:FindFirstChild("ClusterMaterial")) and (Data.Stamp.CurrentParts[1].ClusterMaterial:IsA("Vector3Value")) then
|
|
						local clusterMat = Data.Stamp.CurrentParts[1].ClusterMaterial
|
|
						clusterMat.Value = Vector3.new(clusterMat.Value.X, clusterMat.Value.Y, lastTargetTerrainOrientation)
|
|
					end
|
|
				end
|
|
				Data.Stamp.MovingLock = 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 stamper from dragging ghost parts into other stamped models (once Region3 fix goes out)
|
|
			end
|
|
|
|
			positionPartsAtCFrame3(Data.Stamp.CurrentParts[1], targetCFrame)
|
|
			lastTargetCFrame = targetCFrame -- successful positioning, so update 'dat cframe
|
|
			if (Data.Stamp.CurrentParts[1].Name == "MegaClusterCube") and (Data.Stamp.CurrentParts[1]:FindFirstChild("ClusterMaterial")) and (Data.Stamp.CurrentParts[1].ClusterMaterial:IsA("Vector3Value")) then lastTargetTerrainOrientation = Data.Stamp.CurrentParts[1].ClusterMaterial.Value.Z end
|
|
|
|
|
|
			-- auto break joints code
|
|
			if Mouse and Mouse.Target and Mouse.Target.Parent then
|
|
				local modelInfo = Mouse.Target:FindFirstChild("RobloxModel")
|
|
				if not modelInfo then modelInfo = Mouse.Target.Parent:FindFirstChild("RobloxModel") end
|
|
				
|
|
				local myModelInfo = Data.Stamp.CurrentParts[1]:FindFirstChild("UnstampableFaces")
|
|
|
|
				--if (modelInfo and modelInfo.Parent:FindFirstChild("UnstampableFaces")) or (modelInfo and myModelInfo) then -- need better targetSurface calcs
|
|
				if (true) then
|
|
					local breakingFaces = ""
|
|
					local myBreakingFaces = ""
|
|
					if modelInfo and modelInfo.Parent:FindFirstChild("UnstampableFaces") then breakingFaces = modelInfo.Parent.UnstampableFaces.Value end
|
|
					if myModelInfo then myBreakingFaces = myModelInfo.Value end
|
|
					local hitFace = 0
|
|
|
|
					if modelInfo then hitFace = modelTargetSurface(modelInfo.Parent, game.Workspace.CurrentCamera.CoordinateFrame.p, Mouse.Hit.p) end
|
|
|
|
					-- are we stamping TO an unstampable surface?
|
|
					for bf in string.gmatch(breakingFaces, "[^,]+") do
|
|
						if hitFace == tonumber(bf) then
|
|
							-- return before we hit the JointsService code below!
|
|
							unstampableSurface = true
|
|
							game.JointsService:ClearJoinAfterMoveJoints() -- clear the JointsService cache
|
|
							Data.Stamp.MovingLock = false
|
|
							return
|
|
						end
|
|
					end
|
|
|
|
					-- now we have to cast the ray back in the other direction to find the surface we're stamping FROM
|
|
					hitFace = modelTargetSurface(Data.Stamp.CurrentParts[1], Mouse.Hit.p, game.Workspace.CurrentCamera.CoordinateFrame.p)
|
|
|
|
					-- are we stamping WITH an unstampable surface?
|
|
					for bf in string.gmatch(myBreakingFaces, "[^,]+") do
|
|
						if hitFace == tonumber(bf) then
|
|
							unstampableSurface = true
|
|
							game.JointsService:ClearJoinAfterMoveJoints() -- clear the JointsService cache
|
|
							Data.Stamp.MovingLock = false
|
|
							return
|
|
						end
|
|
					end
|
|
|
|
					-- just need to match breakingFace against targetSurface using rotation supplied by modelCFrame
|
|
					-- targetSurface: 1 is top, 4 is bottom,
|
|
				end
|
|
			end
|
|
|
|
		end
|
|
|
|
		-- to show joints during the mouse move
|
|
		unstampableSurface = false
|
|
game.JointsService:SetJoinAfterMoveInstance(Data.Stamp.CurrentParts[1])
|
|
|
|
		-- most common mouse inactive error occurs here, so check mouse active one more time in a pcall
|
|
		if not pcall(function () if Mouse and Mouse.Target and Mouse.Target.Parent:FindFirstChild("RobloxModel") == nil then return true else return false end end) then print("ERRORED OUT") game.JointsService:ClearJoinAfterMoveJoints() Mouse = nil Data.Stamp.MovingLock = false return end
|
|
|
|
if Mouse and Mouse.Target and Mouse.Target.Parent:FindFirstChild("RobloxModel") == nil then
|
|
			game.JointsService:SetJoinAfterMoveTarget(Mouse.Target)
|
|
else
|
|
			game.JointsService:SetJoinAfterMoveTarget(nil)
|
|
end
|
|
game.JointsService:ShowPermissibleJoints()
|
|
|
|
		-- here we allow for a line of high-scalability parts
|
|
		if (Data.Stamp.CurrentParts[1] and Data.Stamp.CurrentParts[1].Name == "MegaClusterCube") and HighScalabilityLine.Start then
|
|
			HighScalabilityLine.End = Data.Stamp.CurrentParts[1].CFrame.p
|
|
|
|
			local line
|
|
			local line2 = Vector3.new(0, 0, 0)
|
|
			local line3 = Vector3.new(0, 0, 0)
|
|
|
|
			if HighScalabilityLine.Dimensions == 1 then
|
|
				-- extract the line from these positions and limit to a 2D plane made from 2 of the world axes
|
|
				-- then use dominating axis to limit line to be at 45-degree intervals
|
|
				-- will use this internal representation of the line for the actual stamping
|
|
				line = (HighScalabilityLine.End - HighScalabilityLine.Start)
|
|
|
|
				if math.abs(line.X) < math.abs(line.Y) then
|
|
					if math.abs(line.X) < math.abs(line.Z) then
|
|
						-- limit to Y/Z plane, domination unknown
|
|
						local newY, newZ
|
|
						if (math.abs(line.Y) > math.abs(line.Z)) then
|
|
							newY, newZ = truncateToCircleEighth(line.Y, line.Z)
|
|
						else
|
|
							newZ, newY = truncateToCircleEighth(line.Z, line.Y)
|
|
						end
|
|
						line = Vector3.new(0, newY, newZ)
|
|
					else
|
|
						-- limit to X/Y plane, with Y dominating
|
|
						local newY, newX = truncateToCircleEighth(line.Y, line.X)
|
|
						line = Vector3.new(newX, newY, 0)
|
|
					end
|
|
				else
|
|
					if math.abs(line.Y) < math.abs(line.Z) then
|
|
						-- limit to X/Z plane, domination unknown
|
|
						local newX, newZ
|
|
						if math.abs(line.X) > math.abs(line.Z) then
|
|
							newX, newZ = truncateToCircleEighth(line.X, line.Z)
|
|
						else
|
|
							newZ, newX = truncateToCircleEighth(line.Z, line.X)
|
|
						end
|
|
						line = Vector3.new(newX, 0, newZ)
|
|
					else
|
|
						-- limit to X/Y plane, with X dominating
|
|
						local newX, newY = truncateToCircleEighth(line.X, line.Y)
|
|
						line = Vector3.new(newX, newY, 0)
|
|
					end
|
|
				end
|
|
				HighScalabilityLine.InternalLine = line
|
|
|
|
			elseif HighScalabilityLine.Dimensions == 2 then
|
|
				line = HighScalabilityLine.MoreLines[1]
|
|
				line2 = HighScalabilityLine.End - HighScalabilityLine.MorePoints[1]
|
|
		
|
|
				-- take out any component of line2 along line1, so you get perpendicular to line1 component
|
|
				line2 = line2 - line.unit*line.unit:Dot(line2)
|
|
|
|
				tempCFrame = CFrame.new(HighScalabilityLine.Start, HighScalabilityLine.Start + line)
|
|
|
|
				-- then zero out whichever is the smaller component
|
|
				local yAxis = tempCFrame:vectorToWorldSpace(Vector3.new(0, 1, 0))
|
|
				local xAxis = tempCFrame:vectorToWorldSpace(Vector3.new(1, 0, 0))
|
|
				
|
|
				local xComp = xAxis:Dot(line2)
|
|
				local yComp = yAxis:Dot(line2)
|
|
|
|
				if math.abs(yComp) > math.abs(xComp) then
|
|
					line2 = line2 - xAxis*xComp
|
|
				else
|
|
					line2 = line2 - yAxis*yComp
|
|
				end
|
|
|
|
				HighScalabilityLine.InternalLine = line2
|
|
			elseif HighScalabilityLine.Dimensions == 3 then
|
|
				line = HighScalabilityLine.MoreLines[1]
|
|
				line2 = HighScalabilityLine.MoreLines[2]
|
|
				line3 = HighScalabilityLine.End - HighScalabilityLine.MorePoints[2]
|
|
|
|
				-- zero out all components of previous lines
|
|
				line3 = line3 - line.unit*line.unit:Dot(line3)
|
|
				line3 = line3 - line2.unit*line2.unit:Dot(line3)
|
|
|
|
				HighScalabilityLine.InternalLine = line3
|
|
			end
|
|
|
|
			-- resize the "line" graphic to be the correct size and orientation
|
|
			tempCFrame = CFrame.new(HighScalabilityLine.Start, HighScalabilityLine.Start + line)
|
|
			
|
|
			if HighScalabilityLine.Dimensions == 1 then -- faster calculation for line
|
|
				HighScalabilityLine.AdornPart.Size = Vector3.new(4, 4, line.magnitude + 4)
|
|
				HighScalabilityLine.AdornPart.CFrame = tempCFrame + tempCFrame:vectorToWorldSpace(Vector3.new(2, 2, 2) - HighScalabilityLine.AdornPart.Size/2)
|
|
			else
|
|
				local boxSize = tempCFrame:vectorToObjectSpace(line + line2 + line3)
|
|
				HighScalabilityLine.AdornPart.Size = Vector3.new(4, 4, 4) + Vector3.new(math.abs(boxSize.X), math.abs(boxSize.Y), math.abs(boxSize.Z))
|
|
				HighScalabilityLine.AdornPart.CFrame = tempCFrame + tempCFrame:vectorToWorldSpace(boxSize/2)
|
|
			end
|
|
|
|
			-- make player able to see this ish
|
|
			if player then HighScalabilityLine.Adorn.Parent = player.PlayerGui end
|
|
			if HighScalabilityLine.NewHint then
|
|
				if HighScalabilityLine.Dimensions == 1 and line and (line.magnitude > 4) then hint("Press C to stamp in 2D") HighScalabilityLine.NewHint = false
|
|
				elseif HighScalabilityLine.Dimensions == 2 and line2 and (line2.magnitude > 4) then hint("Press C again to stamp in 3D") HighScalabilityLine.NewHint = false
|
|
				elseif HighScalabilityLine.Dimensions == 3 then HighScalabilityLine.NewHint = false end -- if we do cyclic, then let them know they're going back to line stamping
|
|
			end
|
|
		end
|
|
	end
|
|
|
|
	Data.Stamp.MovingLock = false
|
|
|
|
end
|
|
|
|
|
|
function onInsertMouseButton1Down()
|
|
|
|
	if Data.Stamp.Dragger or Data.Stamp.Decal then
|
|
		Data.Stamp.MouseDown = true
|
|
	end
|
|
|
|
	if (Data.Stamp.CurrentParts and Data.Stamp.CurrentParts[1] and Data.Stamp.CurrentParts[1].Name == "MegaClusterCube") and not eyeDropperConnection then
|
|
			-- only let them drag if they start dragging on the cluster!
|
|
			if Mouse and Mouse.Target and Mouse.Target:IsA("Terrain") then
|
|
				HighScalabilityLine.Dimensions = 1
|
|
				HighScalabilityLine.Start = Data.Stamp.CurrentParts[1].CFrame.p
|
|
			end
|
|
	end
|
|
end
|
|
|
|
|
|
function cancelAssetPlacement()
|
|
	HighScalabilityLine.Start = nil
|
|
	HighScalabilityLine.Adorn.Parent = nil
|
|
|
|
	gInitial90DegreeRotations = 0
|
|
	Data.Stamp.Cancelled = true
|
|
|
|
	if Data.Stamp["Model"] then
|
|
		Data.Stamp.Model.Parent = nil
|
|
	end
|
|
|
|
	if Data.Stamp.CurrentParts then
|
|
		for index, object in pairs(Data.Stamp.CurrentParts) do
|
|
			object.Parent = nil
|
|
		end
|
|
	
|
|
		Data.Stamp.CurrentParts.Parent = nil
|
|
	end
|
|
|
|
	if Data.Stamp.DecalSelection then
|
|
		Data.Stamp.DecalSelection:Remove()
|
|
		Data.Stamp.DecalSelection = nil
|
|
	end
|
|
	if Data.Stamp.Decal then
|
|
		Data.Stamp.Decal:Remove()
|
|
		Data.Stamp.Decal = nil
|
|
	end
|
|
|
|
	if Mouse then
|
|
		Mouse.Icon = "http://www.roblox.com/asset?id=66887745"
|
|
	end
|
|
	game.JointsService:ClearJoinAfterMoveJoints()
|
|
|
|
end
|
|
|
|
|
|
function collectParts(object, baseParts, scripts, decals)
|
|
|
|
	if object:IsA("BasePart") then
|
|
		baseParts[#baseParts+1] = object
|
|
	elseif object:IsA("Script") then
|
|
		scripts[#scripts+1] = object
|
|
	elseif object:IsA("Decal") then
|
|
		decals[#decals+1] = object
|
|
	end
|
|
|
|
	for index,child in pairs(object:GetChildren()) do
|
|
		collectParts(child, baseParts, scripts, decals)
|
|
	end
|
|
|
|
end
|
|
|
|
function getTargetPartBoundingBox(targetPart)
|
|
|
|
	if targetPart.Parent:FindFirstChild("RobloxModel") ~= nil then
|
|
		return getBoundingBox2(targetPart.Parent)
|
|
	else
|
|
		return getBoundingBox2(targetPart)
|
|
	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 partOrModel:IsA("Part") or partOrModel:IsA("WedgePart") or partOrModel:IsA("CornerWedgePart") or partOrModel:IsA("TrussPart")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]
|
|
		if partOrModel:IsA("Tool") then part1 = partOrModel.Handle if not part1 then return end end
|
|
		if part1:IsA("Flag") then part1 = partOrModel:FindFirstChild("Part") if not part1 then return end end
|
|
		for i, object in pairs(partOrModel:GetChildren()) do
|
|
			if (object:IsA("Part") or object:IsA("WedgePart") or object:IsA("CornerWedgePart") 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 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
|
|
|
|
	-- Adjust bounding box to reflect what the model or part author wants in terms of justification
|
|
	local justifyValue = partOrModel:FindFirstChild("Justification")
|
|
	if justifyValue ~= nil then
|
|
		-- find the multiple of 4 that contains the model
|
|
		justify = justifyValue.Value
|
|
		two = Vector3.new(2, 2, 2)
|
|
		actualBox = maxVec - minVec - Vector3.new(0.01, 0.01, 0.01)
|
|
		containingGridBox = Vector3.new(4 * math.ceil(actualBox.x/4), 4 * math.ceil(actualBox.y/4), 4 * math.ceil(actualBox.z/4))
|
|
		adjustment = containingGridBox - actualBox
|
|
		minVec = minVec - 0.5 * adjustment * justify
|
|
		maxVec = maxVec + 0.5 * adjustment * (two - justify)
|
|
	end
|
|
|
|
	return minVec, maxVec
|
|
|
|
end
|
|
|
|
|
|
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("BasePart")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("BasePart") then
|
|
				boxMinInWorld = object.CFrame:pointToWorldSpace(-0.5 * object.Size)
|
|
				boxMaxInWorld = object.CFrame:pointToWorldSpace(0.5 * object.Size)
|
|
|
|
				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 < minX then
|
|
					minX = boxMinInWorld.x
|
|
				end
|
|
				if boxMinInWorld.y < minY then
|
|
					minY = boxMinInWorld.y
|
|
				end
|
|
				if boxMinInWorld.z < minZ 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 > maxX then
|
|
					maxX = boxMinInWorld.x
|
|
				end
|
|
				if boxMinInWorld.y > maxY then
|
|
					maxY = boxMinInWorld.y
|
|
				end
|
|
				if boxMinInWorld.z > maxZ 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 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 getMouseTargetCFrame(targetPart)
|
|
|
|
	if targetPart.Parent:FindFirstChild("RobloxModel") ~= nil then
|
|
		if targetPart.Parent:IsA("Tool") then return targetPart.Parent.Handle.CFrame
|
|
		else return targetPart.Parent:GetChildren()[1].CFrame end
|
|
	else
|
|
		return targetPart.CFrame
|
|
	end
|
|
|
|
end
|
|
|
|
|
|
function surfaceToVector(surf)
|
|
	local vect = 1
|
|
	if surf < 0 then
|
|
		surf = surf * -1
|
|
		vect = vect * -1
|
|
	end
|
|
	if surf == 1 then return vect*Vector3.new(1, 0, 0)
|
|
	elseif surf == 2 then return vect*Vector3.new(0, 1, 0)
|
|
	elseif surf == 3 then return vect*Vector3.new(0, 0, 1)
|
|
	elseif Mouse then return Vector3.FromNormalId(Mouse.TargetSurface) end -- if we somehow got a "0", then we just revert to old behavior
|
|
	return Vector3.new(0,0,0)
|
|
end
|
|
|
|
function findConfigAtMouseTarget(partsTable)
|
|
|
|
-- *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(Data.Stamp.CurrentParts[1])
|
|
	local diagBB = maxBB - minBB
|
|
|
|
	local insertCFrame
|
|
	if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then
|
|
		i = 1
|
|
		while (i < (#Data.Stamp.CurrentParts[1]:GetChildren()) and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("Part") and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("TrussPart") and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("WedgePart") and not Data.Stamp.CurrentParts[1]:GetChildren()[i]:IsA("CornerWedgePart")) do
|
|
			i = i + 1
|
|
		end
|
|
		insertCFrame = Data.Stamp.CurrentParts[1]:GetChildren()[i].CFrame
|
|
	else
|
|
		insertCFrame = Data.Stamp.CurrentParts[1].CFrame
|
|
	end
|
|
|
|
	if not isRestricted and Mouse then
|
|
		if Data.Stamp.CurrentParts[1]:IsA("Tool") then Mouse.TargetFilter = Data.Stamp.CurrentParts[1].Handle
|
|
		else Mouse.TargetFilter = Data.Stamp.CurrentParts[1] end
|
|
	end
|
|
|
|
	local targetPart = nil
|
|
	local success = pcall(function() targetPart = Mouse.Target end)
|
|
|
|
	if not success or 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 = CFrame.new(0,0,0)
|
|
	if Mouse then
|
|
		hitCFrame = Mouse.Hit
|
|
	end
|
|
	local mouseHitInWorld = hitCFrame.p
|
|
|
|
	-- find which axis of the insertion objects should match with the target surface
|
|
	-- this should use targetPart CFrame, not the model CFrame
|
|
|
|
	--[[ attempt at fixing Mouse.TargetSurface below...
|
|
	local targetModel = targetPart
|
|
	if not targetPart:FindFirstChild("RobloxModel") and targetPart.Parent and targetPart.Parent:FindFirstChild("RobloxModel") then targetModel = targetPart.Parent end
|
|
	local correctedTargetSurfaceVector = surfaceToVector(modelTargetSurface(targetModel, game.Workspace.CurrentCamera.CoordinateFrame.p, mouseHitInWorld))
|
|
	local targetVectorInWorld = targetPart.CFrame:vectorToWorldSpace(correctedTargetSurfaceVector)
|
|
	--]]
|
|
|
|
	if targetPart:IsA("Terrain") then
|
|
		if not cluster then cluster = game.Workspace.Terrain end
|
|
|
|
		cellID = cluster:WorldToCellPreferSolid(mouseHitInWorld)
|
|
		targetCFrame = CFrame.new(cluster:CellCenterToWorld(cellID.x, cellID.y, cellID.z))
|
|
	end
|
|
	
|
|
	local mouseHitInTarget = targetCFrame:pointToObjectSpace(mouseHitInWorld)
|
|
	local targetVectorInWorld = Vector3.new(0,0,0)
|
|
	if Mouse then
|
|
		targetVectorInWorld = targetCFrame:vectorToWorldSpace(Vector3.FromNormalId(Mouse.TargetSurface))
|
|
	end
|
|
|
|
|
|
	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, getClosestAlignedWorldDirection(targetVectorInWorld)
|
|
|
|
end
|
|
|
|
function checkPartLimit()
|
|
|
|
	local numPoints = player.PointsUsed.Value
|
|
	local maxPoints = player.MaxPoints.Value
|
|
|
|
	if numPoints < maxPoints then
|
|
		return true
|
|
	else
|
|
		return false
|
|
	end
|
|
|
|
	return true
|
|
end
|
|
|
|
function setupDraggableClone()
|
|
	if eyeDropperConnection then eyeDropperConnection:disconnect() eyeDropperConnection = nil end
|
|
|
|
	--if not Mouse.Target then return end
|
|
	click.Value = false
|
|
|
|
	if Data.Stamp.CurrentParts then
|
|
		for i = 1, #Data.Stamp.CurrentParts do
|
|
			if Data.Stamp.CurrentParts[i].Parent ~= nil then
|
|
				Data.Stamp.CurrentParts[i].Parent = partModel
|
|
			end
|
|
		end
|
|
	end
|
|
	
|
|
	if Data.Stamp["Model"] == nil then return end
|
|
|
|
	local clone = Data.Stamp.Model:Clone()
|
|
	local scripts = {}
|
|
	local parts = {}
|
|
	local decals = {}
|
|
	
|
|
	collectParts(clone, parts, scripts, decals)
|
|
|
|
	if #parts > 0 then
|
|
		Data.Stamp.DisabledScripts = {}
|
|
		Data.Stamp.TransparencyTable = {}
|
|
		Data.Stamp.MaterialTable = {}
|
|
		Data.Stamp.CanCollideTable = {}
|
|
		Data.Stamp.AnchoredTable = {}
|
|
		Data.Stamp.DecalTransparencyTable = {}
|
|
|
|
		for index,script in pairs(scripts) do
|
|
			if not(script.Disabled) then
|
|
				script.Disabled = true
|
|
				Data.Stamp.DisabledScripts[#Data.Stamp.DisabledScripts +1] = script
|
|
			end
|
|
		end
|
|
		for index, part in pairs(parts) do
|
|
			Data.Stamp.TransparencyTable[part] = part.Transparency
|
|
			part.Transparency = gStaticTrans + (1-gStaticTrans)*part.Transparency
|
|
			Data.Stamp.MaterialTable[part] = part.Material
|
|
			part.Material = Enum.Material.Plastic
|
|
			Data.Stamp.CanCollideTable[part] = part.CanCollide
|
|
			part.CanCollide = false
|
|
			Data.Stamp.AnchoredTable[part] = part.Anchored
|
|
			part.Anchored = true
|
|
			part.archivable = false
|
|
|
|
			delay(0,function()
|
|
				local con = nil
|
|
				local exitLoop = false
|
|
				con = click.Changed:connect(function()
|
|
					if click.Value then
|
|
						con:disconnect()
|
|
						exitLoop = true
|
|
					end
|
|
				end)
|
|
				wait(fadeInDelayTime) -- give it some time to be completely transparent
|
|
|
|
				if exitLoop then return end -- if we already stamped, we don't need to do the rest of this
|
|
				
|
|
				local begTime = tick()
|
|
				local currTime = begTime
|
|
				while (currTime - begTime) < transFadeInTime and part and part:IsA("BasePart") and part.Transparency > gDesiredTrans and not exitLoop do
|
|
					local newTrans = 1 - (((currTime - begTime)/transFadeInTime) * (gStaticTrans - gDesiredTrans))
|
|
					if Data.Stamp.TransparencyTable[part] then part.Transparency = newTrans + (1-newTrans) * Data.Stamp.TransparencyTable[part] end
|
|
					wait(0.03)
|
|
					currTime = tick()
|
|
				end
|
|
				if part and part:IsA("BasePart") and not exitLoop then
|
|
					if Data.Stamp.TransparencyTable[part] then part.Transparency = gDesiredTrans + (1-gDesiredTrans)*Data.Stamp.TransparencyTable[part] end
|
|
				end
|
|
				if con then con:disconnect() end
|
|
			end)
|
|
		end
|
|
|
|
		for index, decal in pairs(decals) do
|
|
			Data.Stamp.DecalTransparencyTable[decal] = decal.Transparency
|
|
			decal.Transparency = gDesiredTrans + (1-gDesiredTrans)*decal.Transparency
|
|
		end
|
|
		
|
|
		clone.Parent = game.Workspace
|
|
|
|
		-- For Restricting Stamper Tool
|
|
		if(isRestricted) then
|
|
|
|
			-- mark a particular spot in BaseplateBumpers, so we can remove any stragglers later, when player leaves
|
|
			local cloneInsertionSpot = game.Workspace.BaseplateBumpers:FindFirstChild(player.Name)
|
|
			if cloneInsertionSpot == nil then
|
|
				cloneInsertionSpot = Instance.new("Model")
|
|
				cloneInsertionSpot.Name = player.Name
|
|
				cloneInsertionSpot.Parent = game.Workspace.BaseplateBumpers
|
|
			end
|
|
|
|
			clone.Parent = cloneInsertionSpot
|
|
		end
|
|
|
|
		-- disable all seats
|
|
		setSeatEnabledStatus(clone, true)
|
|
		setSeatEnabledStatus(clone, false)
|
|
|
|
		Data.Stamp.CurrentParts = clone:GetChildren()
|
|
|
|
		-- if auto-alignable, we enforce a pre-rotation to the canonical "0-frame"
|
|
		if autoAlignToFace() then
|
|
			if Data.Stamp.CurrentParts[1].PrimaryPart then modelInverse = Data.Stamp.CurrentParts[1].PrimaryPart.CFrame:inverse()
|
|
			else modelInverse = Data.Stamp.CurrentParts[1]:GetModelCFrame():inverse() end
|
|
			for i, object in pairs(Data.Stamp.CurrentParts[1]:GetChildren()) do
|
|
				if object:IsA("Flag") then object = object.Handle end
|
|
				if object:IsA("Part") or object:IsA("TrussPart") or object:IsA("WedgePart") or object:IsA("CornerWedgePart") or object:IsA("Seat") or object:IsA("VehicleSeat") then object.CFrame = modelInverse*object.CFrame end
|
|
			end
|
|
			gInitial90DegreeRotations = 0
|
|
		else
|
|
|
|
		-- pre-rotate if necessary
|
|
		local ry = gInitial90DegreeRotations * math.pi/2
|
|
		local rotCF = CFrame.fromEulerAnglesXYZ(0, ry, 0)
|
|
		if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then
|
|
			for i, object in pairs(Data.Stamp.CurrentParts[1]:GetChildren()) do
|
|
				if object:IsA("Flag") then object = object.Handle end
|
|
				if object:IsA("Part") or object:IsA("TrussPart") or object:IsA("WedgePart") or object:IsA("CornerWedgePart") or object:IsA("Seat") or object:IsA("VehicleSeat") then object.CFrame = rotCF * object.CFrame end
|
|
			end
|
|
		else
|
|
			Data.Stamp.CurrentParts[1].CFrame = rotCF * Data.Stamp.CurrentParts[1].CFrame
|
|
		end
|
|
		end
|
|
|
|
		-- After rotating, update the position
|
|
		configFound, targetCFrame = findConfigAtMouseTarget(Data.Stamp.TransparencyTable)
|
|
		if configFound then
|
|
			positionPartsAtCFrame3(Data.Stamp.TransparencyTable, targetCFrame)
|
|
		end
|
|
		-- to show joints during the mouse move
|
|
game.JointsService:SetJoinAfterMoveInstance(Data.Stamp.CurrentParts[1])
|
|
|
|
		local mouseTarget = nil
|
|
		pcall(function() mouseTarget = Mouse.Target end)
|
|
|
|
if mouseTarget and mouseTarget.Parent:FindFirstChild("RobloxModel") == nil then
|
|
			game.JointsService:SetJoinAfterMoveTarget(mouseTarget)
|
|
else
|
|
			game.JointsService:SetJoinAfterMoveTarget(nil)
|
|
		end
|
|
game.JointsService:ShowPermissibleJoints()
|
|
|
|
		for index, object in pairs(Data.Stamp.CurrentParts) do
|
|
			object.Parent = clone.Parent
|
|
		end
|
|
|
|
		clone:Remove()
|
|
|
|
		lastTargetCFrame = nil
|
|
|
|
	
|
|
		if billBoardOwnerGui then
|
|
			if #parts == 1 then
|
|
				billBoardOwnerGui.Parent = parts[1]
|
|
			else
|
|
				billBoardOwnerGui.Parent = parts[1].Parent
|
|
			end
|
|
		end
|
|
|
|
		HighScalabilityLine.NewHint = true -- show hint if they start dragging a high-scalability part
|
|
|
|
		Data.Stamp.Dragger = Instance.new("Dragger")
|
|
		--Begin a movement by faking a MouseDown signal
|
|
		Data.Stamp.Dragger:MouseDown(parts[1], Vector3.new(0,0,0), parts)
|
|
		Data.Stamp.Dragger:MouseUp()
|
|
	else
|
|
		--Nothing draggable in the Model
|
|
		Data.Stamp.Model:Remove()
|
|
		Data.Stamp.Model = nil
|
|
		Data.Stamp.TransparencyTable = nil
|
|
		Data.Stamp.MaterialTable = nil
|
|
		Data.Stamp.CanCollideTable = nil
|
|
		Data.Stamp.AnchoredTable = nil
|
|
		Data.Stamp.DisabledScripts = nil
|
|
	end
|
|
|
|
end
|
|
|
|
|
|
function noManualWelds(part)
|
|
	local partChildren = part:GetChildren()
|
|
	for i = 1, #partChildren do
|
|
		if partChildren[i]:IsA("ManualWeld") or partChildren[i]:IsA("Rotate") then
|
|
			return false
|
|
		end
|
|
	end
|
|
	return true
|
|
end
|
|
|
|
local debris = game:GetService("Debris")
|
|
function flashRedBox()
|
|
	errorBox.Parent = player.PlayerGui
|
|
	if Data.Stamp.CurrentParts[1]:IsA("Tool") then errorBox.Adornee = Data.Stamp.CurrentParts[1].Handle
|
|
	else errorBox.Adornee = Data.Stamp.CurrentParts[1] end
|
|
|
|
	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
|
|
|
|
	for x = startX, endX do
|
|
		for y = startY, endY do
|
|
			for z = startZ, endZ do
|
|
				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
|
|
-- 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(Data.Stamp.CurrentParts[1]) 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
|
|
|
|
|
|
-- returns whether or not we want to cancel the stamp because we're blocked by this part
|
|
function isBlocker(part)
|
|
	if not part then return false end
|
|
	if not part.Parent then return false end
|
|
	if part:FindFirstChild("Humanoid") then return false end
|
|
	if part:FindFirstChild("RobloxStamper") or part:FindFirstChild("RobloxModel") then return true end
|
|
	if part:IsA("Part") and not part.CanCollide then return false end
|
|
	if part == game.Workspace then return true end
|
|
	if part == game.Lighting then return false end
|
|
	return isBlocker(part.Parent)
|
|
end
|
|
|
|
function onInsertMouseButton1Up()
|
|
	if guiScriptIsLoadingSomething or variables.InsertAsset.Updated.Value then return end -- don't try to stamp while we're loading!
|
|
|
|
	if eyeDropperConnection then
|
|
		eyeDropperConnection:disconnect()
|
|
		eyeDropperConnection = nil
|
|
		return
|
|
	end
|
|
|
|
	if Data.Stamp.MouseDown then
|
|
		Data.Stamp.MouseDown = false
|
|
		if Data.Stamp.Dragger then
|
|
|
|
			--Place the object where the mouse is currently positioned
|
|
			-- For Restricting Stamper Tool
|
|
|
|
			while Data.Stamp.MouseLock do wait() end
|
|
			onInsertMouseMove()
|
|
			Data.Stamp.MouseLock = true
|
|
|
|
			if(isRestricted) then
|
|
				-- if player tries to stamp out of bounds, tell them they can't
|
|
				if not inBounds(Data.Stamp.TransparencyTable) then
|
|
					variables.ShowInvalidPlacement.Value = true
|
|
					Data.Stamp.MouseLock = false
|
|
					HighScalabilityLine.Start = nil
|
|
					HighScalabilityLine.Adorn.Parent = nil
|
|
					return
|
|
				end
|
|
			end
|
|
|
|
			-- if unstampable face, then don't let us stamp there!
|
|
			if unstampableSurface then
|
|
				Data.Stamp.MouseLock = false
|
|
				HighScalabilityLine.Start = nil
|
|
				HighScalabilityLine.Adorn.Parent = nil
|
|
				flashRedBox()
|
|
				return
|
|
			end
|
|
|
|
			-- Prevent part from being stamped on top of a player
|
|
|
|
			local minBB, maxBB = getBoundingBoxInWorldCoordinates(Data.Stamp.CurrentParts[1])
|
|
			local configFound, targetCFrame = findConfigAtMouseTarget(Data.Stamp.TransparencyTable)
|
|
|
|
			if configFound and not HighScalabilityLine.Adorn.Parent then
|
|
				if clusterPartsInRegion(minBB+insertBoundingBoxOverlapVector, maxBB-insertBoundingBoxOverlapVector) then Data.Stamp.MouseLock = false flashRedBox() return end
|
|
|
|
				local blockingParts = game.Workspace:FindPartsInRegion3(Region3.new(minBB+insertBoundingBoxOverlapVector, maxBB-insertBoundingBoxOverlapVector), Data.Stamp.CurrentParts[1], 100)
|
|
				for b = 1, #blockingParts do
|
|
					-- below if we only want to block stamping on self
|
|
					--if blockingParts[b].Parent == script.Parent.Parent then return end
|
|
					
|
|
					-- below if we want to block stamping on self and also stamping that intersects a model we've previously stamped on our baseplate
|
|
					--		 should work as soon as Region3 queries are fixed
|
|
					-- NOTE TO SELF: See if partModel applies when isRestricted is false
|
|
					--if blockingParts[b]:IsDescendantOf(partModel) or blockingParts[b].Parent == script.Parent.Parent then Data.Stamp.MouseLock = false flashRedBox() break end --return end
|
|
					if isBlocker(blockingParts[b]) then Data.Stamp.MouseLock = false flashRedBox() return end-- still error if overlapping another model [should return here too!]
|
|
				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 == script.Parent.Parent then
|
|
--						local blockingPersonTorso = script.Parent.Parent:FindFirstChild("Torso")
|
|
						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
|
|
								Data.Stamp.MouseLock = false
|
|
								flashRedBox()
|
|
								return
|
|
								-- should return here too!
|
|
							end
|
|
						end
|
|
						
|
|
						--break
|
|
					end
|
|
				end
|
|
			elseif (not configFound) then
|
|
				HighScalabilityLine.Start = nil
|
|
				HighScalabilityLine.Adorn.Parent = nil
|
|
				Data.Stamp.MouseLock = false
|
|
				return
|
|
			end -- if no config then don't stamp!
|
|
|
|
			-- something will be stamped! so set the "StampedSomething" toggle to true
|
|
			local localChar = game.Players.LocalPlayer.Character
|
|
			if localChar then
|
|
				local stampTracker = localChar:FindFirstChild("StampTracker")
|
|
				if stampTracker and not stampTracker.Value then stampTracker.Value = true end
|
|
			end
|
|
|
|
			-- also, show hints again if high scalability part
|
|
			HighScalabilityLine.NewHint = true
|
|
|
|
			if Data.Stamp.Model and Data.Stamp.Model:GetChildren()[1] and Data.Stamp.Model:GetChildren()[1].Name == "MegaClusterCube" then
|
|
					local line = HighScalabilityLine.InternalLine
|
|
					local cMax = game.Workspace.Terrain.MaxExtents.Max
|
|
					local cMin = game.Workspace.Terrain.MaxExtents.Min
|
|
|
|
					local clusterMaterial = 1 -- default is grass
|
|
					local clusterType = 0 -- default is brick
|
|
					local clusterOrientation = 0 -- default is 0 rotation
|
|
|
|
					local autoWedgeClusterParts = false
|
|
					if Data.Stamp.CurrentParts[1]:FindFirstChild("AutoWedge") then autoWedgeClusterParts = true end
|
|
|
|
					if Data.Stamp.CurrentParts[1]:FindFirstChild("ClusterMaterial") then
|
|
						clusterMaterial = Data.Stamp.CurrentParts[1].ClusterMaterial
|
|
						if (clusterMaterial:IsA("Vector3Value")) then
|
|
							-- extract all info from vector
|
|
							clusterType = clusterMaterial.Value.Y
|
|
							clusterOrientation = clusterMaterial.Value.Z
|
|
							clusterMaterial = clusterMaterial.Value.X
|
|
						else
|
|
							clusterMaterial = clusterMaterial.Value
|
|
						end
|
|
					end
|
|
		
|
|
					if HighScalabilityLine.Adorn.Parent and HighScalabilityLine.Start and ((HighScalabilityLine.Dimensions > 1) or (line and line.magnitude > 0)) then
|
|
						local startCell = game.Workspace.Terrain:WorldToCell(HighScalabilityLine.Start)
|
|
|
|
						local xInc = {0,0,0}
|
|
						local yInc = {0,0,0}
|
|
						local zInc = {0,0,0}
|
|
			
|
|
						local incrementVect = {nil, nil, nil}
|
|
						local stepVect = {Vector3.new(0, 0, 0), Vector3.new(0, 0, 0), Vector3.new(0, 0, 0)}
|
|
|
|
						local worldAxes = {Vector3.new(1, 0, 0), Vector3.new(0, 1, 0), Vector3.new(0, 0, 1)}
|
|
|
|
						local lines = {}
|
|
						if HighScalabilityLine.Dimensions > 1 then table.insert(lines, HighScalabilityLine.MoreLines[1]) end
|
|
						if line and line.magnitude > 0 then table.insert(lines, line) end
|
|
						if HighScalabilityLine.Dimensions > 2 then table.insert(lines, HighScalabilityLine.MoreLines[2]) end
|
|
|
|
						for i = 1, #lines do
|
|
							lines[i] = Vector3.new(math.floor(lines[i].X+.5), math.floor(lines[i].Y+.5), math.floor(lines[i].Z+.5)) -- round to integers
|
|
|
|
							if lines[i].X > 0 then xInc[i] = 1 elseif lines[i].X < 0 then xInc[i] = -1 end
|
|
							if lines[i].Y > 0 then yInc[i] = 1 elseif lines[i].Y < 0 then yInc[i] = -1 end
|
|
							if lines[i].Z > 0 then zInc[i] = 1 elseif lines[i].Z < 0 then zInc[i] = -1 end
|
|
|
|
							incrementVect[i] = Vector3.new(xInc[i], yInc[i], zInc[i])
|
|
							if incrementVect[i].magnitude < .9 then incrementVect[i] = nil end
|
|
						end
|
|
|
|
|
|
						if not lines[2] then lines[2] = Vector3.new(0, 0, 0) end
|
|
						if not lines[3] then lines[3] = Vector3.new(0, 0, 0) end
|
|
|
|
						while (stepVect[3].magnitude*4 <= lines[3].magnitude) do
|
|
							local outerStepVectIndex = 1
|
|
							while outerStepVectIndex < 4 do
|
|
							stepVect[2] = Vector3.new(0, 0, 0)
|
|
						while (stepVect[2].magnitude*4 <= lines[2].magnitude) do
|
|
							local innerStepVectIndex = 1
|
|
							while innerStepVectIndex < 4 do
|
|
							stepVect[1] = Vector3.new(0, 0, 0)
|
|
						while (stepVect[1].magnitude*4 <= lines[1].magnitude) do
|
|
							local stepVectSum = stepVect[1] + stepVect[2] + stepVect[3]
|
|
							local cellPos = Vector3int16.new(startCell.X + stepVectSum.X, startCell.Y + stepVectSum.Y, startCell.Z + stepVectSum.Z)
|
|
							if cellPos.X >= cMin.X and cellPos.Y >= cMin.Y and cellPos.Z >= cMin.Z and cellPos.X < cMax.X and cellPos.Y < cMax.Y and cellPos.Z < cMax.Z then
|
|
								-- check if overlaps player or part:
|
|
								local cellCenter = game.Workspace.Terrain:CellCenterToWorld(cellPos.X, cellPos.Y, cellPos.Z)
|
|
								local cellBlockingParts = game.Workspace:FindPartsInRegion3(Region3.new(cellCenter - Vector3.new(2, 2, 2) + insertBoundingBoxOverlapVector, cellCenter + Vector3.new(2, 2, 2) - insertBoundingBoxOverlapVector), Data.Stamp.CurrentParts[1], 100)
|
|
|
|
								local skipThisCell = false
|
|
								for b = 1, #cellBlockingParts do
|
|
									if isBlocker(cellBlockingParts[b]) then skipThisCell = true break end
|
|
								end
|
|
								
|
|
								if not skipThisCell then
|
|
									-- pop players up above any set cells
|
|
									local alreadyPushedUp = {}
|
|
									-- if no blocking model below, then see if stamping on top of a character
|
|
									for b = 1, #cellBlockingParts do
|
|
										if cellBlockingParts[b].Parent and not alreadyPushedUp[cellBlockingParts[b].Parent] and cellBlockingParts[b].Parent:FindFirstChild("Humanoid") and cellBlockingParts[b].Parent:FindFirstChild("Humanoid"):IsA("Humanoid") then
|
|
											local blockingPersonTorso = cellBlockingParts[b].Parent:FindFirstChild("Torso")
|
|
											alreadyPushedUp[cellBlockingParts[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 = cellCenter.Y + 5
|
|
												if spaceAboveCharacter(blockingPersonTorso, newY) then
|
|
													blockingPersonTorso.CFrame = blockingPersonTorso.CFrame + Vector3.new(0, newY - blockingPersonTorso.CFrame.p.Y, 0)
|
|
												else
|
|
													-- if no space, we just skip this one
|
|
													skipThisCell = true
|
|
													break
|
|
												end
|
|
											end
|
|
										end
|
|
									end
|
|
								end
|
|
						
|
|
								if not skipThisCell then -- if we STILL aren't skipping... then we're good to go!
|
|
									-- set it
|
|
									cluster:SetCell(cellPos.X, cellPos.Y, cellPos.Z, clusterMaterial, clusterType, clusterOrientation)
|
|
											
|
|
									-- auto-wedge it?
|
|
									if (autoWedgeClusterParts) then
|
|
										game.Workspace.Terrain:AutowedgeCells(Region3int16.new(Vector3int16.new(cellPos.x - 1, cellPos.y - 1, cellPos.z - 1), Vector3int16.new(cellPos.x + 1, cellPos.y + 1, cellPos.z + 1)))
|
|
									end
|
|
								end
|
|
							end
|
|
|
|
							stepVect[1] = stepVect[1] + incrementVect[1]
|
|
						end
|
|
							if incrementVect[2] then
|
|
								while innerStepVectIndex < 4 and worldAxes[innerStepVectIndex]:Dot(incrementVect[2]) == 0 do innerStepVectIndex = innerStepVectIndex + 1 end
|
|
								if innerStepVectIndex < 4 then
|
|
									stepVect[2] = stepVect[2] + worldAxes[innerStepVectIndex]*worldAxes[innerStepVectIndex]:Dot(incrementVect[2])
|
|
								end
|
|
								innerStepVectIndex = innerStepVectIndex + 1
|
|
							else stepVect[2] = Vector3.new(1, 0, 0) innerStepVectIndex = 4 end -- skip all remaining loops
|
|
							if (stepVect[2].magnitude*4 > lines[2].magnitude) then innerStepVectIndex = 4 end
|
|
						end
|
|
						end
|
|
							wait()
|
|
							if incrementVect[3] then
|
|
								while outerStepVectIndex < 4 and worldAxes[outerStepVectIndex]:Dot(incrementVect[3]) == 0 do outerStepVectIndex = outerStepVectIndex + 1 end
|
|
								if outerStepVectIndex < 4 then
|
|
									stepVect[3] = stepVect[3] + worldAxes[outerStepVectIndex]*worldAxes[outerStepVectIndex]:Dot(incrementVect[3])
|
|
								end
|
|
								outerStepVectIndex = outerStepVectIndex + 1
|
|
							else stepVect[3] = Vector3.new(1, 0, 0) outerStepVectIndex = 4 end -- skip all remaining loops
|
|
							if (stepVect[3].magnitude*4 > lines[3].magnitude) then outerStepVectIndex = 4 end
|
|
						end
|
|
						end
|
|
|
|
						-- and also get rid of any HighScalabilityLine stuff if it's there
|
|
						HighScalabilityLine.Start = nil
|
|
						HighScalabilityLine.Adorn.Parent = nil
|
|
						Data.Stamp.MouseLock = false
|
|
						return
|
|
					end
|
|
|
|
				-- not High-Scalability-Line-Based, so behave normally [and get rid of any HSL stuff]
|
|
				HighScalabilityLine.Start = nil
|
|
				HighScalabilityLine.Adorn.Parent = nil
|
|
|
|
				-- if target point is in cluster, just use cluster:SetCell
|
|
				if cluster then
|
|
					-- if targetCFrame is inside cluster, just set that cell to 1 and return
|
|
					local cellPos = cluster:WorldToCell(targetCFrame.p)
|
|
|
|
					if cellPos.X >= cMin.X and cellPos.Y >= cMin.Y and cellPos.Z >= cMin.Z and cellPos.X < cMax.X and cellPos.Y < cMax.Y and cellPos.Z < cMax.Z then
|
|
						cluster:SetCell(cellPos.X, cellPos.Y, cellPos.Z, clusterMaterial, clusterType, clusterOrientation)
|
|
|
|
						-- auto-wedge it
|
|
						if (autoWedgeClusterParts) then
|
|
							game.Workspace.Terrain:AutowedgeCells(Region3int16.new(Vector3int16.new(cellPos.x - 1, cellPos.y - 1, cellPos.z - 1), Vector3int16.new(cellPos.x + 1, cellPos.y + 1, cellPos.z + 1)))
|
|
						end
|
|
|
|
						Data.Stamp.MouseLock = false
|
|
						return
|
|
					end
|
|
				end
|
|
			end
|
|
|
|
			-- Post process: after positioning the part or model, restore transparency, material, anchored and collide states and create joints
|
|
			if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then
|
|
				
|
|
				if Data.Stamp.CurrentParts[1]:IsA("Model") then
|
|
					-- Tyler's magical hack-code for allowing/preserving clones of both Surface and Manual Welds... just don't ask X<
|
|
					manualWeldTable = {}
|
|
					manualWeldParentTable = {}
|
|
					saveTheWelds(Data.Stamp.CurrentParts[1])
|
|
					Data.Stamp.CurrentParts[1]:BreakJoints()
|
|
					Data.Stamp.CurrentParts[1]:MakeJoints()
|
|
					restoreTheWelds()
|
|
				end
|
|
				
|
|
				-- if it's a model, we also want to fill in the playerID and playerName tags, if it has those (e.g. for the friend-only door)
|
|
				playerIdTag = Data.Stamp.CurrentParts[1]:FindFirstChild("PlayerIdTag")
|
|
				playerNameTag = Data.Stamp.CurrentParts[1]:FindFirstChild("PlayerNameTag")
|
|
				if playerIdTag ~= nil then
|
|
					tempPlayerValue = getPlayer()
|
|
					if tempPlayerValue ~= nil then playerIdTag.Value = tempPlayerValue.userId end
|
|
				end
|
|
				if playerNameTag ~= nil then
|
|
					tempPlayerValue = getPlayer()
|
|
					if tempPlayerValue ~= nil then playerNameTag.Value = tempPlayerValue.Name end
|
|
				end
|
|
				-- ...and tag all inserted models for subsequent origin identification
|
|
				-- if no RobloxModel tag already exists, then add it.
|
|
				if Data.Stamp.CurrentParts[1]:FindFirstChild("RobloxModel") == nil then
|
|
					local stringTag = Instance.new("BoolValue", Data.Stamp.CurrentParts[1])
|
|
					stringTag.Name = "RobloxModel"
|
|
|
|
					if Data.Stamp.CurrentParts[1]:FindFirstChild("RobloxStamper") == nil then
|
|
						local stringTag2 = Instance.new("BoolValue", Data.Stamp.CurrentParts[1])
|
|
						stringTag2.Name = "RobloxStamper"
|
|
					end
|
|
				end
|
|
|
|
			else
|
|
				Data.Stamp.CurrentParts[1]:BreakJoints()
|
|
				if Data.Stamp.CurrentParts[1]:FindFirstChild("RobloxStamper") == nil then
|
|
					local stringTag2 = Instance.new("BoolValue", Data.Stamp.CurrentParts[1])
|
|
					stringTag2.Name = "RobloxStamper"
|
|
				end
|
|
			end
|
|
			
|
|
			-- make sure all the joints are activated before restoring anchor states
|
|
			if not createJoints then game.JointsService:CreateJoinAfterMoveJoints() end
|
|
|
|
			click.Value = true
|
|
			--Fix the transparency and material of all the parts
|
|
			for part, transparency in pairs(Data.Stamp.TransparencyTable) do
|
|
				part.Transparency = transparency
|
|
				part.archivable = true
|
|
			end
|
|
			for part, material in pairs(Data.Stamp.MaterialTable) do
|
|
				part.Material = material
|
|
			end
|
|
			for part, collide in pairs(Data.Stamp.CanCollideTable) do
|
|
				part.CanCollide = collide
|
|
			end
|
|
			for part, anchored in pairs(Data.Stamp.AnchoredTable) do
|
|
				part.Anchored = anchored
|
|
			end
|
|
			for decal, transparency in pairs(Data.Stamp.DecalTransparencyTable) do
|
|
				decal.Transparency = transparency
|
|
			end
|
|
|
|
			if (Data.Stamp.CurrentParts[1] and Data.Stamp.CurrentParts[1].Name == "MegaClusterCube") then
|
|
				Data.Stamp.CurrentParts[1].Transparency = 0
|
|
			end
|
|
|
|
			-- re-enable all seats
|
|
			setSeatEnabledStatus(Data.Stamp.CurrentParts[1], true)
|
|
|
|
			Data.Stamp.TransparencyTable = nil
|
|
			Data.Stamp.MaterialTable = nil
|
|
			Data.Stamp.CanCollideTable = nil
|
|
			Data.Stamp.AnchoredTable = nil
|
|
|
|
			-- ...and tag all inserted models for subsequent origin identification
|
|
			-- if no RobloxModel tag already exists, then add it.
|
|
			if Data.Stamp.CurrentParts[1]:FindFirstChild("RobloxModel") == nil then
|
|
				local stringTag = Instance.new("BoolValue", Data.Stamp.CurrentParts[1])
|
|
				stringTag.Name = "RobloxModel"
|
|
			end
|
|
						
|
|
			-- set our object back to the player's plate
|
|
			Data.Stamp.CurrentParts[1].Parent = partModel
|
|
|
|
			--Re-enable the scripts
|
|
			for index,script in pairs(Data.Stamp.DisabledScripts) do
|
|
				script.Disabled = false
|
|
			end
|
|
			--Now that they are all marked enabled, reinsert them into the world so they start running
|
|
			for index,script in pairs(Data.Stamp.DisabledScripts) do
|
|
				local oldParent = script.Parent
|
|
				script.Parent = nil
|
|
				script:Clone().Parent = oldParent
|
|
			end
|
|
			Data.Stamp.DisabledScripts = nil
|
|
			Data.Stamp.Dragger = nil
|
|
			Data.Stamp.CurrentParts.Parent = nil
|
|
			Data.Stamp.CurrentParts = nil
|
|
|
|
			Data.Stamp.MouseLock = false
|
|
|
|
			--Now set up a new instance of the object to allow a second copy to be stamped down
|
|
			variables.Stamped.Value = true
|
|
			variables.Stamped.Value = false
|
|
			if isRestricted then
|
|
				if checkPartLimit() then
|
|
					setupDraggableClone()
|
|
				else
|
|
					variables.ShowMaxedOut.Value = true
|
|
				end
|
|
			else
|
|
				setupDraggableClone()
|
|
			end
|
|
|
|
		end
|
|
	end
|
|
end
|
|
|
|
|
|
------------------------ EyeDropper Code -------------------------------------------
|
|
|
|
function onEyeDropperMouseButton1Down()
|
|
	if eyeDropperMoveConnection then
|
|
		eyeDropperMoveConnection:disconnect()
|
|
	end
|
|
	clearSelection()
|
|
	if Mouse then
|
|
		Mouse.Icon = "http://www.roblox.com/asset?id=66887745"
|
|
	end
|
|
|
|
	-- deny any attempt to clone something that wasn't stamped using the Stamper tool
|
|
	if not Mouse or not Mouse.Target then
|
|
		startEyeDropperOperation()
|
|
		return
|
|
	end
|
|
|
|
	local isTerrainEyedroppering = false
|
|
	if Mouse.Target == game.Workspace.Terrain then
|
|
		-- want to eyedropper a terrain piece; gotta do a little extra footwork
|
|
		print("Eyedroppering Terrain Piece")
|
|
		local newTerrainPiece
|
|
|
|
		-- gotta make the fake part here
|
|
		local hitCell = game.Workspace.Terrain:WorldToCellPreferSolid(Mouse.Hit.p)
|
|
		local cellMat, cellType, cellOrient = game.Workspace.Terrain:GetCell(hitCell.x, hitCell.y, hitCell.z)
|
|
|
|
		if (cellType.Value == 1 or cellType.Value == 4) then newTerrainPiece = Instance.new("WedgePart") newTerrainPiece.formFactor = "Custom"
|
|
		elseif (cellType.Value == 2) then newTerrainPiece = Instance.new("CornerWedgePart")
|
|
		else newTerrainPiece = Instance.new("Part") newTerrainPiece.formFactor = "Custom" end
|
|
		newTerrainPiece.Name = "MegaClusterCube"
|
|
		newTerrainPiece.Size = Vector3.new(4, 4, 4)
|
|
		newTerrainPiece.BottomSurface = "Smooth"
|
|
		newTerrainPiece.TopSurface = "Smooth"
|
|
|
|
		-- can add decals or textures here if feeling particularly adventurous... for now, can make a table of look-up colors
|
|
		newTerrainPiece.BrickColor = getClosestColorToTerrainMaterial(cellMat.Value)
|
|
|
|
		local sideways = 0
|
|
		local flipped = math.pi
|
|
		if cellType.Value == 4 then sideways = -math.pi/2 end
|
|
		if cellType.Value == 2 or cellType.Value == 3 then flipped = 0 end
|
|
		newTerrainPiece.CFrame = CFrame.Angles(0, math.pi/2*cellOrient.Value + flipped, sideways)
|
|
|
|
		if cellType.Value == 3 then
|
|
			local inverseCornerWedgeMesh = Instance.new("SpecialMesh")
|
|
			inverseCornerWedgeMesh.MeshType = "FileMesh"
|
|
			inverseCornerWedgeMesh.MeshId = "http://www.roblox.com/asset?id=66832495"
|
|
			inverseCornerWedgeMesh.Scale = Vector3.new(2, 2, 2)
|
|
			inverseCornerWedgeMesh.Parent = newTerrainPiece
|
|
		end
|
|
|
|
		local materialTag = Instance.new("Vector3Value")
|
|
		materialTag.Value = Vector3.new(cellMat.Value, cellType.Value, cellOrient.Value)
|
|
		materialTag.Name = "ClusterMaterial"
|
|
		materialTag.Parent = newTerrainPiece
|
|
|
|
		local tempModel = Instance.new("Model")
|
|
		newTerrainPiece.Parent = tempModel
|
|
|
|
		Data.Stamp.Model = tempModel
|
|
		Data.Stamp.Model:BreakJoints()
|
|
|
|
		isTerrainEyedroppering = true
|
|
	end
|
|
|
|
	local stamperTag = Mouse.Target.Parent:FindFirstChild("RobloxStamper")
|
|
	if stamperTag == nil then stamperTag = Mouse.Target:FindFirstChild("RobloxStamper") end
|
|
	if stamperTag == nil and not isTerrainEyedroppering then
|
|
		startEyeDropperOperation()
|
|
		return
|
|
	end
|
|
|
|
	local eyeDropperInstance
|
|
	-- find out if the target part is part of a Roblox Set Model
|
|
	local robloxModelTag = Mouse.Target.Parent:FindFirstChild("RobloxModel")
|
|
	if robloxModelTag ~= nil then
|
|
		eyeDropperInstance = Mouse.Target.Parent
|
|
	else
|
|
		eyeDropperInstance = Mouse.Target
|
|
	end
|
|
	
|
|
	-- do not allow certain objects to be captured with eye-dropper
|
|
	-- for now, locked parts
|
|
	if eyeDropperInstance:IsA("Part") and eyeDropperInstance.Locked and not isTerrainEyedroppering then
|
|
		startEyeDropperOperation()
|
|
	else
|
|
		if not isTerrainEyedroppering then
|
|
			local cloneInstance = eyeDropperInstance:clone()
|
|
			local tempModel = Instance.new("Model")
|
|
			cloneInstance.Parent = tempModel
|
|
|
|
			-- once more, we make sure it's on grid before eyedroppering
|
|
			if not isOnGrid(tempModel) then startEyeDropperOperation() return end
|
|
|
|
			Data.Stamp.Model = tempModel
|
|
			Data.Stamp.Model:BreakJoints()
|
|
		end
|
|
|
|
		-- will create and position clone without requiring user to move the mouse		
|
|
|
|
		if isRestricted then
|
|
			if checkPartLimit() then
|
|
				setupDraggableClone()
|
|
				if Mouse and not mouseButton1UpCon then mouseButton1UpCon = Mouse.Button1Up:connect(onInsertMouseButton1Up) end
|
|
			else
|
|
				variables.ShowMaxedOut.Value = true
|
|
			end
|
|
		else
|
|
			setupDraggableClone()
|
|
			if Mouse and not mouseButton1UpCon then mouseButton1UpCon = Mouse.Button1Up:connect(onInsertMouseButton1Up) end
|
|
		end
|
|
|
|
		variables.SwitchLoaderToDialog.AssetImage.Value = "0"
|
|
		variables.SwitchLoaderToDialog.DialogType.Value = "SideDialog"
|
|
		variables.SwitchLoaderToDialog.Value = true
|
|
	end
|
|
end
|
|
|
|
function onEyeDropperMouseMove()
|
|
	if not(inGui) and not(inPalette) then
|
|
		if not Mouse or not Mouse.Target then clearSelection() return end
|
|
		local part = Mouse.Target
|
|
		if part:IsA("Terrain") and Mouse.Hit then
|
|
			selectionBox.Color = BrickColor.Green()
|
|
			setTerrainSelection(Mouse.Hit.p)
|
|
		elseif canEyeDropperObject(part) then
|
|
			local model = findModel(part)
|
|
			if model and isOnGrid(model) then 		
|
|
				selectionBox.Color = BrickColor.Green()
|
|
				setSelection(model)
|
|
			elseif (not model) and isOnGrid(part) then
|
|
				selectionBox.Color = BrickColor.Green()
|
|
				setSelection(part)
|
|
			else
|
|
				clearSelection()
|
|
			end
|
|
		else
|
|
			clearSelection()
|
|
		end
|
|
	end
|
|
end
|
|
|
|
function startEyeDropperOperation()
|
|
|
|
	cancelAssetPlacement()
|
|
	pressedEsc = false
|
|
	signalInsertComplete("EyeDropper")
|
|
|
|
	if mouseButton1UpCon then mouseButton1UpCon:disconnect() mouseButton1UpCon = nil end
|
|
|
|
	if eyeDropperConnection then
|
|
		eyeDropperConnection:disconnect()
|
|
		eyeDropperConnection = nil
|
|
	end
|
|
	if eyeDropperMoveConnection then eyeDropperMoveConnection:disconnect() end
|
|
	if Mouse then
|
|
		--Mouse.Icon ="rbxasset://textures//DropperCursor.png"
|
|
		Mouse.Icon = "http://www.roblox.com/asset?id=67163166"
|
|
		eyeDropperConnection = Mouse.Button1Up:connect(onEyeDropperMouseButton1Down)
|
|
		eyeDropperMoveConnection = Mouse.Move:connect(onEyeDropperMouseMove)
|
|
	end
|
|
|
|
end
|
|
|
|
function findModel(part)
|
|
|
|
	if isRestricted then
|
|
		while part ~= nil do
|
|
			if part.className == "Model" and part.Name ~= playerModel.Name and part.Name ~= "GarbageParts" then
|
|
				return part
|
|
			elseif part.Name == playerModel.Name or part.Name == "GarbageParts" then
|
|
				return nil
|
|
			end
|
|
			part = part.Parent
|
|
		end
|
|
		return nil
|
|
|
|
	else
|
|
		while part ~= game.Workspace do
|
|
			if part:FindFirstChild("RobloxModel") then
|
|
				return part
|
|
			end
|
|
			part = part.Parent
|
|
		end
|
|
		return nil
|
|
	end
|
|
|
|
end
|
|
|
|
------------------------ End EyeDropper Code ---------------------------------------
|
|
|
|
|
|
|
|
|
|
------------------------ Start Selection Highlighting Code --------------------------
|
|
function setTerrainSelection(point)
|
|
	if selectionBox then
|
|
		local cell = game.Workspace.Terrain:WorldToCellPreferSolid(point)
|
|
		local cellCenter = game.Workspace.Terrain:CellCenterToWorld(cell.X, cell.Y, cell.Z)
|
|
		terrainSelectionBox.CFrame = CFrame.new(cellCenter)
|
|
		selectionBox.Adornee = terrainSelectionBox
|
|
	end
|
|
end
|
|
	
|
|
function setSelection(partOrModel)
|
|
	if partOrModel ~= currentSelection then
|
|
		clearSelection()
|
|
		currentSelection = partOrModel
|
|
		selectionBox.Adornee = currentSelection
|
|
	end
|
|
end
|
|
|
|
function clearSelection()
|
|
	if currentSelection ~= nil then
|
|
		for part, color in pairs(currentSelectionColors) do
|
|
			part.BrickColor = color
|
|
		end
|
|
		selectionBox.Adornee = nil
|
|
	end
|
|
	currentSelectionColors = {}
|
|
	-- I put these inside if statements, because we can't assume these exist. (Jahr, 12-29-2010)
|
|
	if currentSelection then currentSelection = nil end
|
|
	if selectionBox then selectionBox.Adornee = nil end
|
|
end
|
|
|
|
------------------------ End Selection Highlighting Code --------------------------
|
|
|
|
function autoAlignToFace()
|
|
	local aatf = Data.Stamp.CurrentParts[1]:FindFirstChild("AutoAlignToFace")
|
|
	if aatf then return aatf.Value else return false end
|
|
end
|
|
|
|
|
|
function autoAlignHelper()
|
|
	local model = Data.Stamp.CurrentParts[1]
|
|
	local aatfTag = model:FindFirstChild("AutoAlignToFace")
|
|
	if not aatfTag then
|
|
		aatfTag = Instance.new("IntValue")
|
|
		aatfTag.Name = "AutoAlignToFace"
|
|
		aatfTag.Parent = Data.Stamp.CurrentParts[1]
|
|
		aatfTag.Value = 3
|
|
	end
|
|
	aatfTag.Value = aatfTag.Value + 1
|
|
	if aatfTag.Value > 3 then aatfTag.Value = 0 end
|
|
end
|
|
|
|
function unstampableFaceHelper()
|
|
	if not Mouse or not Mouse.Target then return end
|
|
	local model = Mouse.Target
|
|
	if not model then return end
|
|
	if not model:FindFirstChild("RobloxModel") then model = model.Parent end
|
|
	if not model then return end
|
|
	if not model:FindFirstChild("RobloxModel") then return end
|
|
|
|
	local ufhTag = model:FindFirstChild("UnstampableFaces")
|
|
	if not ufhTag then
|
|
		ufhTag = Instance.new("StringValue")
|
|
		ufhTag.Name = "UnstampableFaces"
|
|
		ufhTag.Parent = model
|
|
		ufhTag.Value = ""
|
|
	end
|
|
	
|
|
	local hitFace = modelTargetSurface(model, game.Workspace.CurrentCamera.CoordinateFrame.p, Mouse.Hit.p)
|
|
|
|
	-- put string list into table form
|
|
	breakingFaceList = {}
|
|
	for bf = -3, 3 do
|
|
		breakingFaceList[bf] = false
|
|
	end
|
|
	for bf in string.gmatch(ufhTag.Value, "[^,]+") do
|
|
		breakingFaceList[tonumber(bf)] = true
|
|
	end
|
|
|
|
	-- toggle value of hit face
|
|
	breakingFaceList[hitFace] = not breakingFaceList[hitFace]
|
|
|
|
	-- put table form back into string value
|
|
	ufhTag.Value = ""
|
|
	local seenAValueSoFar = false
|
|
	for bf = -3, 3 do
|
|
		if bf ~= 0 then -- ignore 0 face, since that doesn't exist
|
|
			if breakingFaceList[bf] then
|
|
				if seenAValueSoFar then ufhTag.Value = ufhTag.Value .. "," .. tostring(bf)
|
|
				else ufhTag.Value = tostring(bf) seenAValueSoFar = true end
|
|
			end
|
|
		end
|
|
	end
|
|
end
|
|
|
|
function justificationHelper(whichAxis)
|
|
	local model = Data.Stamp.CurrentParts[1]
|
|
	local justTag = model:FindFirstChild("Justification")
|
|
	if not justTag then
|
|
		justTag = Instance.new("Vector3Value")
|
|
		justTag.Name = "Justification"
|
|
		justTag.Parent = Data.Stamp.CurrentParts[1]
|
|
		justTag.Value = Vector3.new(1, 1, 1)
|
|
	end
|
|
	local oldValue = justTag.Value
|
|
	if whichAxis == 1 then
|
|
		if oldValue.X == 2 then justTag.Value = Vector3.new(0, oldValue.Y, oldValue.Z)
|
|
		else justTag.Value = Vector3.new(oldValue.X+1, oldValue.Y, oldValue.Z) end
|
|
	elseif whichAxis == 2 then
|
|
		if oldValue.Y == 2 then justTag.Value = Vector3.new(oldValue.X, 0, oldValue.Z)
|
|
		else justTag.Value = Vector3.new(oldValue.X, oldValue.Y+1, oldValue.Z) end
|
|
	elseif whichAxis == 3 then
|
|
		if oldValue.Z == 2 then justTag.Value = Vector3.new(oldValue.X, oldValue.Y, 0)
|
|
		else justTag.Value = Vector3.new(oldValue.X, oldValue.Y, oldValue.Z+1) end
|
|
	end
|
|
end
|
|
|
|
function onInsertKeyDown(key)
|
|
	key = string.lower(key)
|
|
	if Data.Stamp.Dragger then
|
|
		if key == 'c' and Data.Stamp.CurrentParts[1].Name == "MegaClusterCube" and HighScalabilityLine.InternalLine and HighScalabilityLine.InternalLine.magnitude > 0 and HighScalabilityLine.Dimensions < 3 then
|
|
			HighScalabilityLine.MorePoints[HighScalabilityLine.Dimensions] = HighScalabilityLine.End
|
|
			HighScalabilityLine.MoreLines[HighScalabilityLine.Dimensions] = HighScalabilityLine.InternalLine
|
|
			HighScalabilityLine.Dimensions = HighScalabilityLine.Dimensions + 1
|
|
			HighScalabilityLine.NewHint = true
|
|
		end
|
|
|
|
		if key == 'r' and not autoAlignToFace() then
|
|
			-- Update orientation value if this is a fake terrain part
|
|
			if Data.Stamp.CurrentParts[1].Name == "MegaClusterCube" then
|
|
				local clusterValues = Data.Stamp.CurrentParts[1]:FindFirstChild("ClusterMaterial")
|
|
				if clusterValues and clusterValues:IsA("Vector3Value") then
|
|
					clusterValues.Value = Vector3.new(clusterValues.Value.X, clusterValues.Value.Y, (clusterValues.Value.Z+1)%4)
|
|
				end
|
|
			end
|
|
|
|
			-- Rotate the parts or all the parts in the model
|
|
			local ry = math.pi/2
|
|
			local rotCF = CFrame.fromEulerAnglesXYZ(0, ry, 0)
|
|
			gInitial90DegreeRotations = gInitial90DegreeRotations + 1
|
|
			if Data.Stamp.CurrentParts[1]:IsA("Model") or Data.Stamp.CurrentParts[1]:IsA("Tool") then
|
|
				for i, object in pairs(Data.Stamp.CurrentParts[1]:GetChildren()) do
|
|
					if object:IsA("Flag") then object = object.Handle end
|
|
					if object:IsA("Part") or object:IsA("TrussPart") or object:IsA("WedgePart") or object:IsA("CornerWedgePart") or object:IsA("Seat") or object:IsA("VehicleSeat") then
|
|
						object.CFrame = rotCF * object.CFrame
|
|
					end
|
|
				end
|
|
			else
|
|
				Data.Stamp.CurrentParts[1].CFrame = rotCF * Data.Stamp.CurrentParts[1].CFrame
|
|
			end
|
|
			-- After rotating, update the position
|
|
			configFound, targetCFrame = findConfigAtMouseTarget(Data.Stamp.TransparencyTable)
|
|
			if configFound then
|
|
				positionPartsAtCFrame3(Data.Stamp.CurrentParts[1], targetCFrame)
|
|
				
|
|
				-- update everything else in MouseMove
|
|
				onInsertMouseMove()
|
|
			end
|
|
		end
|
|
	end
|
|
	if key == 'e' then
|
|
		startEyeDropperOperation()
|
|
	elseif key == 'q' then
|
|
		pressedEsc = true
|
|
		if eyeDropperConnection then
|
|
			eyeDropperConnection:disconnect()
|
|
			eyeDropperConnection = nil
|
|
		end
|
|
		if eyeDropperMoveConnection then eyeDropperMoveConnection:disconnect() end
|
|
|
|
		if Mouse and not mouseButton1UpCon then mouseButton1UpCon = Mouse.Button1Up:connect(onInsertMouseButton1Up) end
|
|
|
|
		clearSelection()
|
|
		cancelAssetPlacement()
|
|
		Data.Loading.Cancelled = true
|
|
		signalInsertComplete("Main")
|
|
	end
|
|
	
|
|
	-- admin-only tools: helpful functions for construction purposes
|
|
	if adminAccess then
|
|
		if key == 'L' or key == 'l' then
|
|
			-- autoalign helper
|
|
			if Data.Stamp.Dragger then autoAlignHelper() onInsertMouseMove() end
|
|
		elseif key == 'U' or key == 'u' then
|
|
			-- unstampable face helper
|
|
			unstampableFaceHelper()
|
|
		--elseif key == 'C' or key == 'c' then
|
|
--			if Data.Stamp.Dragger then justificationHelper() end -- the 'c' stands for "Centering" since "j" is already reserved by GuiScript
|
|
		--end
|
|
		elseif key == 'X' or key == 'x' then -- change x justification
|
|
			if Data.Stamp.Dragger then justificationHelper(1) onInsertMouseMove() end
|
|
		elseif key == 'Y' or key == 'y' then -- change y justification
|
|
			if Data.Stamp.Dragger then justificationHelper(2) onInsertMouseMove() end
|
|
		elseif key == 'Z' or key == 'z' then -- change z justification
|
|
			if Data.Stamp.Dragger then justificationHelper(3) onInsertMouseMove() end
|
|
		end
|
|
	end
|
|
end
|
|
|
|
|
|
function onEquippedLocal(newMouse)
|
|
	Mouse = newMouse
|
|
|
|
	player = getPlayer()
|
|
|
|
	-- if equip goes through while in backpack (so getPlayer() returns nil), we don't want to process anything else
|
|
	if not player then return end
|
|
|
|
	--[[if game:FindFirstChild("NetworkClient") and game.CoreGui.Version >= 7 then only show billboards in online mode
|
|
		if not billBoardOwnerGui then billBoardOwnerGui = generateOwnerGui(player.Name) end
|
|
	end]]
|
|
|
|
	if isRestricted then
|
|
		if game.Workspace:FindFirstChild("BuildingAreas") then
|
|
			local areas = game.Workspace.BuildingAreas:GetChildren()
|
|
			for i = 1, #areas do
|
|
				if areas[i]:FindFirstChild("Player") and areas[i].Player.Value == Tool.Parent.Name then
|
|
					playerModel = areas[i]:FindFirstChild("PlayerArea")
|
|
					break
|
|
				end
|
|
			end
|
|
		end
|
|
	else
|
|
		playerModel = game.Workspace
|
|
|
|
		-- give them a topHint gui too, if they don't have it since the place won't already have it	
|
|
		if not player.PlayerGui:FindFirstChild("topHint") then
|
|
			local topHintGui = script.Parent:FindFirstChild("topHint")
|
|
			if topHintGui then
|
|
				topHintGui:Clone().Parent = player.PlayerGui
|
|
			end
|
|
		end
|
|
	end
|
|
|
|
	if not playerModel then return end
|
|
|
|
	-- used to move object when walking
|
|
	cameraChangeCon = game.Players.LocalPlayer.Character.Humanoid.Running:connect(function(speed)
|
|
		if speed > 0 then
|
|
			walking = true
|
|
			while walking and cameraChangeCon do
|
|
				onInsertMouseMove()
|
|
				wait(1.0/30.0)
|
|
			end
|
|
		else
|
|
			walking = false
|
|
		end
|
|
	end)
|
|
	if Mouse then
|
|
		mouseMoveCon = newMouse.Move:connect(onInsertMouseMove)
|
|
		mouseButton1DownCon = newMouse.Button1Down:connect(onInsertMouseButton1Down)
|
|
		mouseButton1UpCon = newMouse.Button1Up:connect(onInsertMouseButton1Up)
|
|
		newMouse.KeyDown:connect(onInsertKeyDown)
|
|
	end
|
|
|
|
	if(isRestricted) then
|
|
		local takenAreas = game.Workspace.BuildingAreas:GetChildren()
|
|
|
|
		waitForChild(player, "playerNumber")
|
|
|
|
		if(player.playerNumber.Value == 0) then
|
|
			buildingPlate = nil
|
|
			partModel = nil
|
|
		else
|
|
			waitForChild(game.Workspace, "BuildingAreas")
|
|
			local buildingAreas = game.Workspace.BuildingAreas
|
|
			waitForChild(buildingAreas, "Area"..tostring(player.playerNumber.Value))
|
|
			local targetArea = buildingAreas:FindFirstChild("Area"..tostring(player.playerNumber.Value))
|
|
			
|
|
			waitForChild(targetArea, "PlayerArea")
|
|
			waitForChild(targetArea.PlayerArea, "BasePlate")
|
|
|
|
			buildingPlate = targetArea.PlayerArea.BasePlate
|
|
			partModel = targetArea.PlayerArea
|
|
		end
|
|
	else
|
|
		partModel = game.Workspace
|
|
	end
|
|
|
|
	selectionBox = Instance.new("SelectionBox")
|
|
	selectionBox.Name = "Model Delete Selection"
|
|
	selectionBox.Color = BrickColor.Red()
|
|
	selectionBox.Adornee = nil
|
|
	selectionBox.Parent = player.PlayerGui
|
|
|
|
	alreadyMoving = false
|
|
end
|
|
|
|
|
|
function onUnequipped()
|
|
	Mouse = nil
|
|
	if mouseMoveCon then mouseMoveCon:disconnect() end
|
|
	if mouseButton1DownCon then mouseButton1DownCon:disconnect() end
|
|
	if mouseButton1UpCon then mouseButton1UpCon:disconnect() end
|
|
	if cameraChangeCon then cameraChangeCon:disconnect() cameraChangeCon = nil end
|
|
	if billBoardOwnerGui then billBoardOwnerGui:Remove() end
|
|
|
|
	cancelAssetPlacement()
|
|
|
|
	clearSelection()
|
|
	if selectionBox then selectionBox:Remove() end
|
|
end
|
|
----------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
-- Lua Start Script
|
|
Tool.Equipped:connect(function(newMouse) onEquippedLocal(newMouse) end)
|
|
|
|
waitForChild(variables,"InsertAsset")
|
|
waitForChild(variables.InsertAsset, "Updated")
|
|
variables.InsertAsset.Updated.Changed:connect(function(prop)
|
|
	if variables.InsertAsset.Updated.Value == true then
|
|
		pressedEsc = false
|
|
		beginInsertAssetStamp(variables.InsertAsset.AssetName.Value, variables.InsertAsset.AssetId.Value,
|
|
			variables.InsertAsset.Image.Value, variables.InsertAsset.StampMode.Value)
|
|
		variables.InsertAsset.Updated.Value = false
|
|
	end
|
|
end)
|
|
|
|
waitForChild(variables, "SwitchMode")
|
|
waitForChild(variables.SwitchMode, "Mode")
|
|
variables.SwitchMode.Changed:connect(function()
|
|
	if variables.SwitchMode.Value == true then
|
|
		if variables.SwitchMode.Mode.Value == "Clone" then
|
|
			startEyeDropperOperation()
|
|
		end
|
|
		variables.SwitchMode.Value = false
|
|
	end
|
|
end)
|
|
|
|
waitForChild(variables, "ReloadCurrentAsset")
|
|
variables.ReloadCurrentAsset.Changed:connect(function()
|
|
	if variables.ReloadCurrentAsset.Value == true then
|
|
		setupDraggableClone()
|
|
		variables.ReloadCurrentAsset.Value = false
|
|
	end
|
|
end)
|
|
|
|
Tool.Unequipped:connect(function() onUnequipped() end)
|
|
----------------------------------------------------------------------------------------
|
|
|
|
|
|
</ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="ScreenGui" referent="RBX101">
|
|
<Properties>
|
|
<string name="Name">topHint</string>
|
|
</Properties>
|
|
<Item class="ImageLabel" referent="RBX102">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<Content name="Image"><null></null></Content>
|
|
<string name="Name">_preview</string>
|
|
<UDim2 name="Position">
|
|
<XS>0</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>1</XS>
|
|
<XO>0</XO>
|
|
<YS>1</YS>
|
|
<YO>0</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<bool name="Visible">false</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
<Item class="Frame" referent="RBX103">
|
|
<Properties>
|
|
<bool name="Active">false</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">0</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<string name="Name">Bkg</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.5</XS>
|
|
<XO>-250</XO>
|
|
<YS>0</YS>
|
|
<YO>10</YO>
|
|
</UDim2>
|
|
<UDim2 name="Size">
|
|
<XS>0</XS>
|
|
<XO>400</XO>
|
|
<YS>0</YS>
|
|
<YO>40</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">3</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="TextButton" referent="RBX104">
|
|
<Properties>
|
|
<bool name="Active">true</bool>
|
|
<bool name="AutoButtonColor">true</bool>
|
|
<Color3 name="BackgroundColor3">4288914085</Color3>
|
|
<float name="BackgroundTransparency">1</float>
|
|
<Color3 name="BorderColor3">4279970357</Color3>
|
|
<int name="BorderSizePixel">1</int>
|
|
<bool name="ClipsDescendants">false</bool>
|
|
<bool name="Draggable">false</bool>
|
|
<token name="Font">0</token>
|
|
<token name="FontSize">5</token>
|
|
<bool name="Modal">false</bool>
|
|
<string name="Name">Label</string>
|
|
<UDim2 name="Position">
|
|
<XS>0.25</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>10</YO>
|
|
</UDim2>
|
|
<bool name="Selected">false</bool>
|
|
<UDim2 name="Size">
|
|
<XS>0.5</XS>
|
|
<XO>0</XO>
|
|
<YS>0</YS>
|
|
<YO>40</YO>
|
|
</UDim2>
|
|
<token name="SizeConstraint">0</token>
|
|
<token name="Style">0</token>
|
|
<string name="Text">Saved changes</string>
|
|
<Color3 name="TextColor3">4294967295</Color3>
|
|
<Color3 name="TextStrokeColor3">4278190080</Color3>
|
|
<float name="TextStrokeTransparency">1</float>
|
|
<float name="TextTransparency">0</float>
|
|
<bool name="TextWrap">false</bool>
|
|
<token name="TextXAlignment">2</token>
|
|
<token name="TextYAlignment">1</token>
|
|
<bool name="Visible">true</bool>
|
|
<int name="ZIndex">1</int>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX105">
|
|
<Properties>
|
|
<bool name="Disabled">true</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">Add</string>
|
|
<ProtectedString name="Source">-- This script's job is to destroy previous topHint instance (if exists) and clone and run a new _topHint script (naming it "topHint")
|
|
-- When this script is finished, it disables and resets itself.
|
|
|
|
function waitForChild(instance, name)
|
|
	while not instance:FindFirstChild(name) do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForNoChild(instance, name)
|
|
	while instance:FindFirstChild(name) do
|
|
		instance.ChildRemoved:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForAnyChild(instance)
|
|
	while not instance:GetChildren()[1] do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
waitForChild(script, "Label")
|
|
waitForChild(script, "Time")
|
|
waitForChild(script, "Width")
|
|
waitForChild(script.Parent, "_topHint")
|
|
waitForChild(script.Parent._topHint, "Label")
|
|
waitForChild(script.Parent._topHint, "HideTime")
|
|
waitForChild(script.Parent._topHint, "Width")
|
|
|
|
local width = 0.55--script.Width.Value
|
|
--width = math.min(0.55,width/script.Parent.AbsoluteSize.X)
|
|
|
|
local quickReplace = true
|
|
|
|
-- If there's already an instance, do you quickly replace the text and width (true), or animate out then in? (false)
|
|
|
|
if (script.Parent:FindFirstChild("topHint")~=nil) then
|
|
	-- If there's already an instance...
|
|
	if(quickReplace) then
|
|
		-- If quickReplace is true...
|
|
		local bkg = script.Parent.Bkg
|
|
		local label = script.Parent.Label
|
|
		local ys = bkg.Position.Y.Scale
|
|
		local yo = bkg.Position.Y.Offset
|
|
		bkg.Position = UDim2.new((1 - width)/2,0, ys, yo)
|
|
		bkg.Size = UDim2.new(width,0, 0, 40)
|
|
		label.Text = script.Label.Value
|
|
		script.Parent.topHint.HideTime.Value = time() + script.Time.Value
|
|
	else
|
|
		-- If quickReplace is false...
|
|
		script.Parent.Delete.Disabled = false
|
|
		-- Wait for instance to be removed
|
|
		waitForNoChild(script.Parent, "topHint")
|
|
		waitForNoChild(script.Parent, "Bkg")
|
|
		waitForNoChild(script.Parent, "Label")
|
|
	end
|
|
else
|
|
	-- There's no previous instance.
|
|
	-- Clone and enable a new instance
|
|
	local topHint = script.Parent._topHint:Clone()
|
|
	topHint.Parent = script.Parent
|
|
	topHint.Name = "topHint"
|
|
	topHint.Label.Value = script.Label.Value
|
|
	topHint.HideTime.Value = time() + script.Time.Value
|
|
	topHint.Width.Value = width
|
|
	topHint.Disabled = false
|
|
end
|
|
|
|
script.Disabled = true
|
|
</ProtectedString>
|
|
</Properties>
|
|
<Item class="NumberValue" referent="RBX106">
|
|
<Properties>
|
|
<string name="Name">Width</string>
|
|
<double name="Value">0</double>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="StringValue" referent="RBX107">
|
|
<Properties>
|
|
<string name="Name">Label</string>
|
|
<string name="Value"></string>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="NumberValue" referent="RBX108">
|
|
<Properties>
|
|
<string name="Name">Time</string>
|
|
<double name="Value">0</double>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX109">
|
|
<Properties>
|
|
<bool name="Disabled">true</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">_topHint</string>
|
|
<ProtectedString name="Source">function waitForChild(instance, name)
|
|
	while not instance:FindFirstChild(name) do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForNoChild(instance, name)
|
|
	while instance:FindFirstChild(name) do
|
|
		instance.ChildRemoved:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForAnyChild(instance)
|
|
	while not instance:GetChildren()[1] do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
-- This script creates the graphics for the new topHint, and animates it.
|
|
-- Before calling this script, we've already made sure: there's no other "topHint", "Bkg", and "Label"
|
|
-- Then, if time~=0, it waits "time" and then calls "Remove" script
|
|
|
|
waitForChild(script, "Label")
|
|
waitForChild(script, "HideTime")
|
|
waitForChild(script, "Width")
|
|
|
|
local container = script.Parent
|
|
local labelText = script.Label.Value
|
|
local hideTime = script.HideTime.Value
|
|
local width = script.Width.Value
|
|
|
|
-- SETTINGS
|
|
local tweenTime = 0.3 -- animation time (seconds)
|
|
local topY = -50
|
|
local bottomY = 10
|
|
local easing = "Sine.easeInOut"
|
|
--
|
|
|
|
local bkg = Instance.new("Frame")
|
|
bkg.Parent = container
|
|
bkg.Name = "Bkg"
|
|
bkg.Position = UDim2.new((1 - width)/2,0, ys, yo)
|
|
bkg.Size = UDim2.new(width,0, 0, 40)
|
|
bkg.Style = "RobloxRound"
|
|
|
|
function destroy()
|
|
	script.Parent.Delete.Disabled = false
|
|
end
|
|
|
|
local label = Instance.new("TextButton")
|
|
label.Parent = container
|
|
label.Name = "Label"
|
|
label.BackgroundTransparency = 1
|
|
label.FontSize = "Size14"
|
|
label.Position = UDim2.new((1 - width)/2,0, 0, topY)
|
|
label.Size = UDim2.new(width,0, 0, 40)
|
|
label.Text = labelText
|
|
label.TextColor3 = Color3.new(1, 1, 1)
|
|
label.MouseButton1Click:connect(destroy)
|
|
|
|
bkg:TweenPosition(UDim2.new(bkg.Position.X.Scale,bkg.Position.X.Offset,bkg.Position.Y.Scale,bottomY),
|
|
		Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
|
|
|
|
label:TweenPosition(UDim2.new(label.Position.X.Scale,label.Position.X.Offset,label.Position.Y.Scale,bottomY),
|
|
		Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
|
|
|
|
if(hideTime~=0) then
|
|
	while(time() < hideTime) do wait(0.1) end
|
|
	destroy()
|
|
end</ProtectedString>
|
|
</Properties>
|
|
<Item class="NumberValue" referent="RBX110">
|
|
<Properties>
|
|
<string name="Name">Width</string>
|
|
<double name="Value">0</double>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="StringValue" referent="RBX111">
|
|
<Properties>
|
|
<string name="Name">Label</string>
|
|
<string name="Value"></string>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="NumberValue" referent="RBX112">
|
|
<Properties>
|
|
<string name="Name">HideTime</string>
|
|
<double name="Value">0</double>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX113">
|
|
<Properties>
|
|
<bool name="Disabled">true</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">Delete</string>
|
|
<ProtectedString name="Source">function waitForChild(instance, name)
|
|
	while not instance:FindFirstChild(name) do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForNoChild(instance, name)
|
|
	while instance:FindFirstChild(name) do
|
|
		instance.ChildRemoved:wait()
|
|
	end
|
|
end
|
|
|
|
function waitForAnyChild(instance)
|
|
	while not instance:GetChildren()[1] do
|
|
		instance.ChildAdded:wait()
|
|
	end
|
|
end
|
|
|
|
local topHint = script.Parent:FindFirstChild("topHint")
|
|
local bkg = script.Parent:FindFirstChild("Bkg")
|
|
local label = script.Parent:FindFirstChild("Label")
|
|
|
|
-- SETTINGS
|
|
local tweenTime = 0.3 -- animation time (seconds)
|
|
local topY = -50 -- top position (Y Offset)
|
|
local easing = "Back.easeInOut"
|
|
--
|
|
|
|
if(topHint~=nil) then
|
|
	topHint:Remove()
|
|
end
|
|
|
|
if(bkg~=nil) then
|
|
	bkg:TweenPosition(UDim2.new(bkg.Position.X.Scale,bkg.Position.X.Offset,bkg.Position.Y.Scale,topY),
|
|
		Enum.EasingDirection.InOut,Enum.EasingStyle.Quad,tweenTime,true)
|
|
end
|
|
|
|
if(label~=nil) then
|
|
	label:TweenPosition(UDim2.new(label.Position.X.Scale,label.Position.X.Offset,label.Position.Y.Scale,topY),
|
|
		Enum.EasingDirection.InOut,Enum.EasingStyle.Quad,tweenTime,true)
|
|
end
|
|
|
|
wait(tweenTime)
|
|
if(bkg~=nil) then bkg:Remove() end
|
|
if(label~=nil) then label:Remove() end
|
|
|
|
script.Disabled = true
|
|
</ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
<Item class="LocalScript" referent="RBX114">
|
|
<Properties>
|
|
<bool name="Disabled">true</bool>
|
|
<Content name="LinkedSource"><null></null></Content>
|
|
<string name="Name">_readme</string>
|
|
<ProtectedString name="Source">--
|
|
-- Top Hint
|
|
--
|
|
-- * This is a string of text that's top-centered in the window. (White text on black background)
|
|
-- * It should be used for messages from the client, and never from the place creator.
|
|
--
|
|
-- FEATURES:
|
|
-- * Auto-hides previous messages before showing yours.
|
|
-- * Always centered, regardless of length.
|
|
-- * Clicking the message hides it.
|
|
--
|
|
-- USE IT FOR:
|
|
-- * Quick task-related (non-essential) hints
|
|
-- * Showing the current modal state
|
|
-- * Tool hints (for the currently equipped tool)
|
|
-- * Keyboard shortcuts
|
|
--
|
|
-- NEVER USE IT FOR:
|
|
-- * Essential information (Use a popup instead)
|
|
-- * Messages from users or place creators. This is for client messages only.
|
|
--
|
|
-- ARGUMENTS:
|
|
-- Label: The message
|
|
-- Width: Text and background width (pixels) -- This should be removed when textWidth is added to Lua
|
|
-- Time: Seconds before hiding itself (If 0, it never hides)
|
|
--
|
|
-- USAGE:
|
|
local topHint = script.Parent.topHint -- path to topHint ScreenGui
|
|
topHint.Add.Label.Value = "Press D to return to main menu."
|
|
topHint.Add.Width.Value = 290
|
|
topHint.Add.Time.Value = 7
|
|
topHint.Add.Disabled = true -- flip it off then on, in case it's currently running.
|
|
topHint.Add.Disabled = false
|
|
--
|
|
-- TO HIDE MANUALLY:
|
|
topHint.Delete.Disabled = false
|
|
-- Clicking the message also hides it.</ProtectedString>
|
|
</Properties>
|
|
</Item>
|
|
</Item>
|
|
</Item>
|
|
</roblox> |