Advertisement
popster12345

Untitled

Feb 22nd, 2016
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 60.51 KB | None | 0 0
  1. -- initial states
  2. local Option = {
  3. -- can modify objects
  4. Modifiable = true;
  5. -- can select objects
  6. Selectable = true;
  7. }
  8.  
  9. -- general size of GUI objects, in pixels
  10. local GUI_SIZE = 16
  11. -- padding between items within each entry
  12. local ENTRY_PADDING = 1
  13. -- padding between each entry
  14. local ENTRY_MARGIN = 1
  15.  
  16. --[[
  17.  
  18. # Explorer Panel
  19.  
  20. A GUI panel that displays the game hierarchy.
  21.  
  22.  
  23. ## Selection Bindables
  24.  
  25. - `Function GetSelection ( )`
  26.  
  27. Returns an array of objects representing the objects currently
  28. selected in the panel.
  29.  
  30. - `Function SetSelection ( Objects selection )`
  31.  
  32. Sets the objects that are selected in the panel. `selection` is an array
  33. of objects.
  34.  
  35. - `Event SelectionChanged ( )`
  36.  
  37. Fired after the selection changes.
  38.  
  39.  
  40. ## Option Bindables
  41.  
  42. - `Function GetOption ( string optionName )`
  43.  
  44. If `optionName` is given, returns the value of that option. Otherwise,
  45. returns a table of options and their current values.
  46.  
  47. - `Function SetOption ( string optionName, bool value )`
  48.  
  49. Sets `optionName` to `value`.
  50.  
  51. Options:
  52.  
  53. - Modifiable
  54.  
  55. Whether objects can be modified by the panel.
  56.  
  57. Note that modifying objects depends on being able to select them. If
  58. Selectable is false, then Actions will not be available. Reparenting
  59. is still possible, but only for the dragged object.
  60.  
  61. - Selectable
  62.  
  63. Whether objects can be selected.
  64.  
  65. If Modifiable is false, then left-clicking will perform a drag
  66. selection.
  67.  
  68. ## Updates
  69.  
  70. - 2013-09-14
  71. - Added GetOption and SetOption bindables.
  72. - Option: Modifiable; sets whether objects can be modified by the panel.
  73. - Option: Selectable; sets whether objects can be selected.
  74. - Slight modification to left-click selection behavior.
  75. - Improved layout and scaling.
  76.  
  77. - 2013-09-13
  78. - Added drag to reparent objects.
  79. - Left-click to select/deselect object.
  80. - Left-click and drag unselected object to reparent single object.
  81. - Left-click and drag selected object to move reparent entire selection.
  82. - Right-click while dragging to cancel.
  83.  
  84. - 2013-09-11
  85. - Added explorer panel header with actions.
  86. - Added Cut action.
  87. - Added Copy action.
  88. - Added Paste action.
  89. - Added Delete action.
  90. - Added drag selection.
  91. - Left-click: Add to selection on drag.
  92. - Right-click: Add to or remove from selection on drag.
  93. - Ensured SelectionChanged fires only when the selection actually changes.
  94. - Added documentation and change log.
  95. - Fixed thread issue.
  96.  
  97. - 2013-09-09
  98. - Added basic multi-selection.
  99. - Left-click to set selection.
  100. - Right-click to add to or remove from selection.
  101. - Removed "Selection" ObjectValue.
  102. - Added GetSelection BindableFunction.
  103. - Added SetSelection BindableFunction.
  104. - Added SelectionChanged BindableEvent.
  105. - Changed font to SourceSans.
  106.  
  107. - 2013-08-31
  108. - Improved GUI sizing based off of `GUI_SIZE` constant.
  109. - Automatic font size detection.
  110.  
  111. - 2013-08-27
  112. - Initial explorer panel.
  113.  
  114.  
  115. ## Todo
  116.  
  117. - Sorting
  118. - by ExplorerOrder
  119. - by children
  120. - by name
  121. - Drag objects to reparent
  122.  
  123. ]]
  124.  
  125. local ENTRY_SIZE = GUI_SIZE + ENTRY_PADDING*2
  126. local ENTRY_BOUND = ENTRY_SIZE + ENTRY_MARGIN
  127. local HEADER_SIZE = ENTRY_SIZE
  128.  
  129. local FONT = 'SourceSans'
  130. local FONT_SIZE do
  131. local size = {8,9,10,11,12,14,18,24,36,48}
  132. local s
  133. local n = math.huge
  134. for i = 1,#size do
  135. if size[i] <= GUI_SIZE then
  136. FONT_SIZE = i - 1
  137. end
  138. end
  139. end
  140.  
  141. local GuiColor = {
  142. Background = Color3.new(233/255, 233/255, 233/255);
  143. Border = Color3.new(149/255, 149/255, 149/255);
  144. Selected = Color3.new( 96/255, 140/255, 211/255);
  145. BorderSelected = Color3.new( 86/255, 125/255, 188/255);
  146. Text = Color3.new( 0/255, 0/255, 0/255);
  147. TextDisabled = Color3.new(128/255, 128/255, 128/255);
  148. TextSelected = Color3.new(255/255, 255/255, 255/255);
  149. Button = Color3.new(221/255, 221/255, 221/255);
  150. ButtonBorder = Color3.new(149/255, 149/255, 149/255);
  151. ButtonSelected = Color3.new(255/255, 0/255, 0/255);
  152. Field = Color3.new(255/255, 255/255, 255/255);
  153. FieldBorder = Color3.new(191/255, 191/255, 191/255);
  154. TitleBackground = Color3.new(178/255, 178/255, 178/255);
  155. }
  156.  
  157. ----------------------------------------------------------------
  158. ----------------------------------------------------------------
  159. ----------------------------------------------------------------
  160. ----------------------------------------------------------------
  161. ---- Icon map constants
  162.  
  163. local MAP_ID = 129293660
  164.  
  165. -- Indices based on implementation of Icon function.
  166. local ACTION_CUT = 160
  167. local ACTION_COPY = 161
  168. local ACTION_PASTE = 162
  169. local ACTION_DELETE = 163
  170. local ACTION_SORT = 164
  171. local ACTION_CUT_OVER = 174
  172. local ACTION_COPY_OVER = 175
  173. local ACTION_PASTE_OVER = 176
  174. local ACTION_DELETE_OVER = 177
  175. local ACTION_SORT_OVER = 178
  176.  
  177. local NODE_COLLAPSED = 165
  178. local NODE_EXPANDED = 166
  179. local NODE_COLLAPSED_OVER = 179
  180. local NODE_EXPANDED_OVER = 180
  181.  
  182. local ExplorerIndex = {
  183. Accoutrement = 32;
  184. AdvancedDragger = 0;
  185. Animation = 60;
  186. AnimationTrack = 60;
  187. AnimationTrackState = 60;
  188. Animator = 0;
  189. ArcHandles = 56;
  190. Authoring = 3;
  191. Backpack = 20;
  192. BackpackItem = 0;
  193. BadgeService = 0;
  194. BasePart = 1;
  195. BasePlayerGui = 46;
  196. BaseScript = 6;
  197. BevelMesh = 8;
  198. BillboardGui = 64;
  199. BindableEvent = 67;
  200. BindableFunction = 66;
  201. BlockMesh = 8;
  202. BodyAngularVelocity = 14;
  203. BodyColors = 0;
  204. BodyForce = 14;
  205. BodyGyro = 14;
  206. BodyMover = 14;
  207. BodyPosition = 14;
  208. BodyThrust = 14;
  209. BodyVelocity = 14;
  210. BoolValue = 4;
  211. BrickColorValue = 4;
  212. Button = 0;
  213. ButtonBindingWidget = 0;
  214. CFrameValue = 4;
  215. CacheableContentProvider = 0;
  216. Camera = 5;
  217. ChangeHistoryService = 0;
  218. CharacterAppearance = 0;
  219. CharacterMesh = 60;
  220. Chat = 0;
  221. ClickDetector = 41;
  222. Clothing = 40;
  223. CollectionService = 0;
  224. Color3Value = 4;
  225. Configuration = 58;
  226. ContentFilter = 0;
  227. ContentProvider = 0;
  228. ContextActionService = 0;
  229. Controller = 0;
  230. ControllerService = 0;
  231. CookiesService = 0;
  232. CoreGui = 0;
  233. CoreScript = 6;
  234. CornerWedgePart = 1;
  235. CustomEvent = 4;
  236. CustomEventReceiver = 4;
  237. CylinderMesh = 8;
  238. DataModel = 0;
  239. DataModelMesh = 8;
  240. Debris = 30;
  241. DebugSettings = 3;
  242. DebuggerBreakpoint = 0;
  243. DebuggerService = 0;
  244. DebuggerWatch = 0;
  245. Decal = 7;
  246. Dialog = 62;
  247. DialogChoice = 63;
  248. DoubleConstrainedValue = 4;
  249. Dragger = 0;
  250. DynamicRotate = 34;
  251. Explosion = 36;
  252. FWService = 0;
  253. FaceInstance = 0;
  254. FastLogSettings = 3;
  255. Feature = 0;
  256. FileMesh = 8;
  257. Fire = 61;
  258. Flag = 38;
  259. FlagStand = 39;
  260. FlagStandService = 0;
  261. FloorWire = 4;
  262. ForceField = 37;
  263. FormFactorPart = 1;
  264. Frame = 48;
  265. FriendService = 0;
  266. FunctionalTest = 0;
  267. GamePassService = 0;
  268. GameSettings = 3;
  269. GenericSettings = 3;
  270. Geometry = 0;
  271. GlobalSettings = 3;
  272. Glue = 34;
  273. GuiBase = 47;
  274. GuiBase2d = 0;
  275. GuiBase3d = 0;
  276. GuiButton = 51;
  277. GuiItem = 0;
  278. GuiLabel = 50;
  279. GuiMain = 47;
  280. GuiObject = 48;
  281. GuiRoot = 0;
  282. GuiService = 0;
  283. GuidRegistryService = 0;
  284. Handles = 53;
  285. HandlesBase = 0;
  286. Hat = 45;
  287. Hint = 33;
  288. Hole = 0;
  289. Hopper = 0;
  290. HopperBin = 22;
  291. Humanoid = 9;
  292. HumanoidController = 0;
  293. ImageButton = 52;
  294. ImageLabel = 49;
  295. InsertService = 0;
  296. Instance = 0;
  297. InstancePacketCache = 0;
  298. IntConstrainedValue = 4;
  299. IntValue = 4;
  300. JointInstance = 34;
  301. JointsService = 0;
  302. Keyframe = 60;
  303. KeyframeSequence = 0;
  304. KeyframeSequenceProvider = 0;
  305. LayerCollector = 0;
  306. Light = 0;
  307. Lighting = 13;
  308. LoadingGui = 46;
  309. LocalBackpack = 0;
  310. LocalScript = 18;
  311. LocalWorkspace = 0;
  312. LuaSettings = 3;
  313. LuaWebService = 0;
  314. ManualGlue = 34;
  315. ManualSurfaceJointInstance = 0;
  316. ManualWeld = 34;
  317. MarketplaceService = 0;
  318. MeshContentProvider = 0;
  319. Message = 33;
  320. Model = 2;
  321. Motor = 34;
  322. Motor6D = 34;
  323. MotorFeature = 0;
  324. Mouse = 0;
  325. NetworkClient = 16;
  326. NetworkMarker = 0;
  327. NetworkPeer = 0;
  328. NetworkReplicator = 29;
  329. NetworkServer = 15;
  330. NetworkSettings = 3;
  331. NotificationBox = 48;
  332. NotificationObject = 48;
  333. NumberValue = 4;
  334. ObjectValue = 4;
  335. PVAdornment = 0;
  336. PVInstance = 0;
  337. Pants = 44;
  338. ParallelRampPart = 1;
  339. Part = 1;
  340. PartAdornment = 0;
  341. PersonalServerService = 0;
  342. PhysicsPacketCache = 0;
  343. PhysicsService = 0;
  344. PhysicsSettings = 3;
  345. Platform = 1;
  346. Player = 12;
  347. PlayerGui = 46;
  348. PlayerHUD = 0;
  349. PlayerMouse = 0;
  350. Players = 21;
  351. Plugin = 0;
  352. PluginManager = 0;
  353. PluginMouse = 0;
  354. PointLight = 0;
  355. Pose = 60;
  356. PrismPart = 1;
  357. ProfilingItem = 0;
  358. PyramidPart = 1;
  359. RayValue = 4;
  360. ReflectionMetadata = 0;
  361. ReflectionMetadataCallbacks = 0;
  362. ReflectionMetadataClass = 0;
  363. ReflectionMetadataClasses = 0;
  364. ReflectionMetadataEvents = 0;
  365. ReflectionMetadataFunctions = 0;
  366. ReflectionMetadataItem = 0;
  367. ReflectionMetadataMember = 0;
  368. ReflectionMetadataProperties = 0;
  369. ReflectionMetadataYieldFunctions = 0;
  370. RenderHooksService = 0;
  371. RenderSettings = 3;
  372. RightAngleRampPart = 1;
  373. RocketPropulsion = 14;
  374. RootInstance = 0;
  375. Rotate = 34;
  376. RotateP = 34;
  377. RotateV = 34;
  378. RunService = 0;
  379. RunningAverageItemDouble = 0;
  380. RunningAverageItemInt = 0;
  381. RuntimeScriptService = 0;
  382. Scale9Frame = 0;
  383. ScreenGui = 47;
  384. Script = 6;
  385. ScriptContext = 0;
  386. ScriptDebugger = 0;
  387. ScriptInformationProvider = 0;
  388. ScriptService = 0;
  389. Seat = 35;
  390. Selection = 0;
  391. SelectionBox = 54;
  392. SelectionLasso = 57;
  393. SelectionPartLasso = 57;
  394. SelectionPointLasso = 57;
  395. ServerReplicator = 0;
  396. ServiceProvider = 0;
  397. Shirt = 43;
  398. ShirtGraphic = 40;
  399. SkateboardController = 0;
  400. SkateboardPlatform = 1;
  401. Skin = 0;
  402. Sky = 28;
  403. Smoke = 59;
  404. Snap = 34;
  405. SocialService = 0;
  406. Sound = 11;
  407. SoundService = 31;
  408. Sparkles = 42;
  409. SpawnLocation = 25;
  410. SpawnerService = 0;
  411. SpecialMesh = 8;
  412. SpotLight = 0;
  413. StarterGear = 20;
  414. StarterGui = 46;
  415. StarterPack = 20;
  416. StarterScript = 18;
  417. Stats = 0;
  418. StatsItem = 0;
  419. Status = 2;
  420. StockSound = 11;
  421. StringValue = 4;
  422. StudioTool = 0;
  423. SurfaceSelection = 55;
  424. TaskScheduler = 0;
  425. Team = 24;
  426. Teams = 23;
  427. TeleportService = 0;
  428. Terrain = 65;
  429. TestService = 68;
  430. TextBox = 51;
  431. TextButton = 51;
  432. TextLabel = 50;
  433. TextService = 0;
  434. Texture = 10;
  435. TextureContentProvider = 0;
  436. TextureTrail = 4;
  437. TimerService = 0;
  438. Tool = 17;
  439. Toolbar = 0;
  440. TotalCountTimeIntervalItem = 0;
  441. TouchTransmitter = 37;
  442. TrussPart = 1;
  443. TweenService = 0;
  444. UserGameSettings = 4;
  445. UserInputService = 0;
  446. UserSettings = 3;
  447. Vector3Value = 4;
  448. VehicleController = 0;
  449. VehicleSeat = 35;
  450. VelocityMotor = 34;
  451. VirtualUser = 0;
  452. Visit = 0;
  453. WedgePart = 1;
  454. Weld = 34;
  455. Workspace = 19;
  456. }
  457.  
  458. ----------------------------------------------------------------
  459. ----------------------------------------------------------------
  460. ----------------------------------------------------------------
  461. ----------------------------------------------------------------
  462. ----------------------------------------------------------------
  463.  
  464. function Create(ty,data)
  465. local obj
  466. if type(ty) == 'string' then
  467. obj = Instance.new(ty)
  468. else
  469. obj = ty
  470. end
  471. for k, v in pairs(data) do
  472. if type(k) == 'number' then
  473. v.Parent = obj
  474. else
  475. obj[k] = v
  476. end
  477. end
  478. return obj
  479. end
  480.  
  481. -- Connects a function to an event such that it fires asynchronously
  482. function Connect(event,func)
  483. return event:connect(function(...)
  484. local a = {...}
  485. Spawn(function() func(unpack(a)) end)
  486. end)
  487. end
  488.  
  489. -- returns the ascendant ScreenGui of an object
  490. function GetScreen(screen)
  491. if screen == nil then return nil end
  492. while not screen:IsA("ScreenGui") do
  493. screen = screen.Parent
  494. if screen == nil then return nil end
  495. end
  496. return screen
  497. end
  498.  
  499. do
  500. local ZIndexLock = {}
  501. -- Sets the ZIndex of an object and its descendants. Objects are locked so
  502. -- that SetZIndexOnChanged doesn't spawn multiple threads that set the
  503. -- ZIndex of the same object.
  504. function SetZIndex(object,z)
  505. if not ZIndexLock[object] then
  506. ZIndexLock[object] = true
  507. if object:IsA'GuiObject' then
  508. object.ZIndex = z
  509. end
  510. local children = object:GetChildren()
  511. for i = 1,#children do
  512. SetZIndex(children[i],z)
  513. end
  514. ZIndexLock[object] = nil
  515. end
  516. end
  517.  
  518. function SetZIndexOnChanged(object)
  519. return object.Changed:connect(function(p)
  520. if p == "ZIndex" then
  521. SetZIndex(object,object.ZIndex)
  522. end
  523. end)
  524. end
  525. end
  526.  
  527. ---- IconMap ----
  528. -- Image size: 256px x 256px
  529. -- Icon size: 16px x 16px
  530. -- Padding between each icon: 2px
  531. -- Padding around image edge: 1px
  532. -- Total icons: 14 x 14 (196)
  533. local Icon do
  534. local iconMap = 'http://www.roblox.com/asset/?id=' .. MAP_ID
  535. Game:GetService('ContentProvider'):Preload(iconMap)
  536. local iconDehash do
  537. -- 14 x 14, 0-based input, 0-based output
  538. local f=math.floor
  539. function iconDehash(h)
  540. return f(h/14%14),f(h%14)
  541. end
  542. end
  543.  
  544. function Icon(IconFrame,index)
  545. local row,col = iconDehash(index)
  546. local mapSize = Vector2.new(256,256)
  547. local pad,border = 2,1
  548. local iconSize = 16
  549.  
  550. local class = 'Frame'
  551. if type(IconFrame) == 'string' then
  552. class = IconFrame
  553. IconFrame = nil
  554. end
  555.  
  556. if not IconFrame then
  557. IconFrame = Create(class,{
  558. Name = "Icon";
  559. BackgroundTransparency = 1;
  560. ClipsDescendants = true;
  561. Create('ImageLabel',{
  562. Name = "IconMap";
  563. Active = false;
  564. BackgroundTransparency = 1;
  565. Image = iconMap;
  566. Size = UDim2.new(mapSize.x/iconSize,0,mapSize.y/iconSize,0);
  567. });
  568. })
  569. end
  570.  
  571. IconFrame.IconMap.Position = UDim2.new(-col - (pad*(col+1) + border)/iconSize,0,-row - (pad*(row+1) + border)/iconSize,0)
  572. return IconFrame
  573. end
  574. end
  575.  
  576. ----------------------------------------------------------------
  577. ----------------------------------------------------------------
  578. ----------------------------------------------------------------
  579. ----------------------------------------------------------------
  580. ---- ScrollBar
  581. do
  582. -- AutoButtonColor doesn't always reset properly
  583. local function ResetButtonColor(button)
  584. local active = button.Active
  585. button.Active = not active
  586. button.Active = active
  587. end
  588.  
  589. local function ArrowGraphic(size,dir,scaled,template)
  590. local Frame = Create('Frame',{
  591. Name = "Arrow Graphic";
  592. BorderSizePixel = 0;
  593. Size = UDim2.new(0,size,0,size);
  594. Transparency = 1;
  595. })
  596. if not template then
  597. template = Instance.new("Frame")
  598. template.BorderSizePixel = 0
  599. end
  600.  
  601. local transform
  602. if dir == nil or dir == 'Up' then
  603. function transform(p,s) return p,s end
  604. elseif dir == 'Down' then
  605. function transform(p,s) return UDim2.new(0,p.X.Offset,0,size-p.Y.Offset-1),s end
  606. elseif dir == 'Left' then
  607. function transform(p,s) return UDim2.new(0,p.Y.Offset,0,p.X.Offset),UDim2.new(0,s.Y.Offset,0,s.X.Offset) end
  608. elseif dir == 'Right' then
  609. function transform(p,s) return UDim2.new(0,size-p.Y.Offset-1,0,p.X.Offset),UDim2.new(0,s.Y.Offset,0,s.X.Offset) end
  610. end
  611.  
  612. local scale
  613. if scaled then
  614. function scale(p,s) return UDim2.new(p.X.Offset/size,0,p.Y.Offset/size,0),UDim2.new(s.X.Offset/size,0,s.Y.Offset/size,0) end
  615. else
  616. function scale(p,s) return p,s end
  617. end
  618.  
  619. local o = math.floor(size/4)
  620. if size%2 == 0 then
  621. local n = size/2-1
  622. for i = 0,n do
  623. local t = template:Clone()
  624. local p,s = scale(transform(
  625. UDim2.new(0,n-i,0,o+i),
  626. UDim2.new(0,(i+1)*2,0,1)
  627. ))
  628. t.Position = p
  629. t.Size = s
  630. t.Parent = Frame
  631. end
  632. else
  633. local n = (size-1)/2
  634. for i = 0,n do
  635. local t = template:Clone()
  636. local p,s = scale(transform(
  637. UDim2.new(0,n-i,0,o+i),
  638. UDim2.new(0,i*2+1,0,1)
  639. ))
  640. t.Position = p
  641. t.Size = s
  642. t.Parent = Frame
  643. end
  644. end
  645. if size%4 > 1 then
  646. local t = template:Clone()
  647. local p,s = scale(transform(
  648. UDim2.new(0,0,0,size-o-1),
  649. UDim2.new(0,size,0,1)
  650. ))
  651. t.Position = p
  652. t.Size = s
  653. t.Parent = Frame
  654. end
  655. return Frame
  656. end
  657.  
  658.  
  659. local function GripGraphic(size,dir,spacing,scaled,template)
  660. local Frame = Create('Frame',{
  661. Name = "Grip Graphic";
  662. BorderSizePixel = 0;
  663. Size = UDim2.new(0,size.x,0,size.y);
  664. Transparency = 1;
  665. })
  666. if not template then
  667. template = Instance.new("Frame")
  668. template.BorderSizePixel = 0
  669. end
  670.  
  671. spacing = spacing or 2
  672.  
  673. local scale
  674. if scaled then
  675. function scale(p) return UDim2.new(p.X.Offset/size.x,0,p.Y.Offset/size.y,0) end
  676. else
  677. function scale(p) return p end
  678. end
  679.  
  680. if dir == 'Vertical' then
  681. for i=0,size.x-1,spacing do
  682. local t = template:Clone()
  683. t.Size = scale(UDim2.new(0,1,0,size.y))
  684. t.Position = scale(UDim2.new(0,i,0,0))
  685. t.Parent = Frame
  686. end
  687. elseif dir == nil or dir == 'Horizontal' then
  688. for i=0,size.y-1,spacing do
  689. local t = template:Clone()
  690. t.Size = scale(UDim2.new(0,size.x,0,1))
  691. t.Position = scale(UDim2.new(0,0,0,i))
  692. t.Parent = Frame
  693. end
  694. end
  695.  
  696. return Frame
  697. end
  698.  
  699. local mt = {
  700. __index = {
  701. GetScrollPercent = function(self)
  702. return self.ScrollIndex/(self.TotalSpace-self.VisibleSpace)
  703. end;
  704. CanScrollDown = function(self)
  705. return self.ScrollIndex + self.VisibleSpace < self.TotalSpace
  706. end;
  707. CanScrollUp = function(self)
  708. return self.ScrollIndex > 0
  709. end;
  710. ScrollDown = function(self)
  711. self.ScrollIndex = self.ScrollIndex + self.PageIncrement
  712. self:Update()
  713. end;
  714. ScrollUp = function(self)
  715. self.ScrollIndex = self.ScrollIndex - self.PageIncrement
  716. self:Update()
  717. end;
  718. ScrollTo = function(self,index)
  719. self.ScrollIndex = index
  720. self:Update()
  721. end;
  722. SetScrollPercent = function(self,percent)
  723. self.ScrollIndex = math.floor((self.TotalSpace - self.VisibleSpace)*percent + 0.5)
  724. self:Update()
  725. end;
  726. };
  727. }
  728. mt.__index.CanScrollRight = mt.__index.CanScrollDown
  729. mt.__index.CanScrollLeft = mt.__index.CanScrollUp
  730. mt.__index.ScrollLeft = mt.__index.ScrollUp
  731. mt.__index.ScrollRight = mt.__index.ScrollDown
  732.  
  733. function ScrollBar(horizontal)
  734. -- create row scroll bar
  735. local ScrollFrame = Create('Frame',{
  736. Name = "ScrollFrame";
  737. Position = horizontal and UDim2.new(0,0,1,-GUI_SIZE) or UDim2.new(1,-GUI_SIZE,0,0);
  738. Size = horizontal and UDim2.new(1,0,0,GUI_SIZE) or UDim2.new(0,GUI_SIZE,1,0);
  739. BackgroundTransparency = 1;
  740. Create('ImageButton',{
  741. Name = "ScrollDown";
  742. Position = horizontal and UDim2.new(1,-GUI_SIZE,0,0) or UDim2.new(0,0,1,-GUI_SIZE);
  743. Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
  744. BackgroundColor3 = GuiColor.Button;
  745. BorderColor3 = GuiColor.Border;
  746. --BorderSizePixel = 0;
  747. });
  748. Create('ImageButton',{
  749. Name = "ScrollUp";
  750. Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
  751. BackgroundColor3 = GuiColor.Button;
  752. BorderColor3 = GuiColor.Border;
  753. --BorderSizePixel = 0;
  754. });
  755. Create('ImageButton',{
  756. Name = "ScrollBar";
  757. Size = horizontal and UDim2.new(1,-GUI_SIZE*2,1,0) or UDim2.new(1,0,1,-GUI_SIZE*2);
  758. Position = horizontal and UDim2.new(0,GUI_SIZE,0,0) or UDim2.new(0,0,0,GUI_SIZE);
  759. AutoButtonColor = false;
  760. BackgroundColor3 = Color3.new(0.94902, 0.94902, 0.94902);
  761. BorderColor3 = GuiColor.Border;
  762. --BorderSizePixel = 0;
  763. Create('ImageButton',{
  764. Name = "ScrollThumb";
  765. AutoButtonColor = false;
  766. Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
  767. BackgroundColor3 = GuiColor.Button;
  768. BorderColor3 = GuiColor.Border;
  769. --BorderSizePixel = 0;
  770. });
  771. });
  772. })
  773.  
  774. local graphicTemplate = Create('Frame',{
  775. Name="Graphic";
  776. BorderSizePixel = 0;
  777. BackgroundColor3 = GuiColor.Border;
  778. })
  779. local graphicSize = GUI_SIZE/2
  780.  
  781. local ScrollDownFrame = ScrollFrame.ScrollDown
  782. local ScrollDownGraphic = ArrowGraphic(graphicSize,horizontal and 'Right' or 'Down',true,graphicTemplate)
  783. ScrollDownGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
  784. ScrollDownGraphic.Parent = ScrollDownFrame
  785. local ScrollUpFrame = ScrollFrame.ScrollUp
  786. local ScrollUpGraphic = ArrowGraphic(graphicSize,horizontal and 'Left' or 'Up',true,graphicTemplate)
  787. ScrollUpGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
  788. ScrollUpGraphic.Parent = ScrollUpFrame
  789. local ScrollBarFrame = ScrollFrame.ScrollBar
  790. local ScrollThumbFrame = ScrollBarFrame.ScrollThumb
  791. do
  792. local size = GUI_SIZE*3/8
  793. local Decal = GripGraphic(Vector2.new(size,size),horizontal and 'Vertical' or 'Horizontal',2,graphicTemplate)
  794. Decal.Position = UDim2.new(0.5,-size/2,0.5,-size/2)
  795. Decal.Parent = ScrollThumbFrame
  796. end
  797.  
  798. local Class = setmetatable({
  799. GUI = ScrollFrame;
  800. ScrollIndex = 0;
  801. VisibleSpace = 0;
  802. TotalSpace = 0;
  803. PageIncrement = 1;
  804. },mt)
  805.  
  806. local UpdateScrollThumb
  807. if horizontal then
  808. function UpdateScrollThumb()
  809. ScrollThumbFrame.Size = UDim2.new(Class.VisibleSpace/Class.TotalSpace,0,0,GUI_SIZE)
  810. if ScrollThumbFrame.AbsoluteSize.x < GUI_SIZE then
  811. ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE)
  812. end
  813. local barSize = ScrollBarFrame.AbsoluteSize.x
  814. ScrollThumbFrame.Position = UDim2.new(Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.x)/barSize,0,0,0)
  815. end
  816. else
  817. function UpdateScrollThumb()
  818. ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,Class.VisibleSpace/Class.TotalSpace,0)
  819. if ScrollThumbFrame.AbsoluteSize.y < GUI_SIZE then
  820. ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE)
  821. end
  822. local barSize = ScrollBarFrame.AbsoluteSize.y
  823. ScrollThumbFrame.Position = UDim2.new(0,0,Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.y)/barSize,0)
  824. end
  825. end
  826.  
  827. local lastDown
  828. local lastUp
  829. local scrollStyle = {BackgroundColor3=GuiColor.Border,BackgroundTransparency=0}
  830. local scrollStyle_ds = {BackgroundColor3=GuiColor.Border,BackgroundTransparency=0.7}
  831.  
  832. local function Update()
  833. local t = Class.TotalSpace
  834. local v = Class.VisibleSpace
  835. local s = Class.ScrollIndex
  836. if v <= t then
  837. if s > 0 then
  838. if s + v > t then
  839. Class.ScrollIndex = t - v
  840. end
  841. else
  842. Class.ScrollIndex = 0
  843. end
  844. else
  845. Class.ScrollIndex = 0
  846. end
  847.  
  848. if Class.UpdateCallback then
  849. if Class.UpdateCallback(Class) == false then
  850. return
  851. end
  852. end
  853.  
  854. local down = Class:CanScrollDown()
  855. local up = Class:CanScrollUp()
  856. if down ~= lastDown then
  857. lastDown = down
  858. ScrollDownFrame.Active = down
  859. ScrollDownFrame.AutoButtonColor = down
  860. local children = ScrollDownGraphic:GetChildren()
  861. local style = down and scrollStyle or scrollStyle_ds
  862. for i = 1,#children do
  863. Create(children[i],style)
  864. end
  865. end
  866. if up ~= lastUp then
  867. lastUp = up
  868. ScrollUpFrame.Active = up
  869. ScrollUpFrame.AutoButtonColor = up
  870. local children = ScrollUpGraphic:GetChildren()
  871. local style = up and scrollStyle or scrollStyle_ds
  872. for i = 1,#children do
  873. Create(children[i],style)
  874. end
  875. end
  876. ScrollThumbFrame.Visible = down or up
  877. UpdateScrollThumb()
  878. end
  879. Class.Update = Update
  880.  
  881. SetZIndexOnChanged(ScrollFrame)
  882.  
  883. local MouseDrag = Create('ImageButton',{
  884. Name = "MouseDrag";
  885. Position = UDim2.new(-0.25,0,-0.25,0);
  886. Size = UDim2.new(1.5,0,1.5,0);
  887. Transparency = 1;
  888. AutoButtonColor = false;
  889. Active = true;
  890. ZIndex = 10;
  891. })
  892.  
  893. local scrollEventID = 0
  894. ScrollDownFrame.MouseButton1Down:connect(function()
  895. scrollEventID = tick()
  896. local current = scrollEventID
  897. local up_con
  898. up_con = MouseDrag.MouseButton1Up:connect(function()
  899. scrollEventID = tick()
  900. MouseDrag.Parent = nil
  901. ResetButtonColor(ScrollDownFrame)
  902. up_con:disconnect(); drag = nil
  903. end)
  904. MouseDrag.Parent = GetScreen(ScrollFrame)
  905. Class:ScrollDown()
  906. wait(0.2) -- delay before auto scroll
  907. while scrollEventID == current do
  908. Class:ScrollDown()
  909. if not Class:CanScrollDown() then break end
  910. wait()
  911. end
  912. end)
  913.  
  914. ScrollDownFrame.MouseButton1Up:connect(function()
  915. scrollEventID = tick()
  916. end)
  917.  
  918. ScrollUpFrame.MouseButton1Down:connect(function()
  919. scrollEventID = tick()
  920. local current = scrollEventID
  921. local up_con
  922. up_con = MouseDrag.MouseButton1Up:connect(function()
  923. scrollEventID = tick()
  924. MouseDrag.Parent = nil
  925. ResetButtonColor(ScrollUpFrame)
  926. up_con:disconnect(); drag = nil
  927. end)
  928. MouseDrag.Parent = GetScreen(ScrollFrame)
  929. Class:ScrollUp()
  930. wait(0.2)
  931. while scrollEventID == current do
  932. Class:ScrollUp()
  933. if not Class:CanScrollUp() then break end
  934. wait()
  935. end
  936. end)
  937.  
  938. ScrollUpFrame.MouseButton1Up:connect(function()
  939. scrollEventID = tick()
  940. end)
  941.  
  942. if horizontal then
  943. ScrollBarFrame.MouseButton1Down:connect(function(x,y)
  944. scrollEventID = tick()
  945. local current = scrollEventID
  946. local up_con
  947. up_con = MouseDrag.MouseButton1Up:connect(function()
  948. scrollEventID = tick()
  949. MouseDrag.Parent = nil
  950. ResetButtonColor(ScrollUpFrame)
  951. up_con:disconnect(); drag = nil
  952. end)
  953. MouseDrag.Parent = GetScreen(ScrollFrame)
  954. if x > ScrollThumbFrame.AbsolutePosition.x then
  955. Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
  956. wait(0.2)
  957. while scrollEventID == current do
  958. if x < ScrollThumbFrame.AbsolutePosition.x + ScrollThumbFrame.AbsoluteSize.x then break end
  959. Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
  960. wait()
  961. end
  962. else
  963. Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
  964. wait(0.2)
  965. while scrollEventID == current do
  966. if x > ScrollThumbFrame.AbsolutePosition.x then break end
  967. Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
  968. wait()
  969. end
  970. end
  971. end)
  972. else
  973. ScrollBarFrame.MouseButton1Down:connect(function(x,y)
  974. scrollEventID = tick()
  975. local current = scrollEventID
  976. local up_con
  977. up_con = MouseDrag.MouseButton1Up:connect(function()
  978. scrollEventID = tick()
  979. MouseDrag.Parent = nil
  980. ResetButtonColor(ScrollUpFrame)
  981. up_con:disconnect(); drag = nil
  982. end)
  983. MouseDrag.Parent = GetScreen(ScrollFrame)
  984. if y > ScrollThumbFrame.AbsolutePosition.y then
  985. Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
  986. wait(0.2)
  987. while scrollEventID == current do
  988. if y < ScrollThumbFrame.AbsolutePosition.y + ScrollThumbFrame.AbsoluteSize.y then break end
  989. Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
  990. wait()
  991. end
  992. else
  993. Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
  994. wait(0.2)
  995. while scrollEventID == current do
  996. if y > ScrollThumbFrame.AbsolutePosition.y then break end
  997. Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
  998. wait()
  999. end
  1000. end
  1001. end)
  1002. end
  1003.  
  1004. if horizontal then
  1005. ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
  1006. scrollEventID = tick()
  1007. local mouse_offset = x - ScrollThumbFrame.AbsolutePosition.x
  1008. local drag_con
  1009. local up_con
  1010. drag_con = MouseDrag.MouseMoved:connect(function(x,y)
  1011. local bar_abs_pos = ScrollBarFrame.AbsolutePosition.x
  1012. local bar_drag = ScrollBarFrame.AbsoluteSize.x - ScrollThumbFrame.AbsoluteSize.x
  1013. local bar_abs_one = bar_abs_pos + bar_drag
  1014. x = x - mouse_offset
  1015. x = x < bar_abs_pos and bar_abs_pos or x > bar_abs_one and bar_abs_one or x
  1016. x = x - bar_abs_pos
  1017. Class:SetScrollPercent(x/(bar_drag))
  1018. end)
  1019. up_con = MouseDrag.MouseButton1Up:connect(function()
  1020. scrollEventID = tick()
  1021. MouseDrag.Parent = nil
  1022. ResetButtonColor(ScrollThumbFrame)
  1023. drag_con:disconnect(); drag_con = nil
  1024. up_con:disconnect(); drag = nil
  1025. end)
  1026. MouseDrag.Parent = GetScreen(ScrollFrame)
  1027. end)
  1028. else
  1029. ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
  1030. scrollEventID = tick()
  1031. local mouse_offset = y - ScrollThumbFrame.AbsolutePosition.y
  1032. local drag_con
  1033. local up_con
  1034. drag_con = MouseDrag.MouseMoved:connect(function(x,y)
  1035. local bar_abs_pos = ScrollBarFrame.AbsolutePosition.y
  1036. local bar_drag = ScrollBarFrame.AbsoluteSize.y - ScrollThumbFrame.AbsoluteSize.y
  1037. local bar_abs_one = bar_abs_pos + bar_drag
  1038. y = y - mouse_offset
  1039. y = y < bar_abs_pos and bar_abs_pos or y > bar_abs_one and bar_abs_one or y
  1040. y = y - bar_abs_pos
  1041. Class:SetScrollPercent(y/(bar_drag))
  1042. end)
  1043. up_con = MouseDrag.MouseButton1Up:connect(function()
  1044. scrollEventID = tick()
  1045. MouseDrag.Parent = nil
  1046. ResetButtonColor(ScrollThumbFrame)
  1047. drag_con:disconnect(); drag_con = nil
  1048. up_con:disconnect(); drag = nil
  1049. end)
  1050. MouseDrag.Parent = GetScreen(ScrollFrame)
  1051. end)
  1052. end
  1053.  
  1054. function Class:Destroy()
  1055. ScrollFrame:Destroy()
  1056. MouseDrag:Destroy()
  1057. for k in pairs(Class) do
  1058. Class[k] = nil
  1059. end
  1060. setmetatable(Class,nil)
  1061. end
  1062.  
  1063. Update()
  1064.  
  1065. return Class
  1066. end
  1067. end
  1068.  
  1069. ----------------------------------------------------------------
  1070. ----------------------------------------------------------------
  1071. ----------------------------------------------------------------
  1072. ----------------------------------------------------------------
  1073. ---- Explorer panel
  1074.  
  1075. local explorerPanel = script.Parent
  1076. Create(explorerPanel,{
  1077. BackgroundColor3 = GuiColor.Field;
  1078. BorderColor3 = GuiColor.Border;
  1079. Active = true;
  1080. })
  1081.  
  1082. local listFrame = Create('Frame',{
  1083. Name = "List";
  1084. BackgroundTransparency = 1;
  1085. ClipsDescendants = true;
  1086. Position = UDim2.new(0,0,0,HEADER_SIZE);
  1087. Size = UDim2.new(1,-GUI_SIZE,1,-HEADER_SIZE);
  1088. Parent = explorerPanel;
  1089. })
  1090.  
  1091. local scrollBar = ScrollBar(false)
  1092. scrollBar.PageIncrement = 1
  1093. Create(scrollBar.GUI,{
  1094. Position = UDim2.new(1,-GUI_SIZE,0,HEADER_SIZE);
  1095. Size = UDim2.new(0,GUI_SIZE,1,-HEADER_SIZE);
  1096. Parent = explorerPanel;
  1097. })
  1098.  
  1099. local scrollBarH = ScrollBar(true)
  1100. scrollBarH.PageIncrement = GUI_SIZE
  1101. Create(scrollBarH.GUI,{
  1102. Position = UDim2.new(0,0,1,-GUI_SIZE);
  1103. Size = UDim2.new(1,-GUI_SIZE,0,GUI_SIZE);
  1104. Visible = false;
  1105. Parent = explorerPanel;
  1106. })
  1107.  
  1108. local headerFrame = Create('Frame',{
  1109. Name = "Header";
  1110. BackgroundColor3 = GuiColor.Background;
  1111. BorderColor3 = GuiColor.Border;
  1112. Position = UDim2.new(0,0,0,0);
  1113. Size = UDim2.new(1,0,0,HEADER_SIZE);
  1114. Parent = explorerPanel;
  1115. Create('TextLabel',{
  1116. Text = "Explorer";
  1117. BackgroundTransparency = 1;
  1118. TextColor3 = GuiColor.Text;
  1119. TextXAlignment = 'Left';
  1120. Font = FONT;
  1121. FontSize = FONT_SIZE;
  1122. Position = UDim2.new(0,4,0,0);
  1123. Size = UDim2.new(1,-4,1,0);
  1124. });
  1125. })
  1126.  
  1127. SetZIndexOnChanged(explorerPanel)
  1128.  
  1129. local getTextWidth do
  1130. local text = Create('TextLabel',{
  1131. Name = "TextWidth";
  1132. TextXAlignment = 'Left';
  1133. TextYAlignment = 'Center';
  1134. Font = FONT;
  1135. FontSize = FONT_SIZE;
  1136. Text = "";
  1137. Position = UDim2.new(0,0,0,0);
  1138. Size = UDim2.new(1,0,1,0);
  1139. Visible = false;
  1140. Parent = explorerPanel;
  1141. })
  1142. function getTextWidth(s)
  1143. text.Text = s
  1144. return text.TextBounds.x
  1145. end
  1146. end
  1147.  
  1148. -- Holds the game tree converted to a list.
  1149. local TreeList = {}
  1150. -- Matches objects to their tree node representation.
  1151. local NodeLookup = {}
  1152.  
  1153. local nodeWidth = 0
  1154.  
  1155. local updateList,rawUpdateList,updateScroll,rawUpdateSize do
  1156. local function r(t)
  1157. for i = 1,#t do
  1158. TreeList[#TreeList+1] = t[i]
  1159.  
  1160. local w = (t[i].Depth)*(2+ENTRY_PADDING+GUI_SIZE) + 2 + ENTRY_SIZE + 4 + getTextWidth(t[i].Object.Name) + 4
  1161. if w > nodeWidth then
  1162. nodeWidth = w
  1163. end
  1164. if t[i].Expanded then
  1165. r(t[i])
  1166. end
  1167. end
  1168. end
  1169.  
  1170. function rawUpdateSize()
  1171. scrollBarH.TotalSpace = nodeWidth
  1172. scrollBarH.VisibleSpace = listFrame.AbsoluteSize.x
  1173. scrollBarH:Update()
  1174. local visible = scrollBarH:CanScrollDown() or scrollBarH:CanScrollUp()
  1175. scrollBarH.GUI.Visible = visible
  1176.  
  1177. listFrame.Size = UDim2.new(1,-GUI_SIZE,1,-GUI_SIZE*(visible and 1 or 0) - HEADER_SIZE)
  1178.  
  1179. scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
  1180. scrollBar.GUI.Size = UDim2.new(0,GUI_SIZE,1,-GUI_SIZE*(visible and 1 or 0) - HEADER_SIZE)
  1181.  
  1182. scrollBar.TotalSpace = #TreeList+1
  1183. scrollBar:Update()
  1184. end
  1185.  
  1186. function rawUpdateList()
  1187. -- Clear then repopulate the entire list. It appears to be fast enough.
  1188. TreeList = {}
  1189. nodeWidth = 0
  1190. r(NodeLookup[Game])
  1191. rawUpdateSize()
  1192. end
  1193.  
  1194. -- Adding or removing large models will cause many updates to occur. We
  1195. -- can reduce the number of updates by creating a delay, then dropping any
  1196. -- updates that occur during the delay.
  1197. local updatingList = false
  1198. function updateList()
  1199. if updatingList then return end
  1200. updatingList = true
  1201. wait(0.25)
  1202. updatingList = false
  1203. rawUpdateList()
  1204. end
  1205.  
  1206. local updatingScroll = false
  1207. function updateScroll()
  1208. if updatingScroll then return end
  1209. updatingScroll = true
  1210. wait(0.25)
  1211. updatingScroll = false
  1212. scrollBar:Update()
  1213. end
  1214. end
  1215.  
  1216. local Selection do
  1217. local bindGetSelection = script.Parent:FindFirstChild("GetSelection")
  1218. if not bindGetSelection then
  1219. bindGetSelection = Create('BindableFunction',{Name = "GetSelection"})
  1220. bindGetSelection.Parent = script.Parent
  1221. end
  1222.  
  1223. local bindSetSelection = script.Parent:FindFirstChild("SetSelection")
  1224. if not bindSetSelection then
  1225. bindSetSelection = Create('BindableFunction',{Name = "SetSelection"})
  1226. bindSetSelection.Parent = script.Parent
  1227. end
  1228.  
  1229. local bindSelectionChanged = script.Parent:FindFirstChild("SelectionChanged")
  1230. if not bindSelectionChanged then
  1231. bindSelectionChanged = Create('BindableEvent',{Name = "SelectionChanged"})
  1232. bindSelectionChanged.Parent = script.Parent
  1233. end
  1234.  
  1235. local SelectionList = {}
  1236. local SelectionSet = {}
  1237. Selection = {
  1238. Selected = SelectionSet;
  1239. List = SelectionList;
  1240. }
  1241.  
  1242. local function addObject(object)
  1243. -- list update
  1244. local lupdate = false
  1245. -- scroll update
  1246. local supdate = false
  1247.  
  1248. if not SelectionSet[object] then
  1249. local node = NodeLookup[object]
  1250. if node then
  1251. table.insert(SelectionList,object)
  1252. SelectionSet[object] = true
  1253. node.Selected = true
  1254.  
  1255. -- expand all ancestors so that selected node becomes visible
  1256. node = node.Parent
  1257. while node do
  1258. if not node.Expanded then
  1259. node.Expanded = true
  1260. lupdate = true
  1261. end
  1262. node = node.Parent
  1263. end
  1264. supdate = true
  1265. end
  1266. end
  1267. return lupdate,supdate
  1268. end
  1269.  
  1270. function Selection:Set(objects)
  1271. local lupdate = false
  1272. local supdate = false
  1273.  
  1274. if #SelectionList > 0 then
  1275. for i = 1,#SelectionList do
  1276. local object = SelectionList[i]
  1277. local node = NodeLookup[object]
  1278. if node then
  1279. node.Selected = false
  1280. SelectionSet[object] = nil
  1281. end
  1282. end
  1283.  
  1284. SelectionList = {}
  1285. Selection.List = SelectionList
  1286. supdate = true
  1287. end
  1288.  
  1289. for i = 1,#objects do
  1290. local l,s = addObject(objects[i])
  1291. lupdate = l or lupdate
  1292. supdate = s or supdate
  1293. end
  1294.  
  1295. if lupdate then
  1296. rawUpdateList()
  1297. supdate = true
  1298. elseif supdate then
  1299. scrollBar:Update()
  1300. end
  1301.  
  1302. if supdate then
  1303. bindSelectionChanged:Fire()
  1304. end
  1305. end
  1306.  
  1307. function Selection:Add(object)
  1308. local l,s = addObject(object)
  1309. if l then
  1310. rawUpdateList()
  1311. bindSelectionChanged:Fire()
  1312. elseif s then
  1313. scrollBar:Update()
  1314. bindSelectionChanged:Fire()
  1315. end
  1316. end
  1317.  
  1318. function Selection:Remove(object,noupdate)
  1319. if SelectionSet[object] then
  1320. local node = NodeLookup[object]
  1321. if node then
  1322. node.Selected = false
  1323. SelectionSet[object] = nil
  1324. for i = 1,#SelectionList do
  1325. if SelectionList[i] == object then
  1326. table.remove(SelectionList,i)
  1327. break
  1328. end
  1329. end
  1330.  
  1331. if not noupdate then
  1332. scrollBar:Update()
  1333. end
  1334. bindSelectionChanged:Fire()
  1335. end
  1336. end
  1337. end
  1338.  
  1339. function Selection:Get()
  1340. local list = {}
  1341. for i = 1,#SelectionList do
  1342. list[i] = SelectionList[i]
  1343. end
  1344. return list
  1345. end
  1346.  
  1347. bindSetSelection.OnInvoke = function(...)
  1348. Selection:Set(...)
  1349. end
  1350.  
  1351. bindGetSelection.OnInvoke = function()
  1352. return Selection:Get()
  1353. end
  1354. end
  1355.  
  1356. local function cancelReparentDrag()end
  1357. local function cancelSelectDrag()end
  1358. do
  1359. local listEntries = {}
  1360. local nameConnLookup = {}
  1361.  
  1362. local mouseDrag = Create('ImageButton',{
  1363. Name = "MouseDrag";
  1364. Position = UDim2.new(-0.25,0,-0.25,0);
  1365. Size = UDim2.new(1.5,0,1.5,0);
  1366. Transparency = 1;
  1367. AutoButtonColor = false;
  1368. Active = true;
  1369. ZIndex = 10;
  1370. })
  1371. local function dragSelect(last,add,button)
  1372. local connDrag
  1373. local conUp
  1374.  
  1375. conDrag = mouseDrag.MouseMoved:connect(function(x,y)
  1376. local pos = Vector2.new(x,y) - listFrame.AbsolutePosition
  1377. local size = listFrame.AbsoluteSize
  1378. if pos.x < 0 or pos.x > size.x or pos.y < 0 or pos.y > size.y then return end
  1379.  
  1380. local i = math.ceil(pos.y/ENTRY_BOUND) + scrollBar.ScrollIndex
  1381. -- Mouse may have made a large step, so interpolate between the
  1382. -- last index and the current.
  1383. for n = i<last and i or last, i>last and i or last do
  1384. local node = TreeList[n]
  1385. if node then
  1386. if add then
  1387. Selection:Add(node.Object)
  1388. else
  1389. Selection:Remove(node.Object)
  1390. end
  1391. end
  1392. end
  1393. last = i
  1394. end)
  1395.  
  1396. function cancelSelectDrag()
  1397. mouseDrag.Parent = nil
  1398. conDrag:disconnect()
  1399. conUp:disconnect()
  1400. function cancelSelectDrag()end
  1401. end
  1402.  
  1403. conUp = mouseDrag[button]:connect(cancelSelectDrag)
  1404.  
  1405. mouseDrag.Parent = GetScreen(listFrame)
  1406. end
  1407.  
  1408. local function dragReparent(object,dragGhost,clickPos,ghostOffset)
  1409. local connDrag
  1410. local conUp
  1411. local conUp2
  1412.  
  1413. local parentIndex = nil
  1414. local dragged = false
  1415.  
  1416. local parentHighlight = Create('Frame',{
  1417. Transparency = 1;
  1418. Visible = false;
  1419. Create('Frame',{
  1420. BorderSizePixel = 0;
  1421. BackgroundColor3 = Color3.new(0,0,0);
  1422. BackgroundTransparency = 0.1;
  1423. Position = UDim2.new(0,0,0,0);
  1424. Size = UDim2.new(1,0,0,1);
  1425. });
  1426. Create('Frame',{
  1427. BorderSizePixel = 0;
  1428. BackgroundColor3 = Color3.new(0,0,0);
  1429. BackgroundTransparency = 0.1;
  1430. Position = UDim2.new(1,0,0,0);
  1431. Size = UDim2.new(0,1,1,0);
  1432. });
  1433. Create('Frame',{
  1434. BorderSizePixel = 0;
  1435. BackgroundColor3 = Color3.new(0,0,0);
  1436. BackgroundTransparency = 0.1;
  1437. Position = UDim2.new(0,0,1,0);
  1438. Size = UDim2.new(1,0,0,1);
  1439. });
  1440. Create('Frame',{
  1441. BorderSizePixel = 0;
  1442. BackgroundColor3 = Color3.new(0,0,0);
  1443. BackgroundTransparency = 0.1;
  1444. Position = UDim2.new(0,0,0,0);
  1445. Size = UDim2.new(0,1,1,0);
  1446. });
  1447. })
  1448. SetZIndex(parentHighlight,9)
  1449.  
  1450. conDrag = mouseDrag.MouseMoved:connect(function(x,y)
  1451. local dragPos = Vector2.new(x,y)
  1452. if dragged then
  1453. local pos = dragPos - listFrame.AbsolutePosition
  1454. local size = listFrame.AbsoluteSize
  1455.  
  1456. parentIndex = nil
  1457. parentHighlight.Visible = false
  1458. if pos.x >= 0 and pos.x <= size.x and pos.y >= 0 and pos.y <= size.y then
  1459. local i = math.ceil(pos.y/ENTRY_BOUND)
  1460. local node = TreeList[i + scrollBar.ScrollIndex]
  1461. if node and node.Object ~= object and not object:IsAncestorOf(node.Object) then
  1462. parentIndex = i
  1463. local entry = listEntries[i]
  1464. if entry then
  1465. parentHighlight.Visible = true
  1466. parentHighlight.Position = UDim2.new(0,1,0,entry.AbsolutePosition.y-listFrame.AbsolutePosition.y)
  1467. parentHighlight.Size = UDim2.new(0,size.x-4,0,entry.AbsoluteSize.y)
  1468. end
  1469. end
  1470. end
  1471.  
  1472. dragGhost.Position = UDim2.new(0,dragPos.x+ghostOffset.x,0,dragPos.y+ghostOffset.y)
  1473. elseif (clickPos-dragPos).magnitude > 8 then
  1474. dragged = true
  1475. SetZIndex(dragGhost,9)
  1476. dragGhost.IndentFrame.Transparency = 0.25
  1477. dragGhost.IndentFrame.EntryText.TextColor3 = GuiColor.TextSelected
  1478. dragGhost.Position = UDim2.new(0,dragPos.x+ghostOffset.x,0,dragPos.y+ghostOffset.y)
  1479. dragGhost.Parent = GetScreen(listFrame)
  1480. parentHighlight.Parent = listFrame
  1481. end
  1482. end)
  1483.  
  1484. function cancelReparentDrag()
  1485. mouseDrag.Parent = nil
  1486. conDrag:disconnect()
  1487. conUp:disconnect()
  1488. conUp2:disconnect()
  1489. dragGhost:Destroy()
  1490. parentHighlight:Destroy()
  1491. function cancelReparentDrag()end
  1492. end
  1493.  
  1494. local wasSelected = Selection.Selected[object]
  1495. if not wasSelected and Option.Selectable then
  1496. Selection:Set({object})
  1497. end
  1498.  
  1499. conUp = mouseDrag.MouseButton1Up:connect(function()
  1500. cancelReparentDrag()
  1501. if dragged then
  1502. if parentIndex then
  1503. local parentNode = TreeList[parentIndex + scrollBar.ScrollIndex]
  1504. if parentNode then
  1505. parentNode.Expanded = true
  1506.  
  1507. local parentObj = parentNode.Object
  1508. local function parent(a,b)
  1509. a.Parent = b
  1510. end
  1511. if Option.Selectable then
  1512. local list = Selection.List
  1513. for i = 1,#list do
  1514. pcall(parent,list[i],parentObj)
  1515. end
  1516. else
  1517. pcall(parent,object,parentObj)
  1518. end
  1519. end
  1520. end
  1521. else
  1522. -- do selection click
  1523. if wasSelected and Option.Selectable then
  1524. Selection:Set({})
  1525. end
  1526. end
  1527. end)
  1528. conUp2 = mouseDrag.MouseButton2Down:connect(function()
  1529. cancelReparentDrag()
  1530. end)
  1531.  
  1532. mouseDrag.Parent = GetScreen(listFrame)
  1533. end
  1534.  
  1535. local entryTemplate = Create('ImageButton',{
  1536. Name = "Entry";
  1537. Transparency = 1;
  1538. AutoButtonColor = false;
  1539. Position = UDim2.new(0,0,0,0);
  1540. Size = UDim2.new(1,0,0,ENTRY_SIZE);
  1541. Create('Frame',{
  1542. Name = "IndentFrame";
  1543. BackgroundTransparency = 1;
  1544. BackgroundColor3 = GuiColor.Selected;
  1545. BorderColor3 = GuiColor.BorderSelected;
  1546. Position = UDim2.new(0,0,0,0);
  1547. Size = UDim2.new(1,0,1,0);
  1548. Create(Icon('ImageButton',0),{
  1549. Name = "Expand";
  1550. AutoButtonColor = false;
  1551. Position = UDim2.new(0,-GUI_SIZE,0.5,-GUI_SIZE/2);
  1552. Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
  1553. });
  1554. Create(Icon(nil,0),{
  1555. Name = "ExplorerIcon";
  1556. Position = UDim2.new(0,2+ENTRY_PADDING,0.5,-GUI_SIZE/2);
  1557. Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
  1558. });
  1559. Create('TextLabel',{
  1560. Name = "EntryText";
  1561. BackgroundTransparency = 1;
  1562. TextColor3 = GuiColor.Text;
  1563. TextXAlignment = 'Left';
  1564. TextYAlignment = 'Center';
  1565. Font = FONT;
  1566. FontSize = FONT_SIZE;
  1567. Text = "";
  1568. Position = UDim2.new(0,2+ENTRY_SIZE+4,0,0);
  1569. Size = UDim2.new(1,-2,1,0);
  1570. });
  1571. });
  1572. })
  1573.  
  1574. function scrollBar.UpdateCallback(self)
  1575. for i = 1,self.VisibleSpace do
  1576. local node = TreeList[i + self.ScrollIndex]
  1577. if node then
  1578. local entry = listEntries[i]
  1579. if not entry then
  1580. entry = Create(entryTemplate:Clone(),{
  1581. Position = UDim2.new(0,2,0,ENTRY_BOUND*(i-1)+2);
  1582. Size = UDim2.new(0,nodeWidth,0,ENTRY_SIZE);
  1583. ZIndex = listFrame.ZIndex;
  1584. })
  1585. listEntries[i] = entry
  1586.  
  1587. local expand = entry.IndentFrame.Expand
  1588. expand.MouseEnter:connect(function()
  1589. local node = TreeList[i + self.ScrollIndex]
  1590. if #node > 0 then
  1591. if node.Expanded then
  1592. Icon(expand,NODE_EXPANDED_OVER)
  1593. else
  1594. Icon(expand,NODE_COLLAPSED_OVER)
  1595. end
  1596. end
  1597. end)
  1598. expand.MouseLeave:connect(function()
  1599. local node = TreeList[i + self.ScrollIndex]
  1600. if #node > 0 then
  1601. if node.Expanded then
  1602. Icon(expand,NODE_EXPANDED)
  1603. else
  1604. Icon(expand,NODE_COLLAPSED)
  1605. end
  1606. end
  1607. end)
  1608. expand.MouseButton1Down:connect(function()
  1609. local node = TreeList[i + self.ScrollIndex]
  1610. if #node > 0 then
  1611. node.Expanded = not node.Expanded
  1612. -- use raw update so the list updates instantly
  1613. rawUpdateList()
  1614. end
  1615. end)
  1616.  
  1617. entry.MouseButton1Down:connect(function(x,y)
  1618. local node = TreeList[i + self.ScrollIndex]
  1619. if Option.Modifiable then
  1620. local pos = Vector2.new(x,y)
  1621. dragReparent(node.Object,entry:Clone(),pos,entry.AbsolutePosition-pos)
  1622. elseif Option.Selectable then
  1623. if Selection.Selected[node.Object] then
  1624. Selection:Set({})
  1625. else
  1626. Selection:Set({node.Object})
  1627. end
  1628. dragSelect(i+self.ScrollIndex,true,'MouseButton1Up')
  1629. end
  1630. end)
  1631.  
  1632. entry.MouseButton2Down:connect(function()
  1633. if not Option.Selectable then return end
  1634.  
  1635. local node = TreeList[i + self.ScrollIndex]
  1636. if Selection.Selected[node.Object] then
  1637. Selection:Remove(node.Object)
  1638. dragSelect(i+self.ScrollIndex,false,'MouseButton2Up')
  1639. else
  1640. Selection:Add(node.Object)
  1641. dragSelect(i+self.ScrollIndex,true,'MouseButton2Up')
  1642. end
  1643. end)
  1644.  
  1645. entry.Parent = listFrame
  1646. end
  1647.  
  1648. entry.Visible = true
  1649.  
  1650. local object = node.Object
  1651.  
  1652. -- update expand icon
  1653. if #node == 0 then
  1654. entry.IndentFrame.Expand.Visible = false
  1655. elseif node.Expanded then
  1656. Icon(entry.IndentFrame.Expand,NODE_EXPANDED)
  1657. entry.IndentFrame.Expand.Visible = true
  1658. else
  1659. Icon(entry.IndentFrame.Expand,NODE_COLLAPSED)
  1660. entry.IndentFrame.Expand.Visible = true
  1661. end
  1662.  
  1663. -- update explorer icon
  1664. Icon(entry.IndentFrame.ExplorerIcon,ExplorerIndex[object.ClassName] or 0)
  1665.  
  1666. -- update indentation
  1667. local w = (node.Depth)*(2+ENTRY_PADDING+GUI_SIZE)
  1668. entry.IndentFrame.Position = UDim2.new(0,w,0,0)
  1669. entry.IndentFrame.Size = UDim2.new(1,-w,1,0)
  1670.  
  1671. -- update name change detection
  1672. if nameConnLookup[entry] then
  1673. nameConnLookup[entry]:disconnect()
  1674. end
  1675. local text = entry.IndentFrame.EntryText
  1676. text.Text = object.Name
  1677. nameConnLookup[entry] = node.Object.Changed:connect(function(p)
  1678. if p == 'Name' then
  1679. text.Text = object.Name
  1680. end
  1681. end)
  1682.  
  1683. -- update selection
  1684. entry.IndentFrame.Transparency = node.Selected and 0 or 1
  1685. text.TextColor3 = GuiColor[node.Selected and 'TextSelected' or 'Text']
  1686.  
  1687. entry.Size = UDim2.new(0,nodeWidth,0,ENTRY_SIZE)
  1688. elseif listEntries[i] then
  1689. listEntries[i].Visible = false
  1690. end
  1691. end
  1692. for i = self.VisibleSpace+1,self.TotalSpace do
  1693. local entry = listEntries[i]
  1694. if entry then
  1695. listEntries[i] = nil
  1696. entry:Destroy()
  1697. end
  1698. end
  1699. end
  1700.  
  1701. function scrollBarH.UpdateCallback(self)
  1702. for i = 1,scrollBar.VisibleSpace do
  1703. local node = TreeList[i + scrollBar.ScrollIndex]
  1704. if node then
  1705. local entry = listEntries[i]
  1706. if entry then
  1707. entry.Position = UDim2.new(0,2 - scrollBarH.ScrollIndex,0,ENTRY_BOUND*(i-1)+2)
  1708. end
  1709. end
  1710. end
  1711. end
  1712.  
  1713. Connect(listFrame.Changed,function(p)
  1714. if p == 'AbsoluteSize' then
  1715. rawUpdateSize()
  1716. end
  1717. end)
  1718.  
  1719. local wheelAmount = 6
  1720. explorerPanel.MouseWheelForward:connect(function()
  1721. if scrollBar.VisibleSpace - 1 > wheelAmount then
  1722. scrollBar:ScrollTo(scrollBar.ScrollIndex - wheelAmount)
  1723. else
  1724. scrollBar:ScrollTo(scrollBar.ScrollIndex - scrollBar.VisibleSpace)
  1725. end
  1726. end)
  1727. explorerPanel.MouseWheelBackward:connect(function()
  1728. if scrollBar.VisibleSpace - 1 > wheelAmount then
  1729. scrollBar:ScrollTo(scrollBar.ScrollIndex + wheelAmount)
  1730. else
  1731. scrollBar:ScrollTo(scrollBar.ScrollIndex + scrollBar.VisibleSpace)
  1732. end
  1733. end)
  1734. end
  1735.  
  1736. ----------------------------------------------------------------
  1737. ----------------------------------------------------------------
  1738. ----------------------------------------------------------------
  1739. ----------------------------------------------------------------
  1740. ---- Object detection
  1741.  
  1742. -- Inserts `v` into `t` at `i`. Also sets `Index` field in `v`.
  1743. local function insert(t,i,v)
  1744. for n = #t,i,-1 do
  1745. local v = t[n]
  1746. v.Index = n+1
  1747. t[n+1] = v
  1748. end
  1749. v.Index = i
  1750. t[i] = v
  1751. end
  1752.  
  1753. -- Removes `i` from `t`. Also sets `Index` field in removed value.
  1754. local function remove(t,i)
  1755. local v = t[i]
  1756. for n = i+1,#t do
  1757. local v = t[n]
  1758. v.Index = n-1
  1759. t[n-1] = v
  1760. end
  1761. t[#t] = nil
  1762. v.Index = 0
  1763. return v
  1764. end
  1765.  
  1766. -- Returns how deep `o` is in the tree.
  1767. local function depth(o)
  1768. local d = -1
  1769. while o do
  1770. o = o.Parent
  1771. d = d + 1
  1772. end
  1773. return d
  1774. end
  1775.  
  1776.  
  1777. local connLookup = {}
  1778.  
  1779. -- Returns whether a node would be present in the tree list
  1780. local function nodeIsVisible(node)
  1781. local visible = true
  1782. node = node.Parent
  1783. while node and visible do
  1784. visible = visible and node.Expanded
  1785. node = node.Parent
  1786. end
  1787. return visible
  1788. end
  1789.  
  1790. -- Removes an object's tree node. Called when the object stops existing in the
  1791. -- game tree.
  1792. local function removeObject(object)
  1793. local objectNode = NodeLookup[object]
  1794. if not objectNode then
  1795. return
  1796. end
  1797.  
  1798. local visible = nodeIsVisible(objectNode)
  1799.  
  1800. Selection:Remove(object,true)
  1801.  
  1802. local parent = objectNode.Parent
  1803. remove(parent,objectNode.Index)
  1804. NodeLookup[object] = nil
  1805. connLookup[object]:disconnect()
  1806. connLookup[object] = nil
  1807.  
  1808. if visible then
  1809. updateList()
  1810. elseif nodeIsVisible(parent) then
  1811. updateScroll()
  1812. end
  1813. end
  1814.  
  1815. -- Moves a tree node to a new parent. Called when an existing object's parent
  1816. -- changes.
  1817. local function moveObject(object,parent)
  1818. local objectNode = NodeLookup[object]
  1819. if not objectNode then
  1820. return
  1821. end
  1822.  
  1823. local parentNode = NodeLookup[parent]
  1824. if not parentNode then
  1825. return
  1826. end
  1827.  
  1828. local visible = nodeIsVisible(objectNode)
  1829.  
  1830. remove(objectNode.Parent,objectNode.Index)
  1831. objectNode.Parent = parentNode
  1832.  
  1833. objectNode.Depth = depth(object)
  1834. local function r(node,d)
  1835. for i = 1,#node do
  1836. node[i].Depth = d
  1837. r(node[i],d+1)
  1838. end
  1839. end
  1840. r(objectNode,objectNode.Depth+1)
  1841.  
  1842. insert(parentNode,#parentNode+1,objectNode)
  1843.  
  1844. if visible or nodeIsVisible(objectNode) then
  1845. updateList()
  1846. elseif nodeIsVisible(objectNode.Parent) then
  1847. updateScroll()
  1848. end
  1849. end
  1850.  
  1851. -- ScriptContext['/Libraries/LibraryRegistration/LibraryRegistration']
  1852. -- This RobloxLocked object lets me index its properties for some reason
  1853.  
  1854. local function check(object)
  1855. return object.AncestryChanged
  1856. end
  1857.  
  1858. -- Creates a new tree node from an object. Called when an object starts
  1859. -- existing in the game tree.
  1860. local function addObject(object,noupdate)
  1861. if script then
  1862. -- protect against naughty RobloxLocked objects
  1863. local s = pcall(check,object)
  1864. if not s then
  1865. return
  1866. end
  1867. end
  1868.  
  1869. local parentNode = NodeLookup[object.Parent]
  1870. if not parentNode then
  1871. return
  1872. end
  1873.  
  1874. local objectNode = {
  1875. Object = object;
  1876. Parent = parentNode;
  1877. Index = 0;
  1878. Expanded = false;
  1879. Selected = false;
  1880. Depth = depth(object);
  1881. }
  1882.  
  1883. connLookup[object] = Connect(object.AncestryChanged,function(c,p)
  1884. if c == object then
  1885. if p == nil then
  1886. removeObject(c)
  1887. else
  1888. moveObject(c,p)
  1889. end
  1890. end
  1891. end)
  1892.  
  1893. NodeLookup[object] = objectNode
  1894. insert(parentNode,#parentNode+1,objectNode)
  1895.  
  1896. if not noupdate then
  1897. if nodeIsVisible(objectNode) then
  1898. updateList()
  1899. elseif nodeIsVisible(objectNode.Parent) then
  1900. updateScroll()
  1901. end
  1902. end
  1903. end
  1904.  
  1905. do
  1906. NodeLookup[Game] = {
  1907. Object = Game;
  1908. Parent = nil;
  1909. Index = 0;
  1910. Expanded = true;
  1911. }
  1912.  
  1913. Connect(Game.DescendantAdded,addObject)
  1914. Connect(Game.DescendantRemoving,removeObject)
  1915.  
  1916. local function get(o)
  1917. return o:GetChildren()
  1918. end
  1919.  
  1920. local function r(o)
  1921. local s,children = pcall(get,o)
  1922. if s then
  1923. for i = 1,#children do
  1924. addObject(children[i],true)
  1925. r(children[i])
  1926. end
  1927. end
  1928. end
  1929.  
  1930. r(Game)
  1931.  
  1932. scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
  1933. updateList()
  1934. end
  1935.  
  1936. ----------------------------------------------------------------
  1937. ----------------------------------------------------------------
  1938. ----------------------------------------------------------------
  1939. ----------------------------------------------------------------
  1940. ---- Actions
  1941.  
  1942. local actionButtons do
  1943. actionButtons = {}
  1944.  
  1945. local totalActions = (4) + 1
  1946. local currentActions = totalActions
  1947. local function makeButton(icon,over,name)
  1948. local button = Create(Icon('ImageButton',icon),{
  1949. Name = name .. "Button";
  1950. Visible = Option.Modifiable and Option.Selectable;
  1951. Position = UDim2.new(1,-(GUI_SIZE+2)*currentActions+2,0.5,-GUI_SIZE/2);
  1952. Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
  1953. Parent = headerFrame;
  1954. })
  1955.  
  1956. local tipText = Create('TextLabel',{
  1957. Name = name .. "Text";
  1958. Text = name;
  1959. Visible = false;
  1960. BackgroundTransparency = 1;
  1961. TextXAlignment = 'Right';
  1962. Font = FONT;
  1963. FontSize = FONT_SIZE;
  1964. Position = UDim2.new(0,0,0,0);
  1965. Size = UDim2.new(1,-(GUI_SIZE+2)*totalActions,1,0);
  1966. Parent = headerFrame;
  1967. })
  1968.  
  1969.  
  1970. button.MouseEnter:connect(function()
  1971. Icon(button,over)
  1972. tipText.Visible = true
  1973. end)
  1974. button.MouseLeave:connect(function()
  1975. Icon(button,icon)
  1976. tipText.Visible = false
  1977. end)
  1978.  
  1979. currentActions = currentActions - 1
  1980. actionButtons[#actionButtons+1] = button
  1981. return button
  1982. end
  1983.  
  1984. local clipboard = {}
  1985. local function delete(o)
  1986. o.Parent = nil
  1987. end
  1988.  
  1989. -- CUT
  1990. makeButton(ACTION_CUT,ACTION_CUT_OVER,"Cut").MouseButton1Click:connect(function()
  1991. if not Option.Modifiable then return end
  1992. clipboard = {}
  1993. local list = Selection.List
  1994. local cut = {}
  1995. for i = 1,#list do
  1996. local obj = list[i]:Clone()
  1997. if obj then
  1998. table.insert(clipboard,obj)
  1999. table.insert(cut,list[i])
  2000. end
  2001. end
  2002. for i = 1,#cut do
  2003. pcall(delete,cut[i])
  2004. end
  2005. end)
  2006.  
  2007. -- COPY
  2008. makeButton(ACTION_COPY,ACTION_COPY_OVER,"Copy").MouseButton1Click:connect(function()
  2009. if not Option.Modifiable then return end
  2010. clipboard = {}
  2011. local list = Selection.List
  2012. for i = 1,#list do
  2013. table.insert(clipboard,list[i]:Clone())
  2014. end
  2015. end)
  2016.  
  2017. -- PASTE
  2018. makeButton(ACTION_PASTE,ACTION_PASTE_OVER,"Paste").MouseButton1Click:connect(function()
  2019. if not Option.Modifiable then return end
  2020. local parent = Selection.List[1] or Workspace
  2021. for i = 1,#clipboard do
  2022. clipboard[i]:Clone().Parent = parent
  2023. end
  2024. end)
  2025.  
  2026. -- DELETE
  2027. makeButton(ACTION_DELETE,ACTION_DELETE_OVER,"Delete").MouseButton1Click:connect(function()
  2028. if not Option.Modifiable then return end
  2029. local list = Selection:Get()
  2030. for i = 1,#list do
  2031. pcall(delete,list[i])
  2032. end
  2033. Selection:Set({})
  2034. end)
  2035.  
  2036. -- SORT
  2037. -- local actionSort = makeButton(ACTION_SORT,ACTION_SORT_OVER,"Sort")
  2038. end
  2039.  
  2040. ----------------------------------------------------------------
  2041. ----------------------------------------------------------------
  2042. ----------------------------------------------------------------
  2043. ----------------------------------------------------------------
  2044. ---- Option Bindables
  2045.  
  2046. do
  2047. local optionCallback = {
  2048. Modifiable = function(value)
  2049. for i = 1,#actionButtons do
  2050. actionButtons[i].Visible = value and Option.Selectable
  2051. end
  2052. cancelReparentDrag()
  2053. end;
  2054. Selectable = function(value)
  2055. for i = 1,#actionButtons do
  2056. actionButtons[i].Visible = value and Option.Modifiable
  2057. end
  2058. cancelSelectDrag()
  2059. Selection:Set({})
  2060. end;
  2061. }
  2062.  
  2063. local bindSetOption = script.Parent:FindFirstChild("SetOption")
  2064. if not bindSetOption then
  2065. bindSetOption = Create('BindableFunction',{Name = "SetOption"})
  2066. bindSetOption.Parent = script.Parent
  2067. end
  2068.  
  2069. bindSetOption.OnInvoke = function(optionName,value)
  2070. if optionCallback[optionName] then
  2071. Option[optionName] = value
  2072. optionCallback[optionName](value)
  2073. end
  2074. end
  2075.  
  2076. local bindGetOption = script.Parent:FindFirstChild("GetOption")
  2077. if not bindGetOption then
  2078. bindGetOption = Create('BindableFunction',{Name = "GetOption"})
  2079. bindGetOption.Parent = script.Parent
  2080. end
  2081.  
  2082. bindGetOption.OnInvoke = function(optionName)
  2083. if optionName then
  2084. return Option[optionName]
  2085. else
  2086. local options = {}
  2087. for k,v in pairs(Option) do
  2088. options[k] = v
  2089. end
  2090. return options
  2091. end
  2092. end
  2093. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement