Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Source code extracted from https://www.roblox.com/library/741785194/VisualPlugin-useful-building-plugin
- --'Proudly made in the UK' ... by an Anglophile living in the US.
- --Look around for NOTE comments all over the source code; thay contain helpful tips on using VisualPlugin.
- local version={shape='rbxasset://textures/ui/Lobby/Buttons/scroll_up.png',sub='C.U.L8r'}
- local defaults={
- planeV={1,0,1},
- planeS={.7,0,1},
- planeTop={false},
- planeTrans={.4,0,1},
- selBoxSize={.05,0,1},
- --1 for box, 2 for plane.
- selMode={2,1,nil,1},
- maxParts={187,0},
- decRound={3},
- debugP={false},
- saveIncrs={true},
- newPartDist={7,0},
- guiScaling={1,.5},
- handleIntensity={1},
- selectsFirst={true},
- selectLocked={false},
- fromAllEdges={false},
- screenTipDelay={.5,0},
- maxUndo={-1,-1,nil,1},
- resizeNegative={false},
- blocking={false,'NO_TOUCH'},
- --Maximum ancestry to search.
- selectsSameCFrame={2,0,nil,1},
- clearAllOnIncrementClear={false},
- mods={{
- --[[
- game.workspace:
- findFirstChild
- 'ModuleTest',
- ]]
- }},
- --NOTE: Some settings are restricted from editing!
- forceRestart={false,'NO_TOUCH'},
- usedB4={true,'NO_TOUCH'},
- }
- local materialIds={
- SmoothPlastic
- =703387192,
- CorrodedMetal
- =843920084,
- DiamondPlate
- =844342054,
- Cobblestone
- =843920069,
- WoodPlanks
- =843920072,
- Concrete
- =843920069,
- Granite
- =843920074,
- Plastic
- =844342043,
- Fabric
- =843920050,
- Marble
- =843920026,
- Pebble
- =843920063,
- Brick
- =843920065,
- Slate
- =843920055,
- Grass
- =843920051,
- Metal
- =845896371,
- Wood
- =843920048,
- Sand
- =843920044,
- Foil
- =844342044,
- Neon
- =703387192,
- Ice
- =843920041,
- Glass
- =844342043,
- }
- local materialCount=0
- for i,g in pairs(materialIds) do
- materialCount=materialCount+1
- end
- --------------------------------------------------------------------------------------------------------
- local plugin=getfenv().plugin
- print('The plugin object does'
- ..(plugin and''or'n\'t')..' exist.')
- while not script.Parent:
- isA'Tool' and not plugin do
- wait()
- end
- local player=game.
- Players.LocalPlayer
- local tool=not plugin
- and script.Parent or nil
- local mouse=(plugin and plugin or player):GetMouse()
- local core=plugin and game.CoreGui or player.PlayerGui
- local util=require(script
- :WaitForChild'Util')
- local active
- local permsF=require(script:
- WaitForChild'AdminPermissions')
- local partF=permsF.OnNewPartCreation
- local verify=permsF.VerifySelection
- local selFuncs
- local commands
- local canDoStuff
- local rs=game['Run Service']
- local gui=script.VisualPlugin:clone()
- local handlesF=script.Handles:clone()
- local mf=gui:WaitForChild'MainFrame'
- local cmds=mf:WaitForChild'Commands'
- local config=gui:WaitForChild'Config'
- local sm=mf:WaitForChild'Submodes'
- local smTemplate=sm['1']:clone()
- local incBox=sm.Increment.TextBox
- local clTemplate=script:
- WaitForChild'SpecialGui'.Colour
- clTemplate.Visible=false
- local id=plugin and plugin:
- GetStudioUserId()or player.userId
- local hue=1.07773e-8*id
- -3.1896e-17*id^2+.5
- --NOTE: There would be a VIP feature based on the client's user ID.
- local vip=id>0
- and id<1630229
- --NOTE: The hue of your plugin client varies by the client's user ID.
- function accColour()
- return id<1 and Color3
- .new(.7,.7,.7)or Color3
- .fromHSV(hue%1,.75,.95)
- --return BrickColor.new'Gold'.Color
- end
- --Indicies are numbers, values are part tables.
- --Index 0 of said table is optionally a group
- local selGroups={}
- --Indicies are numbers, values are selection tables.
- local selections={}
- --Indicies are numbers, values are parts.
- local selI
- --Stealing from DataBrain? Never mind?
- --[[
- local src=game.InsertService:LoadAsset(284294874):children()[1].Source:gsub('\n',' ')
- local matStr=select(3,src:find('local materials = ({.+}) local BasicMaterials'))
- local materials=loadstring('return '..matStr)()
- local basicMatStr=select(3,src:find('local BasicMaterials = ({.+}) local button'))
- local basicMaterials=loadstring('return '..basicMatStr)()
- ]]
- if plugin then
- defaults.maxUndo
- [2]='NO_TOUCH'
- else
- if not plugin then
- defaults.selectLocked
- [2]='NO_TOUCH'
- end
- end
- local toolSettings={}
- local settings=setmetatable({},{
- __index=function(t,i)
- local v=plugin and
- plugin:GetSetting(i)
- or toolSettings[i]
- if v=='true' then
- return true
- elseif v=='false' then
- return false end
- return v
- end,
- __newindex=function(t,i,v)
- i=tostring(i)
- if plugin then
- if type(v)=='boolean' then
- v=tostring(v)end
- plugin:SetSetting(i,v)
- else
- toolSettings[i]=v
- end
- if reRender then
- reRender()
- end
- end,
- })
- if defaults.forceRestart[1]
- or not settings.usedB4
- or not plugin then
- print'Settings restored.'
- for i,g in pairs(defaults) do
- settings[i]=g[1]
- end
- else
- for i,g in pairs(defaults) do
- if settings[i]==nil --THIS IS WHY THE BOOLEAN SETTINGS WERE SWITCHING TO TRUE;
- --'not settings[i]' improperly returns true when the setting it set to false.
- or g[2]=='NO_TOUCH' then
- toolSettings[i]=g[1]
- settings[i]=g[1]
- end
- end
- end
- local Print=print
- local doPrint=settings.debugP
- local print=function(...)
- if doPrint then
- return Print(unpack(0<#{...}
- and{os.time(),'-',...}or{}))
- end
- end
- local twIndex=0
- local toolWaypoints={}
- local origData,pData={},{}
- function createWaypoint(t)
- if plugin then
- game.ChangeHistoryService
- :SetWaypoint'0x18E014'
- else
- if not t then
- t={}
- local proceed
- for i2 in pairs(origData) do
- if tonumber(i2) then
- local n=pData[i2]
- local o=origData[i2]
- if not proceed and(o.cf~=n.CFrame
- or o.size~=o.part.Size)then
- proceed=true
- end
- t[i2]={undo=
- {cf=o.cf,size=o
- .size},redo={cf=
- n.cf,size=n.size
- },parts=o.parts}
- end
- end
- if not proceed then
- return
- end
- end
- addToolWaypoint(t)
- end
- end
- function addToolWaypoint(t)
- print'Tool waypoint created.'
- --Clears the stuff after the last state.
- for i=1,#toolWaypoints do
- toolWaypoints[i]
- =toolWaypoints[i+twIndex]
- end
- --Adds a new position thingy.
- twIndex=0
- local max=settings.maxUndo
- for i=max>-1 and max-1
- or#toolWaypoints,0,-1 do
- toolWaypoints[i+1]
- =toolWaypoints[i]
- or t
- end
- end
- function undo()
- if plugin and game.
- ChangeHistoryService
- :GetCanUndo() then
- game.ChangeHistoryService:Undo()
- elseif twIndex
- <#toolWaypoints then
- twIndex=twIndex+1
- local w=toolWaypoints[twIndex]
- print('The mode is '..(w.mode
- or'null')..' ('..twIndex..')')
- if w.mode=='del'then
- for i,g in pairs(w[1]) do
- g.part.Parent=g.par
- end
- elseif w.mode=='ins'then
- for i,g in pairs(w[1]) do
- removeSelection(g.part)
- g.part.Parent=nil
- end
- elseif w.mode=='colour'then
- local parents={}
- for i,g in pairs(w[2]) do
- removeSelection(g[1])
- parents[i]=g[1].Parent
- for i2,g2 in pairs(g) do
- g2.Parent=nil
- end
- end
- for i,g in pairs(w[1]) do
- for i2,g2 in pairs(g) do
- g2.Parent=parents[i]
- end
- addSelection(g[1])
- end
- else
- for i,g in pairs(w) do
- for i2,g2 in pairs(g.parts) do
- setCFrame(g2,g.undo.cf)
- setSize(g2,g.undo.size)
- end
- end
- end
- end
- setSubmode()
- end
- function redo()
- if plugin and game.
- ChangeHistoryService
- :GetCanRedo() then
- game.ChangeHistoryService:Redo()
- elseif twIndex>0 then
- twIndex=twIndex-1
- local w=toolWaypoints[twIndex+1]
- if w.mode=='del'then
- for i,g in pairs(w[1]) do
- removeSelection(g.part)
- g.part.Parent=nil
- end
- elseif w.mode=='ins'then
- for i,g in pairs(w[1]) do
- g.part.Parent=g.par
- end
- elseif w.mode=='colour'then
- local parents={}
- for i,g in pairs(w[1]) do
- removeSelection(g[1])
- parents[i]=g[1].Parent
- for i2,g2 in pairs(g) do
- g2.Parent=nil
- end
- end
- for i,g in pairs(w[2]) do
- for i2,g2 in pairs(g) do
- g2.Parent=parents[i]
- end
- addSelection(g[1])
- end
- else
- for i,g in pairs(w) do
- for i2,g2 in pairs(g.parts) do
- setCFrame(g2,g.redo.cf)
- setSize(g2,g.redo.size)
- end
- end
- end
- end
- setSubmode()
- end
- function duplicate()
- local t,c={}
- for i,g in pairs(selGroups) do
- for i2,g2 in pairs(g) do
- c=g2:clone()
- c.Parent=g2.Parent
- selGroups[i][i2]=c
- t[#t+1]={part=c
- ,par=g2.Parent}
- end
- selections[i].destroy()
- selections[i]=selFuncs
- [settings.selMode][2](c)
- end
- setMode(nil,1)
- createWaypoint
- {mode='ins',t}
- upd8GameSel()
- end
- function delete()
- local t=getSelection()
- for i,g in pairs(t) do
- removeSelection(g)
- t[i]={part=g,
- par=g.Parent}
- g.Parent=nil
- end
- createWaypoint
- {mode='del',t}
- t={}
- end
- --------------------------------------------------------------------------------------------------------
- function selContains(p)
- for i,g in pairs(selGroups) do
- for i2,g2 in pairs(g) do
- if g2==p then
- return{g,i,i2}
- end
- end
- end
- end
- function clearSelection()
- for i,g in pairs(selections) do
- g.destroy()end
- selections={}
- selGroups={}
- setMode()
- end
- function getSelection(groups)
- local t={}
- for i,g in pairs(selGroups) do
- if groups and g[0] then
- t[#t+1]=g[0]
- else
- for i=1,#g do
- t[#t+1]=g[i]
- end
- end
- end
- return t
- end
- --[[
- function setSelection(t)
- clearSelection()
- if active then
- for i,g in pairs(t) do
- if type(g)~='table' then
- g={g}end
- selGroups[i]=g
- selections[i]=selFuncs
- [settings.selMode][2](g[1])
- end
- setMode(nil,settings.
- selectsFirst and 1 or#t)
- end
- return t
- end
- function setSel(t)
- local t=t or{}
- for i=1,math.max(#selGroups,#t) do
- selGroups[i]=t[i]end
- end
- ]]
- local addWhenUpd8=true
- function upd8GameSel()
- if plugin then
- addWhenUpd8=false
- game.Selection:Set(
- getSelection(true))
- addWhenUpd8=true
- end
- end
- --The part does not have to be a BasePart.
- function addSelection(p,solo)
- if active then
- local solo=solo
- and not p:isA'Model'
- local t=solo and{{p
- }}or getSelParts(p)
- local c=#selGroups
- if #t>0 then
- if t[1][1]:
- isA'BasePart'then
- for i=1,#t do
- local doIt=true
- if not solo then
- for i2=1,#t[i] do
- if selContains(t
- [i][i2]) then
- doIt=false
- end
- end
- end
- if doIt then
- c=c+1
- t[i][0]=t[0]
- selGroups[c]=t[i]
- selections[c]=selFuncs
- [settings.selMode]
- [2](t[i][1])
- end
- end
- print'Selecktetto.'
- setMode(nil,settings.selectsFirst and 1 or c)
- end
- --Returns the part if success.
- return p
- end
- end
- end
- function removeSelection(p)
- local parts=selContains(p)
- if not parts then
- return end
- local t=getSelParts(p)
- for i in pairs(selGroups) do
- local sel=selGroups[i]
- while sel and((t[0]and selGroups
- [i][0]==t[0])or sel==parts[1])do
- selections[i].destroy()
- sel=selGroups[i+1]
- for i2=i+1,#selGroups+1 do
- selections[i2-1]
- =selections[i2]
- selGroups[i2-1]
- =selGroups[i2]
- end
- end
- end
- local pl=#selGroups~=1
- print('There '..(pl and'are'or'is')
- ..' currently '..#selGroups..' part'
- ..(pl and's'or'')..' selected after removal.')
- setMode(nil,selI
- >#selections and
- (settings.
- selectsFirst and 1
- or#selections)
- or nil)
- return p
- end
- function toggleSelection(p,...)
- if not removeSelection(p,...) then
- addSelection(p,...)
- end
- end
- local stInfo,snapped={}
- local submode,increment
- local handles
- local adornee
- local mode=1
- local secK=not plugin
- and'Control'or'Shift'
- local secondOn
- local binders={}
- game:service'UserInputService'
- .InputBegan:connect(function(inp)
- if inp.UserInputType
- .Name=='Keyboard'
- and inp.KeyCode
- .Name:find(secK)then
- print'Special key pressed.'
- secondOn=true
- end
- end)
- game:service'UserInputService'
- .InputEnded:connect(function(inp)
- if inp.UserInputType
- .Name=='Keyboard'
- and inp.KeyCode
- .Name:find(secK)then
- print'Special key released.'
- secondOn=false
- end
- end)
- function bindH(t)
- if active then
- game.ContextActionService
- :BindAction(t.name,
- function(nme,state)
- if state.Name
- =='Begin'then
- if not secondOn
- ==not t.second then
- t.func()
- else
- for i,g in pairs(binders) do
- if g~=t
- and g.bind
- ==t.bind then
- g.func()
- end
- end
- end
- end
- end,false
- ,t.bind)
- end
- end
- function bind(
- n,f,k,second)
- binders
- [n]={
- bind=k,
- func=f,
- name=n,
- second=
- second}
- local override=true
- --[[
- for i,g in pairs(binders) do
- if g.bind==k and g.
- second~=second then
- override=false
- end
- end
- ]]
- if override then
- bindH(binders[n])
- end
- end
- function unbind(n)
- game.ContextActionService
- :UnbindAction(n)
- binders[n]=nil
- end
- function rsBind(n,f)
- rs:BindToRenderStep(n,666,f)
- end
- function rsUnbind(n,f)
- rs:UnbindFromRenderStep(n)
- end
- local tempParts={}
- --Used for creating a bounding box.
- function forObjCentre(handles,a)
- local p=Instance.new'Part'
- p.Size=util.bounding(a)[2]
- p.Position=a.Position
- --p.Transparency=1
- p.Anchored=true
- --p.Parent=game.workspace
- handles.Adornee=p
- tempParts[1]=p
- return p
- end
- function forGroup(handles,a)
- if not plugin then
- return forObjCentre(handles,a)
- end
- local p=Instance.new'Part'
- p.Position,p.Size=unpack(util
- .bounding(getSelection()))
- --p.Transparency=1
- p.Anchored=true
- --p.Parent=game.workspace
- handles.Adornee=p
- tempParts[1]=p
- return p
- end
- local edgeSaved
- function forEdge(handles,a,changed)
- local p=Instance.new'Part'
- handles.Adornee=nil
- p.Anchored=true
- tempParts[1]=p
- if changed or not edgeSaved then
- local sel=Instance.new'SelectionBox'
- sel.SurfaceColor3=accColour()
- sel.SurfaceTransparency=0
- sel.Parent=core
- sel.Transparency=1
- sel.Adornee=p
- local cft={}
- local edge,relV3,mag
- for i,g in pairs(settings.fromAllEdges
- and(function()
- local t={}
- scanParts(game.
- workspace,t,
- function(p)
- return p:
- isA'BasePart'
- end)
- return t
- end)()or selGroups) do
- cft[i]=util.surroundingCF(type(g
- )=='table' and g[1] or g)
- end
- local dunn
- spawn(function()
- while not dunn and wait() do
- if mouse.Hit then
- mag=nil
- for i,g in pairs(cft) do
- for i2,g2 in pairs(g) do
- local cMag=(mouse.
- Hit.p-g2[2].p).magnitude
- if not mag or cMag<mag then
- edge=g[i2][2]
- relV3=g2[1]
- mag=cMag
- end
- end
- end
- local dist=math.min(1/10*(
- game.workspace.CurrentCamera.
- CFrame.p-edge.p).magnitude,1)
- p.Size=dist*Vector3.new(1,1,1)
- p.CFrame=edge
- end
- end
- end)
- mouse.Button1Up:wait()
- p.Size=Vector3.new()
- edgeSaved=edge
- sel:destroy()
- dunn=true
- else
- p.CFrame=edgeSaved
- end
- p.Size=Vector3.new()
- handles.Adornee=p
- return p
- end
- function partDataTable(p)
- local bm=p[1]:FindFirstChildOfClass'BlockMesh'
- return{cf=p[1].CFrame,size=p[1].Size*(
- bm and bm.Scale or Vector3.new(1,1,1)),
- anchored=p[1].Anchored,parts=p}
- end
- function newPart()
- local sG=selGroups[1]
- local p=Instance.new'Part'
- local dist=settings.newPartDist
- local pos
- if plugin then
- local cf=game.workspace.CurrentCamera.CFrame
- pos=cf.p+dist*cf.lookVector
- else
- local cf=player.Character:GetPrimaryPartCFrame()
- pos=cf.p+dist*Vector3.new(cf.lookVector.x,0,cf.lookVector.z)
- end
- p.Position=pos
- p.Size=Vector3.new(1,1,1)
- p.Parent=sG and(sG[0]or sG[1
- ].Parent)or game.workspace
- p.BottomSurface='Smooth'
- p.TopSurface='Smooth'
- p.Anchored=true
- addSelection(p)
- upd8GameSel()
- if not plugin then
- partF(p,player)end
- return p
- end
- local welds=game
- .JointsService
- :children()
- function weldSelection()
- local main=selGroups[selI][1]
- for i,g in pairs(selGroups) do
- for i2,g2 in
- pairs(g) do
- if i2>=2
- or i~=selI then
- local w=Instance.new'Weld'
- w.Parent=game.JointsService
- w.Part0,w.Part1,w.C0
- =main,g2,main.CFrame
- :inverse()*g2.CFrame
- welds[#welds+1]=w
- end
- end
- end
- end
- function getWelded(p)
- local t,T={}
- if not p then
- T=getSelection()
- elseif type(p)
- =='userdata'then
- T={p
- }end
- for i,g in pairs(welds) do
- for i2,g2 in pairs(T) do
- local doIt=p~=g2
- for i3,g3 in pairs(t) do
- if( g3.Part0==g.Part0
- and g3.Part1==g.Part1)
- or( g3.Part1==g.Part0
- and g3.Part0==g.Part1)then
- doIt=false end end
- if doIt and(g.Part0==g2 or g.Part1==g2)then
- t[#t+1]=g
- for i3,g3 in pairs(getWelded(g2)) do
- t[#t+1]=g3
- end
- end
- end
- end
- return t
- end
- function begin(p,a,t)
- if t.groupI*t
- .selI<2 then
- stInfo={}
- origData={}
- createST()
- snapped=0
- upd8ST()
- origData.temp={}
- for i,g in pairs(tempParts) do
- origData.temp[i]
- =partDataTable{g}
- end
- for i,g in pairs(getWelded()) do
- g.Parent=nil end
- end
- if t.groupI<2 then
- local c={}
- for i,g in pairs(
- selGroups
- [t.selI]) do
- c[#c+1]=g
- end
- origData[t.selI]
- =partDataTable(c)
- end
- p.Anchored=true
- end
- function release(p,a,t)
- p.Anchored=origData
- [t.selI].anchored
- if t.index<2 then
- pData={}
- print'Released.'
- removeST()
- end
- pData[t.selI]
- =partDataTable{p}
- if t.last then
- createWaypoint()
- for i,g in pairs(getWelded()) do
- g.C0=g.Part0.
- CFrame:inverse()
- *g.Part1.CFrame
- g.Parent=game.JointsService
- end
- end
- end
- --NOTE: This code makes it possible for the server to move parts for FE compatibility.
- local cp=require(script.CrossPeer)
- function callCPFunc(name,...)
- cp[name](...)
- if not plugin then
- script.Move:FireServer(name,...)
- end
- end
- function setSize(...)
- callCPFunc('setSize',...)
- end
- function setCFrame(...)
- callCPFunc('setCFrame',...)
- end
- local colourMode={
- materialInfo=(function()
- local t={}
- for i,g in pairs(materialIds) do
- t[i]={transparency
- =i=='Plastic'and 0
- or 01,dim={0,1,0}}
- end
- return t
- end)(),
- }
- function colourFromCoords(v,brickColor)
- local c=Color3
- .fromHSV(v[1],1
- -v[2],(1-v[3]))
- if brickColor then
- return BrickColor.
- new(c).Color
- end
- return c
- end
- function lookGui()
- local upd88s={}
- local mat=script.
- SpecialGui.Material:clone()
- local fr,c=mat.Table.Frame,0
- for i,g in pairs(materialIds) do
- local sl=c==0 and
- fr or fr:clone()
- local il=sl
- .ImageLabel
- sl.ImageLabel.Image
- ='rbxassetid://'..g
- il.ImageRectSize
- =140*Vector2.new(5
- ,7/materialCount)
- il.TextLabel.Text=i
- sl.LayoutOrder=c
- sl.Name=i
- sl.Parent
- =mat.Table
- c=c+1
- local function upd88()
- local il=sl
- .ImageLabel
- local colour
- =colourFromCoords(
- colourMode.
- materialInfo[
- i].dim,true)
- local trans
- =colourMode.
- materialInfo[i
- ].transparency
- il.TransDisplay.
- BackgroundTransparency=trans
- sl.ImageLabel.TransDisplay.
- BackgroundColor3=colour
- il.ImageColor3=colour
- sl.ImageLabel
- .TextBox.Text
- =toNum(trans)
- local eCol=.1313*colour
- .r+.6781*colour.g+.1566
- *colour.b>=.5 and Color3
- .new()or Color3.new(1,1,1)
- il.TextBox.TextColor3,il
- .TextLabel.TextColor3,il
- .TransDisplay.TextColor3
- ,il.Frame.BackgroundColor3
- =eCol,eCol,eCol,eCol
- end
- upd88s[i
- ]=upd88
- il.TextBox.FocusLost
- :connect(function()
- local txt=il.
- TextBox.Text
- local n=tonumber(txt)
- if n and 0<=n
- and n<=1 then
- colourMode.materialInfo[i].
- transparency=tonumber(txt)
- end
- upd88()
- end)
- il.TransDisplay.
- MouseButton1Down:
- connect(function()
- colourMode.materialInfo
- [i].dim=colourGui(mat.
- Colours,colourMode
- .materialInfo[i].
- dim,true,i)upd88()
- end)
- upd88()
- end
- mat.Colour.
- MouseButton1Down:
- connect(function()
- local dim=colourGui(mat.Colours
- ,colourMode.materialInfo.Plastic
- .colour,true,'All materials')
- for i,g
- in pairs(colourMode
- .materialInfo) do
- g.dim=dim
- upd88s[i]()
- end
- end)
- return mat,function()
- local doIt
- for i2,g2 in pairs(colourMode
- .materialInfo) do
- if g2.transparency<1 then
- doIt=true
- end
- end
- if doIt then
- local oParts,nParts={},{}
- for i,g in pairs(selGroups) do
- selections[i]:destroy()
- local parent=g[1].Parent
- oParts[i]={}nParts[i]={}
- for i2,g2 in pairs(g) do
- g2.Parent=nil
- oParts[i][1
- +#oParts
- [i]]=g2
- end
- local count=0
- selGroups[i]=g
- for i2,g2 in pairs(colourMode
- .materialInfo) do
- if g2.transparency<1 then
- local p=g[1]:clone()
- p.Material=i2
- p.Parent=parent
- p.Transparency=g2.transparency
- p.Color=colourFromCoords(g2.dim)
- count=count+1
- g[count]=p
- nParts[i][1
- +#nParts
- [i]]=p
- end
- end
- for i2=#g,count+1,-1 do
- g[i2]=nil
- end
- selections[i]=selFuncs
- [settings.selMode][2](g[1])
- end
- createWaypoint{oParts,
- nParts,mode='colour'}
- upd8GameSel()
- else
- warn'You can\'t do it when all materials are invisible!'
- end
- end
- end
- function colourGui(parent,dim,brickColor,str)
- print'Colour grid creates.'
- local col=clTemplate:clone()
- local chuser=col.Choosers
- local p=chuser.ColourFrame
- local sl=chuser.SlideFrame
- local dim=dim or{0,1,0}
- local pC=p.Colour
- col.Parent=parent
- local colourT={}
- col.Visible=true
- col.Desc.Text
- =str or''
- wait()
- local cSize=p.AbsoluteSize
- chuser.Size=chuser.Size-UDim2
- .new(0,cSize.x%8,0,cSize.y%8)
- local X,Y=p.AbsoluteSize
- .x/8,p.AbsoluteSize.y/8
- --print(X,Y)
- local function
- updateGrid(pos)
- local colour=colourFromCoords(dim,brickColor)
- for x=0,X do
- for y=1,Y do
- local c=colourFromCoords(x>0
- and{(x-.5)/X,(y-.5)/Y,dim[3]
- }or{dim[1],dim[2],(y-.5)
- /Y},brickColor and x>0)
- colourT[x][y].BackgroundColor3=c
- end
- end
- local b
- if colour then
- b=BrickColor.new(colour)
- col.BrickColorButton.Colour.
- BackgroundColor3=b.Color
- col.Color3Button.Colour.
- BackgroundColor3=colour
- end
- col.Value.Text
- =colour and(brickColor
- and b.Number..' '..b.Name
- or math.floor(255*colour.r)..' '
- ..math.floor(255*colour.g)..' '
- ..math.floor(255*colour.b))or''
- end
- for x=0,X do
- colourT[x]={}
- for y=1,Y do
- local c=(x>0 or y>1)
- and pC:clone() or pC
- c.LayoutOrder=x+y*X
- colourT[x][y]=c
- c.Parent=x>0
- and p or sl
- end
- end
- p.InputBegan:connect(function(input)
- if input.UserInputType.
- Name=='MouseButton1' then
- local pos=input.Position
- pos=(Vector2.new(pos.X,pos
- .Y)-p.AbsolutePosition
- )/Vector2.new(X*8,Y*8)
- colourMode.colour
- =colourFromCoords({pos.X,
- pos.Y,dim[3]},brickColor)
- dim[1],dim[2]
- =pos.X,pos.Y
- updateGrid(pos)
- end
- end)
- sl.InputBegan:connect(function(input)
- if input.UserInputType.
- Name=='MouseButton1' then
- local pos=(input.Position.Y
- -p.AbsolutePosition.Y)/Y/8
- colourMode.colour
- =colourFromCoords({dim[1
- ],dim[2],pos},brickColor)
- dim[3]=pos
- updateGrid(pos)
- end
- end)
- col.BrickColorButton
- .MouseButton1Down
- :connect(function()
- brickColor
- =true
- updateGrid()
- end)
- col.Color3Button
- .MouseButton1Down
- :connect(function()
- brickColor
- =false
- updateGrid()
- end)
- updateGrid()
- col.Button.MouseButton1Down:wait()
- print'Finally.'
- col:destroy()
- return dim
- end
- commands={
- {name='move',
- key='z',
- colour=Color3.new(),
- handles=handlesF.MoveHandles,
- current={
- submode=1,
- incr={1},
- },
- submodes={
- 'axis',
- 'first',
- 'object',
- 'similar',
- 'axis-oid',
- },
- submodeFunc={
- [1]=forGroup,
- [5]=forObjCentre,
- },
- MouseDrag=function(part,main,i,face,dist)
- local new,isBloqued
- local initial=part.CFrame
- local orig=origData[i.selI].cf
- local inc=commands[mode].current.incr[1]
- snapped=math.floor(dist/inc+.5)*inc
- local sm=commands[mode].current.submode-1
- if sm<1 then
- new=orig+snapped*Vector3.FromNormalId(face)
- elseif sm<2 then
- new=orig+main.CFrame
- [({'right','up','look'})
- [util.axisIndexFromNormal(face)]..'Vector']*
- snapped*util.signForNormal(face)
- elseif sm<3 then
- new=orig*CFrame.new(snapped*
- Vector3.FromNormalId(face))
- elseif sm<4 then
- new=orig*CFrame.new(
- snapped*Vector3.FromNormalId(
- util.localNormal(
- part,util.globalNormal(main,face))))
- elseif sm<5 then
- new=orig*CFrame.new(
- snapped*Vector3.FromNormalId(
- util.localNormal(part,face)))
- end
- if i.groupI<2 and i.isAdorneer and tempParts[1] then
- tempParts[1].CFrame=(sm<2 and plugin)and new*main
- .CFrame:inverse()*tempParts[1].CFrame or CFrame.new(new.p)
- end
- setCFrame(part,new)
- --if not isBloqued then
- stInfo[i.index]=snapped
- --end
- if i.last then
- upd8ST()
- end
- end,
- MouseButton1Down=begin,
- MouseButton1Up=release,
- },
- {name='resize',
- key='x',
- colour=Color3.fromRGB(0,120,215),
- handles=handlesF.ResizeHandles,
- current={
- submode=1,
- incr={1},
- },
- submodes={
- 'side',
- 'centre',
- 'uniform',
- 'scale',
- 'part scale',
- 'edge scale',
- },
- submodeFunc={
- [4]=forGroup,
- [5]=forObjCentre,
- [6]=forEdge,
- },
- MouseDrag=function(part,main,i,face,dist)
- local initial={part.CFrame,part.Size}
- local orig=origData[i.selI]
- local size=orig.size
- local cf=orig.cf
- local sign=1
- local a=util.axisFromNormal(face)
- local axis=Vector3.FromAxis(a)
- local sm=commands[mode].current.submode
- local inc=commands[mode].current.incr[1]
- if sm<2 then
- snapped=math.floor(dist/inc+.5)*inc
- else
- snapped=math.floor(dist/inc*2+.5)*inc
- end
- if sm<3 then
- size=size+snapped*
- Vector3.FromAxis(a)
- if size[a.Name]<0 then
- sign=-1
- size=size-
- size[a.Name]*
- axis*(settings.
- resizeNegative
- and 2 or 1)
- end
- else
- local m=snapped/(origData.temp[1]or
- origData[i.selI]).size[a.Name]+1
- local M=(settings.resizeNegative
- and math.abs(m)or math.max(m,0))
- size=M*size
- if sm>3 then
- cf=cf-(cf.p-origData
- .temp[1].cf.p)*(1-m)
- tempParts[1].Size=M*
- origData.temp[1].size
- tempParts[1].CFrame=
- origData.temp[1].cf
- end
- if m<0 then
- sign=-1
- end
- end
- if sm<2 then
- cf=cf*CFrame.new((
- sign*size-orig.size)
- [a.Name]*Vector3.
- FromNormalId(face)/2)
- end
- local rSize=setSize(part,size)
- stInfo[i.index]=size[a.Name]
- setCFrame(part,cf)
- if i.last then
- upd8ST()
- end
- end,
- MouseButton1Down=begin,
- MouseButton1Up=release,
- },
- {name='rotate',
- key='c',
- colour=Color3.new(1,1,1),
- handles=handlesF.RotateHandles,
- current={
- submode=1,
- incr={30},
- },
- submodes={
- 'part',
- 'group',
- 'first',
- 'base',
- 'edge',
- 'face',
- },
- submodeFunc={
- [2]=forGroup,
- [4]=forObjCentre,
- [5]=forEdge,
- },
- MouseDrag=function(part,main,i,axis,rad,dist)
- local init=part.CFrame
- local orig=origData[i.selI]
- local sm=commands[mode].current.submode
- local inc=commands[mode].current.incr[1]
- --Rotate face only.
- if sm>5 then
- local a=math.floor(rad/math.pi*2+.5)
- local size,sizeT,tempA,tempI=orig.size,{}
- for i,g in pairs(Enum.Axis:GetEnumItems()) do
- if g~=axis and a%2>0 then
- if tempA then
- local temp=
- size[tempA]
- sizeT[tempI]=
- size[g.Name]
- sizeT[i]=temp
- else
- tempA,tempI
- =g.Name,i
- end
- else
- sizeT[i]=
- size[g.Name]
- end
- end
- setSize(part,Vector3.new(unpack(sizeT)))
- setCFrame(part,orig.cf*CFrame.fromAxisAngle(
- Vector3.FromAxis(axis),a*math.pi/2))
- return
- end
- --Every other type of rotation.
- local cf
- local a=math.deg(rad)%360
- if a>180 then
- a=a-360 end
- snapped=math.floor(a/inc+.5)*inc
- local rot=CFrame.fromAxisAngle(
- Vector3.FromAxis(axis),math.rad(snapped))
- if sm<2 then
- cf=orig.cf*rot
- elseif tempParts[1] then
- local rotCF=origData.temp[1].cf
- cf=rotCF*(rot*(rotCF:inverse()*orig.cf))
- tempParts[1].CFrame=rotCF*rot
- else
- local ocf=origData[selI].cf
- cf=ocf*(rot*(ocf:inverse()*orig.cf))
- end
- setCFrame(part,cf)
- --[[
- local isBloquing
- if settings.blocking then
- local p=part.Position
- part.Position=Vector3.new()
- part.Position=p
- if part.Position~=p then
- part.CFrame=init
- isBloquing=true
- end
- end
- ]]
- --if not isBloquing then
- stInfo[i.index]=snapped
- --end
- if i.last then
- upd8ST()
- end
- end,
- MouseButton1Down=begin,
- --A bit broken, may fix later on Roblox's part.
- MouseButton1Up=release,
- },
- {name='utility',
- key='v',
- colour=Color3.new(1),
- current={
- submode=1,
- },
- submodes={
- 'duplicate',
- 'new part',
- 'weld',
- },
- submodeFunc={
- duplicate,
- --[[ NOTE: 3D selection is actually very ineffective.
- function()
- local sel={}
- local bounds={}
- local iter,dunn=1
- local evt=mouse.Button1Up:
- connect(function()
- iter=iter+1
- dunn=iter>3
- end)
- local p=Instance.new'Part'
- local sel=Instance.new'SelectionBox'
- sel.SurfaceColor3=accColour()
- sel.SurfaceTransparency=0
- sel.Parent=core
- p.Size=Vector3.new()
- sel.Transparency=1
- sel.Adornee=p
- rsBind('region',function()
- if iter<2 then
- bounds[1]=
- mouse.Hit.p
- elseif iter<3 then
- bounds[2]=
- mouse.Hit.p-
- Vector3.new(0,
- mouse.Hit.p.y-
- bounds[1].y)
- else
- bounds[2]=
- bounds[2]+
- Vector3.new(0,
- mouse.Hit.p.y-
- bounds[2].y)
- end
- if #bounds>1 then
- sel.SurfaceTransparency
- =settings.planeTrans
- p.Position=Vector3.new(
- (bounds[1].x+
- bounds[2].x)/2,
- (bounds[1].y+
- bounds[2].y)/2,
- (bounds[1].z+
- bounds[2].z)/2
- )
- p.Size=Vector3.new(
- math.abs(bounds[
- 1].x-bounds[2].x),
- math.abs(bounds[
- 1].y-bounds[2].y),
- math.abs(bounds[
- 1].z-bounds[2].z)
- )
- else
- p.Position
- =bounds[1]
- end
- end)
- while not dunn do
- wait()end
- evt:disconnect()
- sel:destroy()
- unbind'enter'
- for i,g in pairs(game.workspace
- :FindPartsInRegion3(Region3.new(
- Vector3.new(math.min(bounds[1].x,
- bounds[2].x),math.min(bounds[1].y,
- bounds[2].y),math.min(bounds[1].z,
- bounds[2].z)),Vector3.new(math.max(
- bounds[1].x,bounds[2].x),math.max(
- bounds[1].y,bounds[2].y),math.max(
- bounds[1].z,bounds[2].z))))) do
- addSelection(g)
- end
- upd8GameSel()
- end,
- ]]
- newPart,
- weldSelection,
- }
- },
- {name='look',
- key='n',
- colour=Color3.new(0,1),
- current={
- submode=1,
- },
- submodes={
- lookGui,
- },
- submodeFunc={},
- },
- }
- local modeIndicies={}
- for i,g in pairs(commands) do
- modeIndicies[g.name]=i
- end
- --NOTE: an unused modding API. No plans as of 2017-11-27 to do anything about it.
- for i,g in pairs(defaults.mods[1]) do
- print(tostring(g.Parent))
- local m=require(g)
- for tI,t in pairs(m[1]and m or{m}) do
- local mode=tonumber(t.Mode)
- or modeIndicies[t.Mode
- or'utility']
- local cmd=commands[mode]
- if cmd then
- local oldCount
- =#cmd.submodes
- cmd.submodes[oldCount
- +1]=t.Submode
- for i2,g2 in pairs(t) do
- if type(g2)=='function' then
- if i2=='SelectionChange' then
- cmd.submodeFunc
- [oldCount+1]=g2
- else
- local f=cmd[i2]
- cmd[i2]=function(...)
- if cmd.current
- .submode>oldCount then
- g2(getfenv(),...)
- else
- f(...)
- end
- end
- end
- end
- end
- end
- end
- end
- --[[
- for i,g in pairs(commands) do
- for i2,g2 in pairs(g) do
- if type(g2)=='function' then
- end
- end
- end
- ]]
- --Argument passed in is a part.
- selFuncs={
- {'box',function(part)
- if plugin then
- return{
- part=part,
- destroy=function()end
- }
- end
- local box=Instance.new'SelectionBox'
- box.LineThickness=settings.selBoxSize
- box.Color3=commands[mode].colour
- box.Parent=core
- box.Adornee=part
- return{
- part=part,
- destroy=function()
- box:destroy()
- end,
- }
- end},
- {'plane',function(part)
- local hue=0
- local fol=Instance.new'Folder'
- fol.Name='Selection'
- fol.Parent=core
- for i,g in pairs(Enum.NormalId:GetEnumItems()) do
- local sg=Instance.new'SurfaceGui'
- sg.AlwaysOnTop=settings.planeTop
- sg.CanvasSize=Vector2.new(1,1)
- sg.Adornee=part
- sg.Parent=fol
- sg.Face=g
- local fr=Instance.new'Frame'
- fr.BackgroundColor3=Color3.fromHSV(hue
- %1,settings.planeS,settings.planeV)
- fr.BackgroundTransparency=settings.planeTrans
- fr.Size=UDim2.new(1,0,1,0)
- fr.BorderSizePixel=0
- fr.Parent=sg
- if(i%2==1) then
- hue=hue+1/2
- else
- hue=hue-1/3
- end
- end
- return{
- part=part,
- destroy=function()
- fol:destroy()
- end,
- }
- end},
- }
- --rem is a table for reference purposes.
- function scanParts(par,t,f,rem)
- t=t or{}
- for i,g in pairs(par:children()) do
- if scanParts(g,t
- ,f,rem)==0 then
- return end
- if not f or f(g) then
- t[#t+1]=g
- if rem then
- if rem[1]<1 then
- for i in pairs(t) do
- t[i]=nil
- end
- t[1]='nope'
- return
- else
- rem[1]
- =rem[1]-1
- end
- end
- end
- end
- end
- function isValidPart(p)
- return(plugin or(verify(p,player)and not(p.Parent:findFirstChild'Animate'and p.Parent
- :findFirstChild'Humanoid'))and(settings.selectLocked or not p.Locked))or not p:isA'BasePart'
- end
- function getMousePart()
- return mouse.Target
- end
- --Gets the parts to be selected from the target.
- local groupLvl=0
- function getSelParts(part)
- local orig=part
- if part:isA'BasePart' then
- if groupLvl<0 then
- local lvls=-1
- local par=part
- while par~=game do
- par=par.Parent
- lvls=lvls+1
- end
- for i=1,lvls+groupLvl do
- --if part.Parent.Parent~=game then
- part=part.Parent
- --end
- end
- else
- for i=1,groupLvl do
- if part.Parent.Parent~=game then
- part=part.Parent
- end
- end
- end
- end
- if not part:isA'BasePart'then
- local t,count,max={}
- ,0,settings.maxParts
- scanParts(part
- ,t,function(p)
- return p:isA'BasePart'
- and isValidPart(p)
- end,{max})
- print(#t)
- if t[1]=='nope'then
- return{}end
- print('This selection has '
- ..count..' parts.')
- for i,g in pairs(t) do
- t[i]={g}end
- t[0]=part
- return t
- end
- local t=isValidPart(
- part)and{part}or{}
- local par=part
- for i=1,settings.
- selectsSameCFrame do
- if par.Parent
- ==game then
- break
- end
- par=par.Parent or par
- end
- scanParts(par,t,function(p)
- return p~=part and
- p:isA'BasePart' and
- p.CFrame==part.CFrame and
- p.Size==part.Size and
- isValidPart(part)
- end)
- if #t>0 then
- --[[
- print('We have got '..#t..' part'
- ..(#t>2 and's'or'')..' selected.')
- ]]
- return{t}
- else
- return{}
- end
- end
- --[[ May allow for both box and plane selection?
- setSelMode=function(s)
- settings.selMode=s
- for selI,sel in pairs(selGroups) do
- selections[selI]:destroy()
- selections[selI]=addSelection(sel)
- end
- end
- ]]
- function reRender()
- mf.UIScale.Scale
- =settings.guiScaling
- config.UIScale.Scale
- =settings.guiScaling
- print'Rerenderring.'
- for i,g in pairs(selections) do
- g.destroy()
- selections[i]=selFuncs[settings.
- selMode][2](selGroups[i][1])
- end
- end
- function fromNum(n)
- return (''..n):gsub('%.(.'
- ..string.rep('.?',settings
- .decRound-1)..').*',',%1')
- end
- function toNum(s,p)
- if p then
- local f=s
- :sub(1,1)
- local rem
- =toNum(s
- :sub(2))
- if'+'==
- f then
- return p+rem
- elseif f
- =='-'then
- return p-rem
- elseif f
- =='*'then
- return p*rem
- elseif f
- =='/'then
- return p/rem
- elseif f
- =='%'then
- return p%rem
- end
- end
- if tonumber(s) then
- return s+0
- end
- local ftTable={s:find'^(%d+)\'%-?([%d%.]*)"?$'}
- if #ftTable>0 then
- return ftTable[3]+(ftTable[4]or 0)/12
- end
- for i,g in pairs{
- km=105e+3/32,
- m=105e+0/32,
- cm=105e-2/32,
- mm=105e-3/32,
- ft=1,
- yd=3,mi=5280,
- ['in']=1/12,
- }do
- local m={s:find('^([%d%.]+)%s*'..i..'$')}
- if m[3] then
- return g*m[3]
- end
- end
- end
- --Saves the increments stored in 'commands' for future use.
- function updateConfigIncrs()
- local t={}
- for i,g in pairs(commands) do
- if g.current then
- t[i]=g.current.incr
- end
- end
- settings.incrs=t
- print'Saved.'
- end
- local defaultIncrs={}
- for i,g in pairs(commands) do
- local t={}
- for i2,g2 in pairs(g.
- current.incr or{}) do
- t[i2]=g2 end
- defaultIncrs[i]=t
- end
- --Loads the increments from settings, if set to do so.
- if settings.saveIncrs
- and settings.incrs then
- local settingIncrs=settings.incrs
- for i,g in pairs(commands) do
- local incrs=settingIncrs[i]
- if g.current and incrs then
- g.current.incr=incrs
- end
- end
- else
- updateConfigIncrs()
- end
- bind('increment',function()
- incBox:CaptureFocus()
- end,'k')
- incBox.Undo.MouseEnter:connect(function()
- incBox.TextColor3=accColour()
- local incr=commands[mode].current.incr
- incBox.Text=fromNum(incr[2]or incr[1])
- end)
- incBox.Undo.MouseLeave:connect(function()
- incBox.TextColor3=Color3.new(1,1,1)
- incBox.Text=fromNum(commands[mode].current.incr[1])
- end)
- incBox.Undo.MouseButton1Click:connect(function()
- incBox.TextColor3=Color3.new(1,1,1)
- local incr=commands[mode].current.incr
- incBox.Text=fromNum(incr[2])
- local first=incr[1]
- for i=1,#incr do
- incr[i]=incr[i+1] or first
- end
- updateConfigIncrs()
- end)
- incBox.Redo.MouseEnter:connect(function()
- incBox.TextColor3=accColour()
- local incr=commands[mode].current.incr
- incBox.Text=fromNum(incr[#incr])
- end)
- incBox.Redo.MouseLeave:connect(function()
- incBox.TextColor3=Color3.new(1,1,1)
- incBox.Text=fromNum(commands[mode].current.incr[1])
- end)
- incBox.Redo.MouseButton1Click:connect(function()
- incBox.TextColor3=Color3.new(1,1,1)
- local incr=commands[mode].current.incr
- local last=incr[#incr]
- incBox.Text=fromNum(last)
- for i=#incr,1,-1 do
- incr[i]=incr[i-1] or last
- end
- updateConfigIncrs()
- end)
- --Resets the increments
- bind('clearIncs',function()
- print'Increments clearing.'
- if settings.clearAllOnIncrementClear then
- for i,g in pairs(commands) do
- g.current.incr={}
- --Not all modes need increments!
- for i2,g2 in pairs(
- defaultIncrs[i]) do
- g.current.incr[i2]=g2 end
- end else
- commands[mode].current.incr={}
- for i,g in pairs(defaultIncrs[mode]) do
- commands[mode].current.incr[i]=g end
- end
- local incr=commands[mode].current.incr
- incBox.Text=fromNum(incr[1])
- updateConfigIncrs()
- end,'m',true)
- incBox.FocusLost:connect(function()
- local incr=commands
- [mode].current.incr
- local v=toNum(incBox
- .Text,incr[1])
- if v and v>0 then
- incBox.Text=v
- for i=#incr,0,-1 do
- incr[i+1]=incr[i] or v
- end
- updateConfigIncrs()
- else
- incBox.Text=incr[1]
- end
- end)
- local lvlBox=sm.Level.TextBox
- bind('level',function()
- lvlBox:CaptureFocus()
- end,'l')
- lvlBox.FocusLost:connect(function()
- local v=toNum(lvlBox.Text)
- if v then
- lvlBox.Text=v
- groupLvl=v
- else
- lvlBox.Text
- =groupLvl
- end
- end)
- config.Visible=false
- sm.Config.Button.MouseButton1Click:connect(function()
- config.Visible=not config.Visible
- end)
- bind('config',function()
- config.Visible=not config.Visible
- end,Enum.KeyCode.RightBracket)
- local configTypes={}
- for i,g in pairs(config:children()) do
- if g:isA'Frame' then
- configTypes[g.Name]=g:clone()
- g:destroy()
- end
- end
- defaults.selMode[3]=#selFuncs
- for i,g in pairs(defaults) do
- local ty=type(g[1])
- local typeFrame=configTypes[ty]
- if typeFrame and g[2]~='NO_TOUCH' then
- local tf=typeFrame:clone()
- tf.TextLabel.Text=i
- if ty=='number' then
- local tb=tf.TextBox
- tb.Text=fromNum(settings[i])
- tb.FocusLost:connect(function()
- local n=toNum(tb.
- Text,settings[i])
- if n
- and (not g[2] or n>=g[2])
- and (not g[3] or n<=g[3])
- and (not g[4] or n%g[4]==0) then
- settings[i]=n
- print'Ja, the setting was changed.'
- end
- tb.Text=fromNum(settings[i])
- end)
- elseif ty=='boolean' then
- local upd8=function()
- tf.TextLabel.TextColor3=settings[i] and accColour() or Color3.new(1,1,1)
- end
- upd8()
- tf.Button.MouseButton1Click:connect(function()
- settings[i]=not settings[i]
- upd8()
- end)
- end
- tf.Name=i
- tf.Parent=config
- end
- end
- --Set to the function keys!
- local toolKeys={'Q','E','R','T','U','P'}
- for i,g in pairs(toolKeys) do
- toolKeys[i]=g end
- function setSubmode(ii)
- if ii then
- print'Submode set.'
- end
- local m=commands[mode]
- local prev=m.current.submode
- local i=ii or prev
- if m.submodes[i] then
- if type(m.submodes[prev])=='string' then
- sm[prev].TextLabel.TextColor3=Color3.new(1,1,1)
- end
- if type(m.submodes[i])=='string' then
- sm[i].TextLabel.TextColor3=accColour()
- end
- m.current.submode=i
- for i,g in pairs(tempParts) do
- g:destroy()
- tempParts[i]=nil
- end
- --Calls any selection-changing methods if any.
- canDoStuff=false
- local func=m.submodeFunc[i]
- if handles and handles.Adornee then
- handles.Adornee=type(func)
- =='function'and func(handles
- ,selGroups[selI][1],ii~=nil)
- or adornee
- elseif ii and not m.handles then
- func()
- end
- canDoStuff=true
- end
- end
- --Also used to change the main part, however not the submode.
- function setMode(s,ii)
- reactiv8()
- local m=commands[mode]
- selI=ii or 1
- --Clone the handle as to not overlap events.
- if m.handles then
- m.handles.Adornee=nil
- handles=m.handles:clone()
- m.handles:destroy()
- m.handles=handles
- end
- mode=s or mode
- submode=1
- cmds[m.name].Keybind.
- TextColor3=Color3.new(1,1,1)
- m=commands[mode]
- cmds[m.name].Keybind.
- TextColor3=accColour()
- --Responsible for updating the handles and what not.
- if selections[selI] then
- if s then
- print('Mode '..s)
- reRender()
- end
- adornee=selections[selI].part
- handles=m.handles
- if handles then
- handles.Parent=core
- handles.Adornee=adornee
- print('The adornee is '..tostring(adornee)..'.')
- for i,g in pairs(m) do
- if type(g)=='function' then
- --Connects each command event to the handle so that it may function.
- --handles[i]:connect(g)
- handles[i]:connect(function(...)
- --Iterates over each object in the selection.
- if canDoStuff then
- local index=0
- local args={...}
- --[[NOTE: The handleIntensity setting determines the proportion
- between how far you pull the handle and how far the object moves.]]
- if i=='MouseDrag' then
- args[2]=args
- [2]*settings
- .handleIntensity
- end
- for i2,g2 in pairs(selGroups) do
- for i3=1,#g2 do
- index=index+1
- g(g2[i3],adornee,{
- index=index,
- selI=i2,groupI=i3,
- isAdorneer=i2==selI and i3==1,
- last=i2==#selGroups and i3==#g2,
- },unpack(args))
- end
- end
- end
- end)
- end
- end
- end
- --[[
- if m.Activated then
- local index=0
- for i,g in pairs(selGroups) do
- for i2,g2 in pairs(g) do
- index=index+1
- m.Activated(g2,adornee,{
- index=index,
- selI=i,groupI=i2,
- isAdorneer=i==selI and i2==1,
- last=i==#selGroups and i2==#g,
- })
- end
- end
- end
- ]]
- end
- --Now for the GUI stuffs.
- if s then
- local
- i,c=1
- while sm:findFirstChild(i) do
- sm:findFirstChild(i):destroy()
- i=i+1
- end
- for i,g in pairs(m.submodes) do
- if type(g)=='string' then
- c=smTemplate:clone()
- c.TextLabel.Text=g
- elseif type(g)
- =='function'then
- local t={g(i)}
- c=t[1]
- if t[2
- ]then
- m.submodeFunc[i]=t[2]
- end
- end
- local kl=c:findFirstChild('KeyLabel',true)
- if kl then
- kl.Text=(plugin
- and i<11)and i%10
- or toolKeys[i] or''
- end
- local b=c:findFirstChild'Button'
- if b then
- b.MouseButton1Click
- :connect(function()
- setSubmode(i)
- end)
- end
- c.Name=i
- c.Parent=sm
- c.Visible=true
- end
- if m.current.incr then
- sm.Increment.Visible=true
- sm.Increment.TextBox.Text
- =toNum(m.current.incr[1])
- else
- sm.Increment.Visible=false
- end
- end
- setSubmode()
- end
- local button=plugin and plugin:CreateToolbar'VisualPlugin':
- CreateButton(id,'Windowzhiuh.','rbxasset://textures/ui/TixIcon.png')
- --Activates the plugin.
- function activ8(a)
- local willBeActive=a~=nil and a or not active
- print('Active was set to '..(willBeActive and 'on.' or 'off.'))
- gui.Parent=willBeActive and core or script
- if willBeActive then
- reactiv8()
- for i,g in pairs(binders) do
- bindH(g)
- end
- else
- for i,g in pairs(binders) do
- game.ContextActionService
- :UnbindAction(i)
- end
- if plugin then
- print'Lost.'
- button:SetActive(false)
- end
- end
- active=willBeActive
- if active then
- if settings.setToSelection then
- for i,g in pairs(game.Selection:Get()) do
- addSelection(g)
- end
- end
- else
- clearSelection()
- end
- end
- function reactiv8()
- if not active and plugin then
- plugin:Activate(true)
- button:SetActive(true)
- end
- end
- if plugin then
- button.Click:connect(activ8)
- else
- tool.Equipped:connect(activ8)
- tool.Unequipped:connect(activ8)
- end
- sm.Re.Visible=plugin~=nil
- sm.Re.Button.MouseButton1Click
- :connect(function()
- reactiv8()
- end)
- if plugin then
- plugin.Deactivation:connect(function()
- local rt=plugin:GetSelectedRibbonTool().Name
- if active and'None'~=rt
- and'Select'~=rt then
- print'Deactivated.'
- end
- end)
- end
- local timeSC
- local screentip=gui.ScreenTip
- local delayTime=settings.screenTipDelay
- gui.ScreenTip.Visible=false
- function createST()
- if not screentip.Visible then
- screentip.Visible=true
- upd8ST('')
- end
- end
- --If nothing is passed into s, we get the stInfo by default.
- function upd8ST(s)
- timeSC=tick()
- screentip.Position=UDim2
- .new(0,mouse.X,0,mouse.Y)
- if s then
- screentip.Text=s
- else
- local t,b={}
- screentip.Text=fromNum(snapped)
- for i,g in pairs(stInfo) do
- b=true
- local g=fromNum(g)
- for i2,g2 in pairs(t) do
- if g==g2 then
- b=false
- break
- end
- end
- if b then
- t[#t+1]=g
- end
- end
- if #t>0 and t[1]~=snapped then
- screentip.Text=screentip.Text..' ('
- ..table.concat(t,', ')..')'
- end
- end
- screentip.Visible=true
- local size=screentip.TextBounds
- screentip.Size=UDim2.new(0,size.X+5,0,size.Y)
- delay(delayTime,function()
- if tick()-delayTime+.1>=timeSC then
- removeST()
- end
- end)
- --[[The oh-so-requested 'undo rotation'.
- if mode==3 then
- delay(3,function()
- if tick()-3+.1>=timeSC then
- print'Luhh.'
- createWaypoint()
- end
- end)
- end
- ]]
- end
- function removeST()
- screentip.Visible=false
- end
- mouse.Button1Down:connect(function()
- local p=getMousePart()
- if canDoStuff and p then
- toggleSelection(p)
- upd8GameSel()
- end
- end)
- --NOTE: Right click is for changing the main part.
- mouse.Button2Down:connect(function()
- local p=getMousePart()
- if canDoStuff and p then
- local c=selContains(p)
- if c then
- setMode(nil,c[2])
- end
- end
- end)
- --Only actually changed the selection if a setting is turnt up.
- game.Selection.SelectionChanged:connect(function()
- if not addWhenUpd8 or not active then
- return
- end
- print'Selection changed.'
- local prevSel=getSelection()
- local sel=game.Selection:Get()
- print('There were '..#prevSel..' selected.')
- print('There are now '..#sel..' selected.')
- doPrint=false
- for i,g in pairs(prevSel) do
- local doIt=true
- for i2,g2 in pairs(sel) do
- if g2==g then
- doIt=false
- break
- end
- end
- if doIt then
- removeSelection(g)
- end
- end
- local changed
- doPrint=settings.debugP
- for i,g in pairs(sel) do
- local doIt=true
- for i2,g2 in pairs(prevSel) do
- if g2==g then
- doIt=false
- break
- end
- end
- if doIt and not addSelection(g,true) then
- sel[i],changed=nil,true
- end
- end
- if changed then
- wait()
- game.Selection:Set(sel)
- end
- --[[
- clearSelection()
- if active and settings.setToSelection then
- for i,g in pairs(game.Selection:Get()) do
- if g:isA'BasePart'then
- addSelection(g,true)
- elseif g:isA'Model'then
- addSelection(g)
- end
- end
- end
- ]]
- end)
- --Just GUI stuff.
- local c=0
- local template=cmds.Template
- for i,g in pairs(commands) do
- c=c+1
- local clone
- =template:clone()
- clone.Name=g.name
- clone.LayoutOrder=c
- clone.KeyName.Text=g.name
- clone.Parent=template.Parent
- clone.Keybind.Text=g.key:upper()
- --[[
- clone.MouseEnter:
- connect(function(x,y)
- clone.Keybind.
- BackgroundColor3
- =accColour()
- end)
- clone.MouseLeave:
- connect(function(x,y)
- clone.Keybind.
- BackgroundColor3
- =Color3.new(1,1,1)
- end)
- ]]
- --Der maneras of changing mode.
- clone.MouseButton1Click
- :connect(function(x,y)
- print'Inputted.'
- setMode(i)
- end)
- bind(g.name,function(n)
- setMode(i)
- end,g.key)
- end
- cmds.Size=UDim2
- .new(1,0,0,math.
- ceil(c/2)*15+1)
- template.
- Visible
- =false
- --Binds our submode keys.
- --NOTE: If Ctrl+NUM is pressed whilst in tool mode, it switches to that mode number.
- for i=1,10 do
- local sm=i
- bind('NKsubmode'
- ..i,function(n)
- setSubmode(sm)
- end,''..i%10
- ,not plugin)
- end
- if not plugin then
- for i,g in pairs(toolKeys) do
- local sm=i
- bind('TKsubmode'
- ..i,function(n)
- setSubmode(sm)
- end,Enum.KeyCode[g])
- end
- end
- local fr=sm.Version.Frame
- fr.Image.Image=version.shape
- fr.Version.Text=type(version.sub)=='number'
- and fromNum(version.sub)or version.sub
- fr.Version.TextColor3=accColour()
- --NOTE: The coloured bar below the version identifier is used for tracking the client's user ID.
- local dColours={[0]=
- Color3.new(1,0,0),
- Color3.new(1,1,0),
- Color3.new(0,1,0),
- Color3.new(0,1,1),
- Color3.new(0,0,1),
- Color3.new(1,0,1),
- Color3.new(0,0,0),--6
- Color3.new(1,1,1),--7
- Color3.new(.3,.3,.3),--8
- Color3.new(.7,.7,.7),--9
- }
- local tId,i=id,0
- local sq=fr.Line:WaitForChild'Square':clone()
- sq.Name='IDer'
- repeat
- local tSq=sq:clone()
- tSq.BackgroundColor3
- =dColours[tId%10]
- tId=math.floor(tId/10)
- tSq.LayoutOrder=-i
- tSq.Parent=fr.Line
- i=i+1
- until tId<1
- fr.Line.Square:destroy()
- script.ServerEvt.
- Disabled=plugin~=nil
- if not plugin then
- mf.Position=mf.Position
- +UDim2.new(0,0,0,250)
- end
- --[[NOTE:
- The special key (SPC) is ctrl/cmd in tool mode or shift in plugin mode.
- SPC + B = deselect all objects.
- SPC + Z = undo.
- SPC + Y = redo.
- SPC + X = delete.
- SPC + C = duplicate.
- SPC + M = reset increments.
- ]]
- bind('deselect',function()
- clearSelection()
- upd8GameSel()
- end,'b',true)
- local udr=sm.UDR
- udr.Delete.Button.MouseButton1Click:connect(delete)
- udr.Undo.Button.MouseButton1Click:connect(undo)
- udr.Redo.Button.MouseButton1Click:connect(redo)
- bind('duplicate',duplicate,'c',true)
- bind('delete',delete,'x',true)
- bind('undo',undo,'z',true)
- bind('redo',redo,'y',true)
- --------------------------------------------------------------------------------------------------------
- setMode(1)
- reRender()
- print'Dunn.'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement