· 8 years ago · Jan 05, 2018, 02:36 AM
1--Dex made by Raspberry Pi
2--No loadstring version made(edited) by jackintheblox(V3RMILLION)
3
4gui.Parent = game.CoreGui
5script.Parent = gui
6wait(.5)
7spawn(function()
8local Gui = script.Parent
9
10local SideMenu = Gui:WaitForChild("SideMenu")
11local OpenToggleButton = Gui:WaitForChild("Toggle")
12local CloseToggleButton = SideMenu:WaitForChild("Toggle")
13local ExplorerButton = SideMenu:WaitForChild("Explorer")
14local SettingsButton = SideMenu:WaitForChild("Settings")
15
16local SelectionBox = Instance.new("SelectionBox")
17SelectionBox.Parent = Gui
18
19local ExplorerPanel = Gui:WaitForChild("ExplorerPanel")
20local PropertiesFrame = Gui:WaitForChild("PropertiesFrame")
21local SettingsPanel = Gui:WaitForChild("SettingsPanel")
22
23local SettingsListener = SettingsPanel:WaitForChild("GetSetting")
24
25local ClickSelectOption = SettingsPanel:WaitForChild("ClickSelect"):WaitForChild("Change")
26local SelectionBoxOption = SettingsPanel:WaitForChild("SelectionBox"):WaitForChild("Change")
27local ClearPropsOption = SettingsPanel:WaitForChild("ClearProperties"):WaitForChild("Change")
28local SelectUngroupedOption = SettingsPanel:WaitForChild("SelectUngrouped"):WaitForChild("Change")
29
30local SelectionChanged = ExplorerPanel:WaitForChild("SelectionChanged")
31local GetSelection = ExplorerPanel:WaitForChild("GetSelection")
32local SetSelection = ExplorerPanel:WaitForChild("SetSelection")
33
34local Player = game:GetService("Players").LocalPlayer
35local Mouse = Player:GetMouse()
36
37local CurrentWindow = "Explorer"
38
39local Settings = {
40 ClickSelect = false,
41 SelBox = false,
42 ClearProps = false,
43 SelectUngrouped = true
44}
45
46function Enable(t)
47 for i,v in pairs(t:GetChildren()) do
48 Enable(v)
49 if v:IsA'BaseScript' and not v:IsA'ModuleScript' then
50 v.Disabled = true
51 wait(.5)
52 v.Disabled = false
53 end
54 end
55end
56
57Enable(script.Parent)
58
59function ReturnSetting(set)
60 if set == "ClearProps" then
61 return Settings.ClearProps
62 elseif set == "SelectUngrouped" then
63 return Settings.SelectUngrouped
64 end
65end
66
67OpenToggleButton.MouseButton1Up:connect(function()
68 SideMenu:TweenPosition(UDim2.new(1, -330, 0, 0), "Out", "Quad", 0.5, true)
69
70 if CurrentWindow == "Explorer" then
71 ExplorerPanel:TweenPosition(UDim2.new(1, -300, 0, 0), "Out", "Quad", 0.5, true)
72 PropertiesFrame:TweenPosition(UDim2.new(1, -300, 0.5, 21), "Out", "Quad", 0.5, true)
73 else
74 SettingsPanel:TweenPosition(UDim2.new(1, -300, 0, 0), "Out", "Quad", 0.5, true)
75 end
76
77 OpenToggleButton:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", 0.5, true)
78end)
79
80CloseToggleButton.MouseButton1Up:connect(function()
81 SideMenu:TweenPosition(UDim2.new(1, 0, 0, 0), "Out", "Quad", 0.5, true)
82
83 ExplorerPanel:TweenPosition(UDim2.new(1, 30, 0, 0), "Out", "Quad", 0.5, true)
84 PropertiesFrame:TweenPosition(UDim2.new(1, 30, 0.5, 21), "Out", "Quad", 0.5, true)
85 SettingsPanel:TweenPosition(UDim2.new(1, 30, 0, 0), "Out", "Quad", 0.5, true)
86
87 OpenToggleButton:TweenPosition(UDim2.new(1,-30,0,0), "Out", "Quad", 0.5, true)
88end)
89
90ExplorerButton.MouseButton1Up:connect(function()
91 if CurrentWindow ~= "Explorer" then
92 CurrentWindow = "Explorer"
93
94 ExplorerPanel:TweenPosition(UDim2.new(1, -300, 0, 0), "Out", "Quad", 0.5, true)
95 PropertiesFrame:TweenPosition(UDim2.new(1, -300, 0.5, 21), "Out", "Quad", 0.5, true)
96 SettingsPanel:TweenPosition(UDim2.new(1, 0, 0, 0), "Out", "Quad", 0.5, true)
97 end
98end)
99
100SettingsButton.MouseButton1Up:connect(function()
101 if CurrentWindow ~= "Settings" then
102 CurrentWindow = "Settings"
103
104 ExplorerPanel:TweenPosition(UDim2.new(1, 0, 0, 0), "Out", "Quad", 0.5, true)
105 PropertiesFrame:TweenPosition(UDim2.new(1, 0, 0.5, 21), "Out", "Quad", 0.5, true)
106 SettingsPanel:TweenPosition(UDim2.new(1, -300, 0, 0), "Out", "Quad", 0.5, true)
107 end
108end)
109
110ClickSelectOption.MouseButton1Up:connect(function()
111 if Settings.ClickSelect then
112 Settings.ClickSelect = false
113 ClickSelectOption.Text = "OFF"
114 else
115 Settings.ClickSelect = true
116 ClickSelectOption.Text = "ON"
117 end
118end)
119
120SelectionBoxOption.MouseButton1Up:connect(function()
121 if Settings.SelBox then
122 Settings.SelBox = false
123 SelectionBox.Adornee = nil
124 SelectionBoxOption.Text = "OFF"
125 else
126 Settings.SelBox = true
127 SelectionBoxOption.Text = "ON"
128 end
129end)
130
131ClearPropsOption.MouseButton1Up:connect(function()
132 if Settings.ClearProps then
133 Settings.ClearProps = false
134 ClearPropsOption.Text = "OFF"
135 else
136 Settings.ClearProps = true
137 ClearPropsOption.Text = "ON"
138 end
139end)
140
141SelectUngroupedOption.MouseButton1Up:connect(function()
142 if Settings.SelectUngrouped then
143 Settings.SelectUngrouped = false
144 SelectUngroupedOption.Text = "OFF"
145 else
146 Settings.SelectUngrouped = true
147 SelectUngroupedOption.Text = "ON"
148 end
149end)
150
151local function getSelection()
152 local t = GetSelection:Invoke()
153 if t and #t > 0 then
154 return t[1]
155 else
156 return nil
157 end
158end
159
160Mouse.Button1Down:connect(function()
161 if CurrentWindow == "Explorer" and Settings.ClickSelect then
162 local target = Mouse.Target
163 if target then
164 SetSelection:Invoke({target})
165 end
166 end
167end)
168
169SelectionChanged.Event:connect(function()
170 if Settings.SelBox then
171 local success,err = pcall(function()
172 local selection = getSelection()
173 SelectionBox.Adornee = selection
174 end)
175 if err then
176 SelectionBox.Adornee = nil
177 end
178 end
179end)
180
181SettingsListener.OnInvoke = ReturnSetting
182end)
183
184spawn(function()
185-- initial states
186local Option = {
187 -- can modify object parents in the hierarchy
188 Modifiable = false;
189 -- can select objects
190 Selectable = true;
191}
192
193-- MERELY
194
195Option.Modifiable = true
196
197-- END MERELY
198
199-- general size of GUI objects, in pixels
200local GUI_SIZE = 16
201-- padding between items within each entry
202local ENTRY_PADDING = 1
203-- padding between each entry
204local ENTRY_MARGIN = 1
205
206local Input = game:GetService("UserInputService")
207local HoldingCtrl = false
208local HoldingShift = false
209
210--[[
211
212# Explorer Panel
213
214A GUI panel that displays the game hierarchy.
215
216
217## Selection Bindables
218
219- `Function GetSelection ( )`
220
221 Returns an array of objects representing the objects currently
222 selected in the panel.
223
224- `Function SetSelection ( Objects selection )`
225
226 Sets the objects that are selected in the panel. `selection` is an array
227 of objects.
228
229- `Event SelectionChanged ( )`
230
231 Fired after the selection changes.
232
233
234## Option Bindables
235
236- `Function GetOption ( string optionName )`
237
238 If `optionName` is given, returns the value of that option. Otherwise,
239 returns a table of options and their current values.
240
241- `Function SetOption ( string optionName, bool value )`
242
243 Sets `optionName` to `value`.
244
245 Options:
246
247 - Modifiable
248
249 Whether objects can be modified by the panel.
250
251 Note that modifying objects depends on being able to select them. If
252 Selectable is false, then Actions will not be available. Reparenting
253 is still possible, but only for the dragged object.
254
255 - Selectable
256
257 Whether objects can be selected.
258
259 If Modifiable is false, then left-clicking will perform a drag
260 selection.
261
262## Updates
263
264- 2013-09-18
265 - Fixed explorer icons to match studio explorer.
266
267- 2013-09-14
268 - Added GetOption and SetOption bindables.
269 - Option: Modifiable; sets whether objects can be modified by the panel.
270 - Option: Selectable; sets whether objects can be selected.
271 - Slight modification to left-click selection behavior.
272 - Improved layout and scaling.
273
274- 2013-09-13
275 - Added drag to reparent objects.
276 - Left-click to select/deselect object.
277 - Left-click and drag unselected object to reparent single object.
278 - Left-click and drag selected object to move reparent entire selection.
279 - Right-click while dragging to cancel.
280
281- 2013-09-11
282 - Added explorer panel header with actions.
283 - Added Cut action.
284 - Added Copy action.
285 - Added Paste action.
286 - Added Delete action.
287 - Added drag selection.
288 - Left-click: Add to selection on drag.
289 - Right-click: Add to or remove from selection on drag.
290 - Ensured SelectionChanged fires only when the selection actually changes.
291 - Added documentation and change log.
292 - Fixed thread issue.
293
294- 2013-09-09
295 - Added basic multi-selection.
296 - Left-click to set selection.
297 - Right-click to add to or remove from selection.
298 - Removed "Selection" ObjectValue.
299 - Added GetSelection BindableFunction.
300 - Added SetSelection BindableFunction.
301 - Added SelectionChanged BindableEvent.
302 - Changed font to SourceSans.
303
304- 2013-08-31
305 - Improved GUI sizing based off of `GUI_SIZE` constant.
306 - Automatic font size detection.
307
308- 2013-08-27
309 - Initial explorer panel.
310
311
312## Todo
313
314- Sorting
315 - by ExplorerOrder
316 - by children
317 - by name
318- Drag objects to reparent
319
320]]
321
322local ENTRY_SIZE = GUI_SIZE + ENTRY_PADDING*2
323local ENTRY_BOUND = ENTRY_SIZE + ENTRY_MARGIN
324local HEADER_SIZE = ENTRY_SIZE*2
325
326local FONT = 'SourceSans'
327local FONT_SIZE do
328 local size = {8,9,10,11,12,14,18,24,36,48}
329 local s
330 local n = math.huge
331 for i = 1,#size do
332 if size[i] <= GUI_SIZE then
333 FONT_SIZE = i - 1
334 end
335 end
336end
337
338local GuiColor = {
339 Background = Color3.new(233/255, 233/255, 233/255);
340 Border = Color3.new(149/255, 149/255, 149/255);
341 Selected = Color3.new( 96/255, 140/255, 211/255);
342 BorderSelected = Color3.new( 86/255, 125/255, 188/255);
343 Text = Color3.new( 0/255, 0/255, 0/255);
344 TextDisabled = Color3.new(128/255, 128/255, 128/255);
345 TextSelected = Color3.new(255/255, 255/255, 255/255);
346 Button = Color3.new(221/255, 221/255, 221/255);
347 ButtonBorder = Color3.new(149/255, 149/255, 149/255);
348 ButtonSelected = Color3.new(255/255, 0/255, 0/255);
349 Field = Color3.new(255/255, 255/255, 255/255);
350 FieldBorder = Color3.new(191/255, 191/255, 191/255);
351 TitleBackground = Color3.new(178/255, 178/255, 178/255);
352}
353
354----------------------------------------------------------------
355----------------------------------------------------------------
356----------------------------------------------------------------
357----------------------------------------------------------------
358---- Icon map constants
359
360local MAP_ID = 418720155
361
362-- Indices based on implementation of Icon function.
363local ACTION_CUT = 160
364local ACTION_COPY = 161
365local ACTION_PASTE = 162
366local ACTION_DELETE = 163
367local ACTION_SORT = 164
368local ACTION_CUT_OVER = 174
369local ACTION_COPY_OVER = 175
370local ACTION_PASTE_OVER = 176
371local ACTION_DELETE_OVER = 177
372local ACTION_SORT_OVER = 178
373
374local NODE_COLLAPSED = 165
375local NODE_EXPANDED = 166
376local NODE_COLLAPSED_OVER = 179
377local NODE_EXPANDED_OVER = 180
378
379local ExplorerIndex = {
380 ["Accessory"] = 32;
381 ["Accoutrement"] = 32;
382 ["AdService"] = 73;
383 ["Animation"] = 60;
384 ["AnimationController"] = 60;
385 ["AnimationTrack"] = 60;
386 ["Animator"] = 60;
387 ["ArcHandles"] = 56;
388 ["AssetService"] = 72;
389 ["Attachment"] = 34;
390 ["Backpack"] = 20;
391 ["BadgeService"] = 75;
392 ["BallSocketConstraint"] = 89;
393 ["BillboardGui"] = 64;
394 ["BinaryStringValue"] = 4;
395 ["BindableEvent"] = 67;
396 ["BindableFunction"] = 66;
397 ["BlockMesh"] = 8;
398 ["BloomEffect"] = 90;
399 ["BlurEffect"] = 90;
400 ["BodyAngularVelocity"] = 14;
401 ["BodyForce"] = 14;
402 ["BodyGyro"] = 14;
403 ["BodyPosition"] = 14;
404 ["BodyThrust"] = 14;
405 ["BodyVelocity"] = 14;
406 ["BoolValue"] = 4;
407 ["BoxHandleAdornment"] = 54;
408 ["BrickColorValue"] = 4;
409 ["Camera"] = 5;
410 ["CFrameValue"] = 4;
411 ["CharacterMesh"] = 60;
412 ["Chat"] = 33;
413 ["ClickDetector"] = 41;
414 ["CollectionService"] = 30;
415 ["Color3Value"] = 4;
416 ["ColorCorrectionEffect"] = 90;
417 ["ConeHandleAdornment"] = 54;
418 ["Configuration"] = 58;
419 ["ContentProvider"] = 72;
420 ["ContextActionService"] = 41;
421 ["CoreGui"] = 46;
422 ["CoreScript"] = 18;
423 ["CornerWedgePart"] = 1;
424 ["CustomEvent"] = 4;
425 ["CustomEventReceiver"] = 4;
426 ["CylinderHandleAdornment"] = 54;
427 ["CylinderMesh"] = 8;
428 ["CylindricalConstraint"] = 89;
429 ["Debris"] = 30;
430 ["Decal"] = 7;
431 ["Dialog"] = 62;
432 ["DialogChoice"] = 63;
433 ["DoubleConstrainedValue"] = 4;
434 ["Explosion"] = 36;
435 ["FileMesh"] = 8;
436 ["Fire"] = 61;
437 ["Flag"] = 38;
438 ["FlagStand"] = 39;
439 ["FloorWire"] = 4;
440 ["Folder"] = 70;
441 ["ForceField"] = 37;
442 ["Frame"] = 48;
443 ["GamePassService"] = 19;
444 ["Glue"] = 34;
445 ["GuiButton"] = 52;
446 ["GuiMain"] = 47;
447 ["GuiService"] = 47;
448 ["Handles"] = 53;
449 ["HapticService"] = 84;
450 ["Hat"] = 45;
451 ["HingeConstraint"] = 89;
452 ["Hint"] = 33;
453 ["HopperBin"] = 22;
454 ["HttpService"] = 76;
455 ["Humanoid"] = 9;
456 ["ImageButton"] = 52;
457 ["ImageLabel"] = 49;
458 ["InsertService"] = 72;
459 ["IntConstrainedValue"] = 4;
460 ["IntValue"] = 4;
461 ["JointInstance"] = 34;
462 ["JointsService"] = 34;
463 ["Keyframe"] = 60;
464 ["KeyframeSequence"] = 60;
465 ["KeyframeSequenceProvider"] = 60;
466 ["Lighting"] = 13;
467 ["LineHandleAdornment"] = 54;
468 ["LocalScript"] = 18;
469 ["LogService"] = 87;
470 ["MarketplaceService"] = 46;
471 ["Message"] = 33;
472 ["Model"] = 2;
473 ["ModuleScript"] = 71;
474 ["Motor"] = 34;
475 ["Motor6D"] = 34;
476 ["MoveToConstraint"] = 89;
477 ["NegateOperation"] = 78;
478 ["NetworkClient"] = 16;
479 ["NetworkReplicator"] = 29;
480 ["NetworkServer"] = 15;
481 ["NumberValue"] = 4;
482 ["ObjectValue"] = 4;
483 ["Pants"] = 44;
484 ["ParallelRampPart"] = 1;
485 ["Part"] = 1;
486 ["ParticleEmitter"] = 69;
487 ["PartPairLasso"] = 57;
488 ["PathfindingService"] = 37;
489 ["Platform"] = 35;
490 ["Player"] = 12;
491 ["PlayerGui"] = 46;
492 ["Players"] = 21;
493 ["PlayerScripts"] = 82;
494 ["PointLight"] = 13;
495 ["PointsService"] = 83;
496 ["Pose"] = 60;
497 ["PrismaticConstraint"] = 89;
498 ["PrismPart"] = 1;
499 ["PyramidPart"] = 1;
500 ["RayValue"] = 4;
501 ["ReflectionMetadata"] = 86;
502 ["ReflectionMetadataCallbacks"] = 86;
503 ["ReflectionMetadataClass"] = 86;
504 ["ReflectionMetadataClasses"] = 86;
505 ["ReflectionMetadataEnum"] = 86;
506 ["ReflectionMetadataEnumItem"] = 86;
507 ["ReflectionMetadataEnums"] = 86;
508 ["ReflectionMetadataEvents"] = 86;
509 ["ReflectionMetadataFunctions"] = 86;
510 ["ReflectionMetadataMember"] = 86;
511 ["ReflectionMetadataProperties"] = 86;
512 ["ReflectionMetadataYieldFunctions"] = 86;
513 ["RemoteEvent"] = 80;
514 ["RemoteFunction"] = 79;
515 ["ReplicatedFirst"] = 72;
516 ["ReplicatedStorage"] = 72;
517 ["RightAngleRampPart"] = 1;
518 ["RocketPropulsion"] = 14;
519 ["RodConstraint"] = 89;
520 ["RopeConstraint"] = 89;
521 ["Rotate"] = 34;
522 ["RotateP"] = 34;
523 ["RotateV"] = 34;
524 ["RunService"] = 66;
525 ["ScreenGui"] = 47;
526 ["Script"] = 6;
527 ["ScrollingFrame"] = 48;
528 ["Seat"] = 35;
529 ["Selection"] = 55;
530 ["SelectionBox"] = 54;
531 ["SelectionPartLasso"] = 57;
532 ["SelectionPointLasso"] = 57;
533 ["SelectionSphere"] = 54;
534 ["ServerScriptService"] = 0;
535 ["ServerStorage"] = 74;
536 ["Shirt"] = 43;
537 ["ShirtGraphic"] = 40;
538 ["SkateboardPlatform"] = 35;
539 ["Sky"] = 28;
540 ["SlidingBallConstraint"] = 89;
541 ["Smoke"] = 59;
542 ["Snap"] = 34;
543 ["Sound"] = 11;
544 ["SoundService"] = 31;
545 ["Sparkles"] = 42;
546 ["SpawnLocation"] = 25;
547 ["SpecialMesh"] = 8;
548 ["SphereHandleAdornment"] = 54;
549 ["SpotLight"] = 13;
550 ["SpringConstraint"] = 89;
551 ["StarterCharacterScripts"] = 82;
552 ["StarterGear"] = 20;
553 ["StarterGui"] = 46;
554 ["StarterPack"] = 20;
555 ["StarterPlayer"] = 88;
556 ["StarterPlayerScripts"] = 82;
557 ["Status"] = 2;
558 ["StringValue"] = 4;
559 ["SunRaysEffect"] = 90;
560 ["SurfaceGui"] = 64;
561 ["SurfaceLight"] = 13;
562 ["SurfaceSelection"] = 55;
563 ["Team"] = 24;
564 ["Teams"] = 23;
565 ["TeleportService"] = 81;
566 ["Terrain"] = 65;
567 ["TerrainRegion"] = 65;
568 ["TestService"] = 68;
569 ["TextBox"] = 51;
570 ["TextButton"] = 51;
571 ["TextLabel"] = 50;
572 ["Texture"] = 10;
573 ["TextureTrail"] = 4;
574 ["Tool"] = 17;
575 ["TouchTransmitter"] = 37;
576 ["TrussPart"] = 1;
577 ["UnionOperation"] = 77;
578 ["UserInputService"] = 84;
579 ["Vector3Value"] = 4;
580 ["VehicleSeat"] = 35;
581 ["VelocityMotor"] = 34;
582 ["WedgePart"] = 1;
583 ["Weld"] = 34;
584 ["Workspace"] = 19;
585}
586
587----------------------------------------------------------------
588----------------------------------------------------------------
589----------------------------------------------------------------
590----------------------------------------------------------------
591----------------------------------------------------------------
592
593function Create(ty,data)
594 local obj
595 if type(ty) == 'string' then
596 obj = Instance.new(ty)
597 else
598 obj = ty
599 end
600 for k, v in pairs(data) do
601 if type(k) == 'number' then
602 v.Parent = obj
603 else
604 obj[k] = v
605 end
606 end
607 return obj
608end
609
610local barActive = false
611local activeOptions = {}
612
613function createDDown(dBut, callback,...)
614 if barActive then
615 for i,v in pairs(activeOptions) do
616 v:Destroy()
617 end
618 activeOptions = {}
619 barActive = false
620 return
621 else
622 barActive = true
623 end
624 local slots = {...}
625 local base = dBut
626 for i,v in pairs(slots) do
627 local newOption = base:Clone()
628 newOption.ZIndex = 5
629 newOption.Name = "Option "..tostring(i)
630 newOption.Parent = base.Parent.Parent.Parent
631 newOption.BackgroundTransparency = 0
632 newOption.ZIndex = 2
633 table.insert(activeOptions,newOption)
634 newOption.Position = UDim2.new(-0.4, dBut.Position.X.Offset, dBut.Position.Y.Scale, dBut.Position.Y.Offset + (#activeOptions * dBut.Size.Y.Offset))
635 newOption.Text = slots[i]
636 newOption.MouseButton1Down:connect(function()
637 dBut.Text = slots[i]
638 callback(slots[i])
639 for i,v in pairs(activeOptions) do
640 v:Destroy()
641 end
642 activeOptions = {}
643 barActive = false
644 end)
645 end
646end
647
648-- Connects a function to an event such that it fires asynchronously
649function Connect(event,func)
650 return event:connect(function(...)
651 local a = {...}
652 spawn(function() func(unpack(a)) end)
653 end)
654end
655
656-- returns the ascendant ScreenGui of an object
657function GetScreen(screen)
658 if screen == nil then return nil end
659 while not screen:IsA("ScreenGui") do
660 screen = screen.Parent
661 if screen == nil then return nil end
662 end
663 return screen
664end
665
666do
667 local ZIndexLock = {}
668 -- Sets the ZIndex of an object and its descendants. Objects are locked so
669 -- that SetZIndexOnChanged doesn't spawn multiple threads that set the
670 -- ZIndex of the same object.
671 function SetZIndex(object,z)
672 if not ZIndexLock[object] then
673 ZIndexLock[object] = true
674 if object:IsA'GuiObject' then
675 object.ZIndex = z
676 end
677 local children = object:GetChildren()
678 for i = 1,#children do
679 SetZIndex(children[i],z)
680 end
681 ZIndexLock[object] = nil
682 end
683 end
684
685 function SetZIndexOnChanged(object)
686 return object.Changed:connect(function(p)
687 if p == "ZIndex" then
688 SetZIndex(object,object.ZIndex)
689 end
690 end)
691 end
692end
693
694---- IconMap ----
695-- Image size: 256px x 256px
696-- Icon size: 16px x 16px
697-- Padding between each icon: 2px
698-- Padding around image edge: 1px
699-- Total icons: 14 x 14 (196)
700local Icon do
701 local iconMap = 'http://www.roblox.com/asset/?id=' .. MAP_ID
702 game:GetService('ContentProvider'):Preload(iconMap)
703 local iconDehash do
704 -- 14 x 14, 0-based input, 0-based output
705 local f=math.floor
706 function iconDehash(h)
707 return f(h/14%14),f(h%14)
708 end
709 end
710
711 function Icon(IconFrame,index)
712 local row,col = iconDehash(index)
713 local mapSize = Vector2.new(256,256)
714 local pad,border = 2,1
715 local iconSize = 16
716
717 local class = 'Frame'
718 if type(IconFrame) == 'string' then
719 class = IconFrame
720 IconFrame = nil
721 end
722
723 if not IconFrame then
724 IconFrame = Create(class,{
725 Name = "Icon";
726 BackgroundTransparency = 1;
727 ClipsDescendants = true;
728 Create('ImageLabel',{
729 Name = "IconMap";
730 Active = false;
731 BackgroundTransparency = 1;
732 Image = iconMap;
733 Size = UDim2.new(mapSize.x/iconSize,0,mapSize.y/iconSize,0);
734 });
735 })
736 end
737
738 IconFrame.IconMap.Position = UDim2.new(-col - (pad*(col+1) + border)/iconSize,0,-row - (pad*(row+1) + border)/iconSize,0)
739 return IconFrame
740 end
741end
742
743----------------------------------------------------------------
744----------------------------------------------------------------
745----------------------------------------------------------------
746----------------------------------------------------------------
747---- ScrollBar
748do
749 -- AutoButtonColor doesn't always reset properly
750 local function ResetButtonColor(button)
751 local active = button.Active
752 button.Active = not active
753 button.Active = active
754 end
755
756 local function ArrowGraphic(size,dir,scaled,template)
757 local Frame = Create('Frame',{
758 Name = "Arrow Graphic";
759 BorderSizePixel = 0;
760 Size = UDim2.new(0,size,0,size);
761 Transparency = 1;
762 })
763 if not template then
764 template = Instance.new("Frame")
765 template.BorderSizePixel = 0
766 end
767
768 local transform
769 if dir == nil or dir == 'Up' then
770 function transform(p,s) return p,s end
771 elseif dir == 'Down' then
772 function transform(p,s) return UDim2.new(0,p.X.Offset,0,size-p.Y.Offset-1),s end
773 elseif dir == 'Left' then
774 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
775 elseif dir == 'Right' then
776 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
777 end
778
779 local scale
780 if scaled then
781 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
782 else
783 function scale(p,s) return p,s end
784 end
785
786 local o = math.floor(size/4)
787 if size%2 == 0 then
788 local n = size/2-1
789 for i = 0,n do
790 local t = template:Clone()
791 local p,s = scale(transform(
792 UDim2.new(0,n-i,0,o+i),
793 UDim2.new(0,(i+1)*2,0,1)
794 ))
795 t.Position = p
796 t.Size = s
797 t.Parent = Frame
798 end
799 else
800 local n = (size-1)/2
801 for i = 0,n do
802 local t = template:Clone()
803 local p,s = scale(transform(
804 UDim2.new(0,n-i,0,o+i),
805 UDim2.new(0,i*2+1,0,1)
806 ))
807 t.Position = p
808 t.Size = s
809 t.Parent = Frame
810 end
811 end
812 if size%4 > 1 then
813 local t = template:Clone()
814 local p,s = scale(transform(
815 UDim2.new(0,0,0,size-o-1),
816 UDim2.new(0,size,0,1)
817 ))
818 t.Position = p
819 t.Size = s
820 t.Parent = Frame
821 end
822 return Frame
823 end
824
825
826 local function GripGraphic(size,dir,spacing,scaled,template)
827 local Frame = Create('Frame',{
828 Name = "Grip Graphic";
829 BorderSizePixel = 0;
830 Size = UDim2.new(0,size.x,0,size.y);
831 Transparency = 1;
832 })
833 if not template then
834 template = Instance.new("Frame")
835 template.BorderSizePixel = 0
836 end
837
838 spacing = spacing or 2
839
840 local scale
841 if scaled then
842 function scale(p) return UDim2.new(p.X.Offset/size.x,0,p.Y.Offset/size.y,0) end
843 else
844 function scale(p) return p end
845 end
846
847 if dir == 'Vertical' then
848 for i=0,size.x-1,spacing do
849 local t = template:Clone()
850 t.Size = scale(UDim2.new(0,1,0,size.y))
851 t.Position = scale(UDim2.new(0,i,0,0))
852 t.Parent = Frame
853 end
854 elseif dir == nil or dir == 'Horizontal' then
855 for i=0,size.y-1,spacing do
856 local t = template:Clone()
857 t.Size = scale(UDim2.new(0,size.x,0,1))
858 t.Position = scale(UDim2.new(0,0,0,i))
859 t.Parent = Frame
860 end
861 end
862
863 return Frame
864 end
865
866 local mt = {
867 __index = {
868 GetScrollPercent = function(self)
869 return self.ScrollIndex/(self.TotalSpace-self.VisibleSpace)
870 end;
871 CanScrollDown = function(self)
872 return self.ScrollIndex + self.VisibleSpace < self.TotalSpace
873 end;
874 CanScrollUp = function(self)
875 return self.ScrollIndex > 0
876 end;
877 ScrollDown = function(self)
878 self.ScrollIndex = self.ScrollIndex + self.PageIncrement
879 self:Update()
880 end;
881 ScrollUp = function(self)
882 self.ScrollIndex = self.ScrollIndex - self.PageIncrement
883 self:Update()
884 end;
885 ScrollTo = function(self,index)
886 self.ScrollIndex = index
887 self:Update()
888 end;
889 SetScrollPercent = function(self,percent)
890 self.ScrollIndex = math.floor((self.TotalSpace - self.VisibleSpace)*percent + 0.5)
891 self:Update()
892 end;
893 };
894 }
895 mt.__index.CanScrollRight = mt.__index.CanScrollDown
896 mt.__index.CanScrollLeft = mt.__index.CanScrollUp
897 mt.__index.ScrollLeft = mt.__index.ScrollUp
898 mt.__index.ScrollRight = mt.__index.ScrollDown
899
900 function ScrollBar(horizontal)
901 -- create row scroll bar
902 local ScrollFrame = Create('Frame',{
903 Name = "ScrollFrame";
904 Position = horizontal and UDim2.new(0,0,1,-GUI_SIZE) or UDim2.new(1,-GUI_SIZE,0,0);
905 Size = horizontal and UDim2.new(1,0,0,GUI_SIZE) or UDim2.new(0,GUI_SIZE,1,0);
906 BackgroundTransparency = 1;
907 Create('ImageButton',{
908 Name = "ScrollDown";
909 Position = horizontal and UDim2.new(1,-GUI_SIZE,0,0) or UDim2.new(0,0,1,-GUI_SIZE);
910 Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
911 BackgroundColor3 = GuiColor.Button;
912 BorderColor3 = GuiColor.Border;
913 --BorderSizePixel = 0;
914 });
915 Create('ImageButton',{
916 Name = "ScrollUp";
917 Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
918 BackgroundColor3 = GuiColor.Button;
919 BorderColor3 = GuiColor.Border;
920 --BorderSizePixel = 0;
921 });
922 Create('ImageButton',{
923 Name = "ScrollBar";
924 Size = horizontal and UDim2.new(1,-GUI_SIZE*2,1,0) or UDim2.new(1,0,1,-GUI_SIZE*2);
925 Position = horizontal and UDim2.new(0,GUI_SIZE,0,0) or UDim2.new(0,0,0,GUI_SIZE);
926 AutoButtonColor = false;
927 BackgroundColor3 = Color3.new(0.94902, 0.94902, 0.94902);
928 BorderColor3 = GuiColor.Border;
929 --BorderSizePixel = 0;
930 Create('ImageButton',{
931 Name = "ScrollThumb";
932 AutoButtonColor = false;
933 Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
934 BackgroundColor3 = GuiColor.Button;
935 BorderColor3 = GuiColor.Border;
936 --BorderSizePixel = 0;
937 });
938 });
939 })
940
941 local graphicTemplate = Create('Frame',{
942 Name="Graphic";
943 BorderSizePixel = 0;
944 BackgroundColor3 = GuiColor.Border;
945 })
946 local graphicSize = GUI_SIZE/2
947
948 local ScrollDownFrame = ScrollFrame.ScrollDown
949 local ScrollDownGraphic = ArrowGraphic(graphicSize,horizontal and 'Right' or 'Down',true,graphicTemplate)
950 ScrollDownGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
951 ScrollDownGraphic.Parent = ScrollDownFrame
952 local ScrollUpFrame = ScrollFrame.ScrollUp
953 local ScrollUpGraphic = ArrowGraphic(graphicSize,horizontal and 'Left' or 'Up',true,graphicTemplate)
954 ScrollUpGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
955 ScrollUpGraphic.Parent = ScrollUpFrame
956 local ScrollBarFrame = ScrollFrame.ScrollBar
957 local ScrollThumbFrame = ScrollBarFrame.ScrollThumb
958 do
959 local size = GUI_SIZE*3/8
960 local Decal = GripGraphic(Vector2.new(size,size),horizontal and 'Vertical' or 'Horizontal',2,graphicTemplate)
961 Decal.Position = UDim2.new(0.5,-size/2,0.5,-size/2)
962 Decal.Parent = ScrollThumbFrame
963 end
964
965 local Class = setmetatable({
966 GUI = ScrollFrame;
967 ScrollIndex = 0;
968 VisibleSpace = 0;
969 TotalSpace = 0;
970 PageIncrement = 1;
971 },mt)
972
973 local UpdateScrollThumb
974 if horizontal then
975 function UpdateScrollThumb()
976 ScrollThumbFrame.Size = UDim2.new(Class.VisibleSpace/Class.TotalSpace,0,0,GUI_SIZE)
977 if ScrollThumbFrame.AbsoluteSize.x < GUI_SIZE then
978 ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE)
979 end
980 local barSize = ScrollBarFrame.AbsoluteSize.x
981 ScrollThumbFrame.Position = UDim2.new(Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.x)/barSize,0,0,0)
982 end
983 else
984 function UpdateScrollThumb()
985 ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,Class.VisibleSpace/Class.TotalSpace,0)
986 if ScrollThumbFrame.AbsoluteSize.y < GUI_SIZE then
987 ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE)
988 end
989 local barSize = ScrollBarFrame.AbsoluteSize.y
990 ScrollThumbFrame.Position = UDim2.new(0,0,Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.y)/barSize,0)
991 end
992 end
993
994 local lastDown
995 local lastUp
996 local scrollStyle = {BackgroundColor3=GuiColor.Border,BackgroundTransparency=0}
997 local scrollStyle_ds = {BackgroundColor3=GuiColor.Border,BackgroundTransparency=0.7}
998
999 local function Update()
1000 local t = Class.TotalSpace
1001 local v = Class.VisibleSpace
1002 local s = Class.ScrollIndex
1003 if v <= t then
1004 if s > 0 then
1005 if s + v > t then
1006 Class.ScrollIndex = t - v
1007 end
1008 else
1009 Class.ScrollIndex = 0
1010 end
1011 else
1012 Class.ScrollIndex = 0
1013 end
1014
1015 if Class.UpdateCallback then
1016 if Class.UpdateCallback(Class) == false then
1017 return
1018 end
1019 end
1020
1021 local down = Class:CanScrollDown()
1022 local up = Class:CanScrollUp()
1023 if down ~= lastDown then
1024 lastDown = down
1025 ScrollDownFrame.Active = down
1026 ScrollDownFrame.AutoButtonColor = down
1027 local children = ScrollDownGraphic:GetChildren()
1028 local style = down and scrollStyle or scrollStyle_ds
1029 for i = 1,#children do
1030 Create(children[i],style)
1031 end
1032 end
1033 if up ~= lastUp then
1034 lastUp = up
1035 ScrollUpFrame.Active = up
1036 ScrollUpFrame.AutoButtonColor = up
1037 local children = ScrollUpGraphic:GetChildren()
1038 local style = up and scrollStyle or scrollStyle_ds
1039 for i = 1,#children do
1040 Create(children[i],style)
1041 end
1042 end
1043 ScrollThumbFrame.Visible = down or up
1044 UpdateScrollThumb()
1045 end
1046 Class.Update = Update
1047
1048 SetZIndexOnChanged(ScrollFrame)
1049
1050 local MouseDrag = Create('ImageButton',{
1051 Name = "MouseDrag";
1052 Position = UDim2.new(-0.25,0,-0.25,0);
1053 Size = UDim2.new(1.5,0,1.5,0);
1054 Transparency = 1;
1055 AutoButtonColor = false;
1056 Active = true;
1057 ZIndex = 10;
1058 })
1059
1060 local scrollEventID = 0
1061 ScrollDownFrame.MouseButton1Down:connect(function()
1062 scrollEventID = tick()
1063 local current = scrollEventID
1064 local up_con
1065 up_con = MouseDrag.MouseButton1Up:connect(function()
1066 scrollEventID = tick()
1067 MouseDrag.Parent = nil
1068 ResetButtonColor(ScrollDownFrame)
1069 up_con:disconnect(); drag = nil
1070 end)
1071 MouseDrag.Parent = GetScreen(ScrollFrame)
1072 Class:ScrollDown()
1073 wait(0.2) -- delay before auto scroll
1074 while scrollEventID == current do
1075 Class:ScrollDown()
1076 if not Class:CanScrollDown() then break end
1077 wait()
1078 end
1079 end)
1080
1081 ScrollDownFrame.MouseButton1Up:connect(function()
1082 scrollEventID = tick()
1083 end)
1084
1085 ScrollUpFrame.MouseButton1Down:connect(function()
1086 scrollEventID = tick()
1087 local current = scrollEventID
1088 local up_con
1089 up_con = MouseDrag.MouseButton1Up:connect(function()
1090 scrollEventID = tick()
1091 MouseDrag.Parent = nil
1092 ResetButtonColor(ScrollUpFrame)
1093 up_con:disconnect(); drag = nil
1094 end)
1095 MouseDrag.Parent = GetScreen(ScrollFrame)
1096 Class:ScrollUp()
1097 wait(0.2)
1098 while scrollEventID == current do
1099 Class:ScrollUp()
1100 if not Class:CanScrollUp() then break end
1101 wait()
1102 end
1103 end)
1104
1105 ScrollUpFrame.MouseButton1Up:connect(function()
1106 scrollEventID = tick()
1107 end)
1108
1109 if horizontal then
1110 ScrollBarFrame.MouseButton1Down:connect(function(x,y)
1111 scrollEventID = tick()
1112 local current = scrollEventID
1113 local up_con
1114 up_con = MouseDrag.MouseButton1Up:connect(function()
1115 scrollEventID = tick()
1116 MouseDrag.Parent = nil
1117 ResetButtonColor(ScrollUpFrame)
1118 up_con:disconnect(); drag = nil
1119 end)
1120 MouseDrag.Parent = GetScreen(ScrollFrame)
1121 if x > ScrollThumbFrame.AbsolutePosition.x then
1122 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
1123 wait(0.2)
1124 while scrollEventID == current do
1125 if x < ScrollThumbFrame.AbsolutePosition.x + ScrollThumbFrame.AbsoluteSize.x then break end
1126 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
1127 wait()
1128 end
1129 else
1130 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
1131 wait(0.2)
1132 while scrollEventID == current do
1133 if x > ScrollThumbFrame.AbsolutePosition.x then break end
1134 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
1135 wait()
1136 end
1137 end
1138 end)
1139 else
1140 ScrollBarFrame.MouseButton1Down:connect(function(x,y)
1141 scrollEventID = tick()
1142 local current = scrollEventID
1143 local up_con
1144 up_con = MouseDrag.MouseButton1Up:connect(function()
1145 scrollEventID = tick()
1146 MouseDrag.Parent = nil
1147 ResetButtonColor(ScrollUpFrame)
1148 up_con:disconnect(); drag = nil
1149 end)
1150 MouseDrag.Parent = GetScreen(ScrollFrame)
1151 if y > ScrollThumbFrame.AbsolutePosition.y then
1152 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
1153 wait(0.2)
1154 while scrollEventID == current do
1155 if y < ScrollThumbFrame.AbsolutePosition.y + ScrollThumbFrame.AbsoluteSize.y then break end
1156 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
1157 wait()
1158 end
1159 else
1160 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
1161 wait(0.2)
1162 while scrollEventID == current do
1163 if y > ScrollThumbFrame.AbsolutePosition.y then break end
1164 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
1165 wait()
1166 end
1167 end
1168 end)
1169 end
1170
1171 if horizontal then
1172 ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
1173 scrollEventID = tick()
1174 local mouse_offset = x - ScrollThumbFrame.AbsolutePosition.x
1175 local drag_con
1176 local up_con
1177 drag_con = MouseDrag.MouseMoved:connect(function(x,y)
1178 local bar_abs_pos = ScrollBarFrame.AbsolutePosition.x
1179 local bar_drag = ScrollBarFrame.AbsoluteSize.x - ScrollThumbFrame.AbsoluteSize.x
1180 local bar_abs_one = bar_abs_pos + bar_drag
1181 x = x - mouse_offset
1182 x = x < bar_abs_pos and bar_abs_pos or x > bar_abs_one and bar_abs_one or x
1183 x = x - bar_abs_pos
1184 Class:SetScrollPercent(x/(bar_drag))
1185 end)
1186 up_con = MouseDrag.MouseButton1Up:connect(function()
1187 scrollEventID = tick()
1188 MouseDrag.Parent = nil
1189 ResetButtonColor(ScrollThumbFrame)
1190 drag_con:disconnect(); drag_con = nil
1191 up_con:disconnect(); drag = nil
1192 end)
1193 MouseDrag.Parent = GetScreen(ScrollFrame)
1194 end)
1195 else
1196 ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
1197 scrollEventID = tick()
1198 local mouse_offset = y - ScrollThumbFrame.AbsolutePosition.y
1199 local drag_con
1200 local up_con
1201 drag_con = MouseDrag.MouseMoved:connect(function(x,y)
1202 local bar_abs_pos = ScrollBarFrame.AbsolutePosition.y
1203 local bar_drag = ScrollBarFrame.AbsoluteSize.y - ScrollThumbFrame.AbsoluteSize.y
1204 local bar_abs_one = bar_abs_pos + bar_drag
1205 y = y - mouse_offset
1206 y = y < bar_abs_pos and bar_abs_pos or y > bar_abs_one and bar_abs_one or y
1207 y = y - bar_abs_pos
1208 Class:SetScrollPercent(y/(bar_drag))
1209 end)
1210 up_con = MouseDrag.MouseButton1Up:connect(function()
1211 scrollEventID = tick()
1212 MouseDrag.Parent = nil
1213 ResetButtonColor(ScrollThumbFrame)
1214 drag_con:disconnect(); drag_con = nil
1215 up_con:disconnect(); drag = nil
1216 end)
1217 MouseDrag.Parent = GetScreen(ScrollFrame)
1218 end)
1219 end
1220
1221 function Class:Destroy()
1222 ScrollFrame:Destroy()
1223 MouseDrag:Destroy()
1224 for k in pairs(Class) do
1225 Class[k] = nil
1226 end
1227 setmetatable(Class,nil)
1228 end
1229
1230 Update()
1231
1232 return Class
1233 end
1234end
1235
1236----------------------------------------------------------------
1237----------------------------------------------------------------
1238----------------------------------------------------------------
1239----------------------------------------------------------------
1240---- Explorer panel
1241
1242local explorerPanel = gui.ExplorerPanel
1243Create(explorerPanel,{
1244 BackgroundColor3 = GuiColor.Field;
1245 BorderColor3 = GuiColor.Border;
1246 Active = true;
1247})
1248
1249local SettingsRemote = explorerPanel.Parent:WaitForChild("SettingsPanel"):WaitForChild("GetSetting")
1250local GetApiRemote = explorerPanel.Parent:WaitForChild("PropertiesFrame"):WaitForChild("GetApi")
1251local GetAwaitRemote = explorerPanel.Parent:WaitForChild("PropertiesFrame"):WaitForChild("GetAwaiting")
1252local bindSetAwaiting = explorerPanel.Parent:WaitForChild("PropertiesFrame"):WaitForChild("SetAwaiting")
1253
1254local SaveInstanceWindow = explorerPanel.Parent:WaitForChild("SaveInstance")
1255local ConfirmationWindow = explorerPanel.Parent:WaitForChild("Confirmation")
1256local CautionWindow = explorerPanel.Parent:WaitForChild("Caution")
1257local TableCautionWindow = explorerPanel.Parent:WaitForChild("TableCaution")
1258
1259local RemoteWindow = explorerPanel.Parent:WaitForChild("CallRemote")
1260
1261local CurrentSaveInstanceWindow
1262local CurrentRemoteWindow
1263
1264local lastSelectedNode
1265
1266local listFrame = Create('Frame',{
1267 Name = "List";
1268 BackgroundTransparency = 1;
1269 ClipsDescendants = true;
1270 Position = UDim2.new(0,0,0,HEADER_SIZE);
1271 Size = UDim2.new(1,-GUI_SIZE,1,-HEADER_SIZE);
1272 Parent = explorerPanel;
1273})
1274
1275local scrollBar = ScrollBar(false)
1276scrollBar.PageIncrement = 1
1277Create(scrollBar.GUI,{
1278 Position = UDim2.new(1,-GUI_SIZE,0,HEADER_SIZE);
1279 Size = UDim2.new(0,GUI_SIZE,1,-HEADER_SIZE);
1280 Parent = explorerPanel;
1281})
1282
1283local scrollBarH = ScrollBar(true)
1284scrollBarH.PageIncrement = GUI_SIZE
1285Create(scrollBarH.GUI,{
1286 Position = UDim2.new(0,0,1,-GUI_SIZE);
1287 Size = UDim2.new(1,-GUI_SIZE,0,GUI_SIZE);
1288 Visible = false;
1289 Parent = explorerPanel;
1290})
1291
1292local headerFrame = Create('Frame',{
1293 Name = "Header";
1294 BackgroundColor3 = GuiColor.Background;
1295 BorderColor3 = GuiColor.Border;
1296 Position = UDim2.new(0,0,0,0);
1297 Size = UDim2.new(1,0,0,HEADER_SIZE);
1298 Parent = explorerPanel;
1299 Create('TextLabel',{
1300 Text = "Explorer";
1301 BackgroundTransparency = 1;
1302 TextColor3 = GuiColor.Text;
1303 TextXAlignment = 'Left';
1304 Font = FONT;
1305 FontSize = FONT_SIZE;
1306 Position = UDim2.new(0,4,0,0);
1307 Size = UDim2.new(1,-4,0.5,0);
1308 });
1309})
1310
1311local explorerFilter = Create('TextBox',{
1312 Text = "Filter Workspace";
1313 BackgroundTransparency = 0.8;
1314 TextColor3 = GuiColor.Text;
1315 TextXAlignment = 'Left';
1316 Font = FONT;
1317 FontSize = FONT_SIZE;
1318 Position = UDim2.new(0,4,0.5,0);
1319 Size = UDim2.new(1,-8,0.5,-2);
1320});
1321explorerFilter.Parent = headerFrame
1322
1323SetZIndexOnChanged(explorerPanel)
1324
1325local function CreateColor3(r, g, b) return Color3.new(r/255,g/255,b/255) end
1326
1327local Styles = {
1328 Font = Enum.Font.Arial;
1329 Margin = 5;
1330 Black = CreateColor3(0,0,0);
1331 White = CreateColor3(255,255,255);
1332}
1333
1334local DropDown = {
1335 Font = Styles.Font;
1336 FontSize = Enum.FontSize.Size14;
1337 TextColor = CreateColor3(0,0,0);
1338 TextColorOver = Styles.White;
1339 TextXAlignment = Enum.TextXAlignment.Left;
1340 Height = 20;
1341 BackColor = Styles.White;
1342 BackColorOver = CreateColor3(86,125,188);
1343 BorderColor = CreateColor3(216,216,216);
1344 BorderSizePixel = 2;
1345 ArrowColor = CreateColor3(160,160,160);
1346 ArrowColorOver = Styles.Black;
1347}
1348
1349local Row = {
1350 Font = Styles.Font;
1351 FontSize = Enum.FontSize.Size14;
1352 TextXAlignment = Enum.TextXAlignment.Left;
1353 TextColor = Styles.Black;
1354 TextColorOver = Styles.White;
1355 TextLockedColor = CreateColor3(120,120,120);
1356 Height = 24;
1357 BorderColor = CreateColor3(216,216,216);
1358 BackgroundColor = Styles.White;
1359 BackgroundColorAlternate = CreateColor3(246,246,246);
1360 BackgroundColorMouseover = CreateColor3(211,224,244);
1361 TitleMarginLeft = 15;
1362}
1363
1364local currentRightClickMenu
1365local CurrentInsertObjectWindow
1366local CurrentFunctionCallerWindow
1367
1368local RbxApi
1369
1370function ClassCanCreate(IName)
1371 local success,err = pcall(function() Instance.new(IName) end)
1372 if err then
1373 return false
1374 else
1375 return true
1376 end
1377end
1378
1379function GetClasses()
1380 if RbxApi == nil then return {} end
1381 local classTable = {}
1382 for i,v in pairs(RbxApi.Classes) do
1383 if ClassCanCreate(v.Name) then
1384 table.insert(classTable,v.Name)
1385 end
1386 end
1387 return classTable
1388end
1389
1390local function sortAlphabetic(t, property)
1391 table.sort(t,
1392 function(x,y) return x[property] < y[property]
1393 end)
1394end
1395
1396local function FunctionIsHidden(functionData)
1397 local tags = functionData["tags"]
1398 for _,name in pairs(tags) do
1399 if name == "deprecated"
1400 or name == "hidden"
1401 or name == "writeonly" then
1402 return true
1403 end
1404 end
1405 return false
1406end
1407
1408local function GetAllFunctions(className)
1409 local class = RbxApi.Classes[className]
1410 local functions = {}
1411
1412 if not class then return functions end
1413
1414 while class do
1415 if class.Name == "Instance" then break end
1416 for _,nextFunction in pairs(class.Functions) do
1417 if not FunctionIsHidden(nextFunction) then
1418 table.insert(functions, nextFunction)
1419 end
1420 end
1421 class = RbxApi.Classes[class.Superclass]
1422 end
1423
1424 sortAlphabetic(functions, "Name")
1425
1426 return functions
1427end
1428
1429function GetFunctions()
1430 if RbxApi == nil then return {} end
1431 local List = SelectionVar():Get()
1432
1433 if #List == 0 then return end
1434
1435 local MyObject = List[1]
1436
1437 local functionTable = {}
1438 for i,v in pairs(GetAllFunctions(MyObject.ClassName)) do
1439 table.insert(functionTable,v)
1440 end
1441 return functionTable
1442end
1443
1444function CreateInsertObjectMenu(choices, currentChoice, readOnly, onClick)
1445 local mouse = game.Players.LocalPlayer:GetMouse()
1446 local totalSize = explorerPanel.Parent.AbsoluteSize.y
1447 if #choices == 0 then return end
1448
1449 table.sort(choices, function(a,b) return a < b end)
1450
1451 local frame = Instance.new("Frame")
1452 frame.Name = "InsertObject"
1453 frame.Size = UDim2.new(0, 200, 1, 0)
1454 frame.BackgroundTransparency = 1
1455 frame.Active = true
1456
1457 local menu = nil
1458 local arrow = nil
1459 local expanded = false
1460 local margin = DropDown.BorderSizePixel;
1461
1462 --[[
1463 local button = Instance.new("TextButton")
1464 button.Font = Row.Font
1465 button.FontSize = Row.FontSize
1466 button.TextXAlignment = Row.TextXAlignment
1467 button.BackgroundTransparency = 1
1468 button.TextColor3 = Row.TextColor
1469 if readOnly then
1470 button.TextColor3 = Row.TextLockedColor
1471 end
1472 button.Text = currentChoice
1473 button.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
1474 button.Position = UDim2.new(0, Styles.Margin, 0, 0)
1475 button.Parent = frame
1476 --]]
1477
1478 local function hideMenu()
1479 expanded = false
1480 --showArrow(DropDown.ArrowColor)
1481 if frame then
1482 --frame:Destroy()
1483 CurrentInsertObjectWindow.Visible = false
1484 end
1485 end
1486
1487 local function showMenu()
1488 expanded = true
1489 menu = Instance.new("ScrollingFrame")
1490 menu.Size = UDim2.new(0,200,1,0)
1491 menu.CanvasSize = UDim2.new(0, 200, 0, #choices * DropDown.Height)
1492 menu.Position = UDim2.new(0, margin, 0, 0)
1493 menu.BackgroundTransparency = 0
1494 menu.BackgroundColor3 = DropDown.BackColor
1495 menu.BorderColor3 = DropDown.BorderColor
1496 menu.BorderSizePixel = DropDown.BorderSizePixel
1497 menu.TopImage = "rbxasset://textures/blackBkg_square.png"
1498 menu.MidImage = "rbxasset://textures/blackBkg_square.png"
1499 menu.BottomImage = "rbxasset://textures/blackBkg_square.png"
1500 menu.Active = true
1501 menu.ZIndex = 5
1502 menu.Parent = frame
1503
1504 --local parentFrameHeight = script.Parent.List.Size.Y.Offset
1505 --local rowHeight = mouse.Y
1506 --if (rowHeight + menu.Size.Y.Offset) > parentFrameHeight then
1507 -- menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
1508 --end
1509
1510 local function choice(name)
1511 onClick(name)
1512 hideMenu()
1513 end
1514
1515 for i,name in pairs(choices) do
1516 local option = CreateRightClickMenuItem(name, function()
1517 choice(name)
1518 end,1)
1519 option.Size = UDim2.new(1, 0, 0, 20)
1520 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
1521 option.ZIndex = menu.ZIndex
1522 option.Parent = menu
1523 end
1524 end
1525
1526
1527 showMenu()
1528
1529
1530 return frame
1531end
1532
1533function CreateFunctionCallerMenu(choices, currentChoice, readOnly, onClick)
1534 local mouse = game.Players.LocalPlayer:GetMouse()
1535 local totalSize = explorerPanel.Parent.AbsoluteSize.y
1536 if #choices == 0 then return end
1537
1538 table.sort(choices, function(a,b) return a.Name < b.Name end)
1539
1540 local frame = Instance.new("Frame")
1541 frame.Name = "InsertObject"
1542 frame.Size = UDim2.new(0, 200, 1, 0)
1543 frame.BackgroundTransparency = 1
1544 frame.Active = true
1545
1546 local menu = nil
1547 local arrow = nil
1548 local expanded = false
1549 local margin = DropDown.BorderSizePixel;
1550
1551 local function hideMenu()
1552 expanded = false
1553 --showArrow(DropDown.ArrowColor)
1554 if frame then
1555 --frame:Destroy()
1556 CurrentInsertObjectWindow.Visible = false
1557 end
1558 end
1559
1560 local function showMenu()
1561 expanded = true
1562 menu = Instance.new("ScrollingFrame")
1563 menu.Size = UDim2.new(0,300,1,0)
1564 menu.CanvasSize = UDim2.new(0, 300, 0, #choices * DropDown.Height)
1565 menu.Position = UDim2.new(0, margin, 0, 0)
1566 menu.BackgroundTransparency = 0
1567 menu.BackgroundColor3 = DropDown.BackColor
1568 menu.BorderColor3 = DropDown.BorderColor
1569 menu.BorderSizePixel = DropDown.BorderSizePixel
1570 menu.TopImage = "rbxasset://textures/blackBkg_square.png"
1571 menu.MidImage = "rbxasset://textures/blackBkg_square.png"
1572 menu.BottomImage = "rbxasset://textures/blackBkg_square.png"
1573 menu.Active = true
1574 menu.ZIndex = 5
1575 menu.Parent = frame
1576
1577 --local parentFrameHeight = script.Parent.List.Size.Y.Offset
1578 --local rowHeight = mouse.Y
1579 --if (rowHeight + menu.Size.Y.Offset) > parentFrameHeight then
1580 -- menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
1581 --end
1582
1583 local function GetParameters(functionData)
1584 local paraString = ""
1585 paraString = paraString.."("
1586 for i,v in pairs(functionData.Arguments) do
1587 paraString = paraString..v.Type.." "..v.Name
1588 if i < #functionData.Arguments then
1589 paraString = paraString..", "
1590 end
1591 end
1592 paraString = paraString..")"
1593 return paraString
1594 end
1595
1596 local function choice(name)
1597 onClick(name)
1598 hideMenu()
1599 end
1600
1601 for i,name in pairs(choices) do
1602 local option = CreateRightClickMenuItem(name.ReturnType.." "..name.Name..GetParameters(name), function()
1603 choice(name)
1604 end,2)
1605 option.Size = UDim2.new(1, 0, 0, 20)
1606 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
1607 option.ZIndex = menu.ZIndex
1608 option.Parent = menu
1609 end
1610 end
1611
1612
1613 showMenu()
1614
1615
1616 return frame
1617end
1618
1619function CreateInsertObject()
1620 if not CurrentInsertObjectWindow then return end
1621 CurrentInsertObjectWindow.Visible = true
1622 if currentRightClickMenu and CurrentInsertObjectWindow.Visible then
1623 CurrentInsertObjectWindow.Position = UDim2.new(0,currentRightClickMenu.Position.X.Offset-currentRightClickMenu.Size.X.Offset-2,0,0)
1624 end
1625 if CurrentInsertObjectWindow.Visible then
1626 CurrentInsertObjectWindow.Parent = explorerPanel.Parent
1627 end
1628end
1629
1630function CreateFunctionCaller()
1631 if CurrentFunctionCallerWindow then
1632 CurrentFunctionCallerWindow:Destroy()
1633 CurrentFunctionCallerWindow = nil
1634 end
1635 CurrentFunctionCallerWindow = CreateFunctionCallerMenu(
1636 GetFunctions(),
1637 "",
1638 false,
1639 function(option)
1640 CurrentFunctionCallerWindow:Destroy()
1641 CurrentFunctionCallerWindow = nil
1642 local list = SelectionVar():Get()
1643 for i = 1,#list do
1644 pcall(function() Instance.new(option,list[i]) end)
1645 end
1646 print(option.Name .. " selected to be called. Function caller being added soon, please wait!")
1647 --CallFunction()
1648 DestroyRightClick()
1649 end
1650 )
1651 if currentRightClickMenu and CurrentFunctionCallerWindow then
1652 CurrentFunctionCallerWindow.Position = UDim2.new(0,currentRightClickMenu.Position.X.Offset-currentRightClickMenu.Size.X.Offset*1.5-2,0,0)
1653 end
1654 if CurrentFunctionCallerWindow then
1655 CurrentFunctionCallerWindow.Parent = explorerPanel.Parent
1656 end
1657end
1658
1659function CreateRightClickMenuItem(text, onClick, insObj)
1660 local button = Instance.new("TextButton")
1661 button.Font = DropDown.Font
1662 button.FontSize = DropDown.FontSize
1663 button.TextColor3 = DropDown.TextColor
1664 button.TextXAlignment = DropDown.TextXAlignment
1665 button.BackgroundColor3 = DropDown.BackColor
1666 button.AutoButtonColor = false
1667 button.BorderSizePixel = 0
1668 button.Active = true
1669 button.Text = text
1670
1671 if insObj == 1 then
1672 local newIcon = Icon(nil,ExplorerIndex[text] or 0)
1673 newIcon.Position = UDim2.new(0,0,0,2)
1674 newIcon.Size = UDim2.new(0,16,0,16)
1675 newIcon.IconMap.ZIndex = 5
1676 newIcon.Parent = button
1677 button.Text = "\t\t"..button.Text
1678 elseif insObj == 2 then
1679 button.FontSize = Enum.FontSize.Size11
1680 end
1681
1682 button.MouseEnter:connect(function()
1683 button.TextColor3 = DropDown.TextColorOver
1684 button.BackgroundColor3 = DropDown.BackColorOver
1685 if not insObj and CurrentInsertObjectWindow then
1686 if CurrentInsertObjectWindow.Visible == false and button.Text == "Insert Object" then
1687 CreateInsertObject()
1688 elseif CurrentInsertObjectWindow.Visible and button.Text ~= "Insert Object" then
1689 CurrentInsertObjectWindow.Visible = false
1690 end
1691 end
1692 if not insObj then
1693 if CurrentFunctionCallerWindow and button.Text ~= "Call Function" then
1694 CurrentFunctionCallerWindow:Destroy()
1695 CurrentFunctionCallerWindow = nil
1696 elseif button.Text == "Call Function" then
1697 CreateFunctionCaller()
1698 end
1699 end
1700 end)
1701 button.MouseLeave:connect(function()
1702 button.TextColor3 = DropDown.TextColor
1703 button.BackgroundColor3 = DropDown.BackColor
1704 end)
1705 button.MouseButton1Click:connect(function()
1706 button.TextColor3 = DropDown.TextColor
1707 button.BackgroundColor3 = DropDown.BackColor
1708 onClick(text)
1709 end)
1710 return button
1711end
1712
1713function CreateRightClickMenu(choices, currentChoice, readOnly, onClick)
1714 local mouse = game.Players.LocalPlayer:GetMouse()
1715
1716 local frame = Instance.new("Frame")
1717 frame.Name = "DropDown"
1718 frame.Size = UDim2.new(0, 200, 1, 0)
1719 frame.BackgroundTransparency = 1
1720 frame.Active = true
1721
1722 local menu = nil
1723 local arrow = nil
1724 local expanded = false
1725 local margin = DropDown.BorderSizePixel;
1726
1727 --[[
1728 local button = Instance.new("TextButton")
1729 button.Font = Row.Font
1730 button.FontSize = Row.FontSize
1731 button.TextXAlignment = Row.TextXAlignment
1732 button.BackgroundTransparency = 1
1733 button.TextColor3 = Row.TextColor
1734 if readOnly then
1735 button.TextColor3 = Row.TextLockedColor
1736 end
1737 button.Text = currentChoice
1738 button.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
1739 button.Position = UDim2.new(0, Styles.Margin, 0, 0)
1740 button.Parent = frame
1741 --]]
1742
1743 local function hideMenu()
1744 expanded = false
1745 --showArrow(DropDown.ArrowColor)
1746 if frame then
1747 frame:Destroy()
1748 DestroyRightClick()
1749 end
1750 end
1751
1752 local function showMenu()
1753 expanded = true
1754 menu = Instance.new("Frame")
1755 menu.Size = UDim2.new(0, 200, 0, #choices * DropDown.Height)
1756 menu.Position = UDim2.new(0, margin, 0, 5)
1757 menu.BackgroundTransparency = 0
1758 menu.BackgroundColor3 = DropDown.BackColor
1759 menu.BorderColor3 = DropDown.BorderColor
1760 menu.BorderSizePixel = DropDown.BorderSizePixel
1761 menu.Active = true
1762 menu.ZIndex = 5
1763 menu.Parent = frame
1764
1765 --local parentFrameHeight = script.Parent.List.Size.Y.Offset
1766 --local rowHeight = mouse.Y
1767 --if (rowHeight + menu.Size.Y.Offset) > parentFrameHeight then
1768 -- menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
1769 --end
1770
1771 local function choice(name)
1772 onClick(name)
1773 hideMenu()
1774 end
1775
1776 for i,name in pairs(choices) do
1777 local option = CreateRightClickMenuItem(name, function()
1778 choice(name)
1779 end)
1780 option.Size = UDim2.new(1, 0, 0, 20)
1781 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
1782 option.ZIndex = menu.ZIndex
1783 option.Parent = menu
1784 end
1785 end
1786
1787
1788 showMenu()
1789
1790
1791 return frame
1792end
1793
1794function checkMouseInGui(gui)
1795 if gui == nil then return false end
1796 local plrMouse = game.Players.LocalPlayer:GetMouse()
1797 local guiPosition = gui.AbsolutePosition
1798 local guiSize = gui.AbsoluteSize
1799
1800 if plrMouse.X >= guiPosition.x and plrMouse.X <= guiPosition.x + guiSize.x and plrMouse.Y >= guiPosition.y and plrMouse.Y <= guiPosition.y + guiSize.y then
1801 return true
1802 else
1803 return false
1804 end
1805end
1806
1807local clipboard = {}
1808local function delete(o)
1809 o.Parent = nil
1810end
1811
1812local getTextWidth do
1813 local text = Create('TextLabel',{
1814 Name = "TextWidth";
1815 TextXAlignment = 'Left';
1816 TextYAlignment = 'Center';
1817 Font = FONT;
1818 FontSize = FONT_SIZE;
1819 Text = "";
1820 Position = UDim2.new(0,0,0,0);
1821 Size = UDim2.new(1,0,1,0);
1822 Visible = false;
1823 Parent = explorerPanel;
1824 })
1825 function getTextWidth(s)
1826 text.Text = s
1827 return text.TextBounds.x
1828 end
1829end
1830
1831local nameScanned = false
1832-- Holds the game tree converted to a list.
1833local TreeList = {}
1834-- Matches objects to their tree node representation.
1835local NodeLookup = {}
1836
1837local nodeWidth = 0
1838
1839function filteringWorkspace()
1840 if explorerFilter.Text ~= "" and explorerFilter.Text ~= "Filter Workspace" then
1841 return true
1842 end
1843 return false
1844end
1845
1846function lookForAName(obj,name)
1847 for i,v in pairs(obj:GetChildren()) do
1848 if string.find(string.lower(v.Name),string.lower(name)) then nameScanned = true end
1849 lookForAName(v,name)
1850 end
1851end
1852
1853function scanName(obj)
1854 nameScanned = false
1855 if string.find(string.lower(obj.Name),string.lower(explorerFilter.Text)) then
1856 nameScanned = true
1857 else
1858 lookForAName(obj,explorerFilter.Text)
1859 end
1860 return nameScanned
1861end
1862
1863local updateList,rawUpdateList,updateScroll,rawUpdateSize do
1864 local function r(t)
1865 for i = 1,#t do
1866 if not filteringWorkspace() or scanName(t[i].Object) then
1867 TreeList[#TreeList+1] = t[i]
1868
1869 local w = (t[i].Depth)*(2+ENTRY_PADDING+GUI_SIZE) + 2 + ENTRY_SIZE + 4 + getTextWidth(t[i].Object.Name) + 4
1870 if w > nodeWidth then
1871 nodeWidth = w
1872 end
1873 if t[i].Expanded or filteringWorkspace() then
1874 r(t[i])
1875 end
1876 end
1877 end
1878 end
1879
1880 function rawUpdateSize()
1881 scrollBarH.TotalSpace = nodeWidth
1882 scrollBarH.VisibleSpace = listFrame.AbsoluteSize.x
1883 scrollBarH:Update()
1884 local visible = scrollBarH:CanScrollDown() or scrollBarH:CanScrollUp()
1885 scrollBarH.GUI.Visible = visible
1886
1887 listFrame.Size = UDim2.new(1,-GUI_SIZE,1,-GUI_SIZE*(visible and 1 or 0) - HEADER_SIZE)
1888
1889 scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
1890 scrollBar.GUI.Size = UDim2.new(0,GUI_SIZE,1,-GUI_SIZE*(visible and 1 or 0) - HEADER_SIZE)
1891
1892 scrollBar.TotalSpace = #TreeList+1
1893 scrollBar:Update()
1894 end
1895
1896 function rawUpdateList()
1897 -- Clear then repopulate the entire list. It appears to be fast enough.
1898 TreeList = {}
1899 nodeWidth = 0
1900 r(NodeLookup[workspace.Parent])
1901 rawUpdateSize()
1902 end
1903
1904 -- Adding or removing large models will cause many updates to occur. We
1905 -- can reduce the number of updates by creating a delay, then dropping any
1906 -- updates that occur during the delay.
1907 local updatingList = false
1908 function updateList()
1909 if updatingList then return end
1910 updatingList = true
1911 wait(0.25)
1912 updatingList = false
1913 rawUpdateList()
1914 end
1915
1916 local updatingScroll = false
1917 function updateScroll()
1918 if updatingScroll then return end
1919 updatingScroll = true
1920 wait(0.25)
1921 updatingScroll = false
1922 scrollBar:Update()
1923 end
1924end
1925
1926local Selection do
1927 local bindGetSelection = explorerPanel:FindFirstChild("GetSelection")
1928 if not bindGetSelection then
1929 bindGetSelection = Create('BindableFunction',{Name = "GetSelection"})
1930 bindGetSelection.Parent = explorerPanel
1931 end
1932
1933 local bindSetSelection = explorerPanel:FindFirstChild("SetSelection")
1934 if not bindSetSelection then
1935 bindSetSelection = Create('BindableFunction',{Name = "SetSelection"})
1936 bindSetSelection.Parent = explorerPanel
1937 end
1938
1939 local bindSelectionChanged = explorerPanel:FindFirstChild("SelectionChanged")
1940 if not bindSelectionChanged then
1941 bindSelectionChanged = Create('BindableEvent',{Name = "SelectionChanged"})
1942 bindSelectionChanged.Parent = explorerPanel
1943 end
1944
1945 local SelectionList = {}
1946 local SelectionSet = {}
1947 local Updates = true
1948 Selection = {
1949 Selected = SelectionSet;
1950 List = SelectionList;
1951 }
1952
1953 local function addObject(object)
1954 -- list update
1955 local lupdate = false
1956 -- scroll update
1957 local supdate = false
1958
1959 if not SelectionSet[object] then
1960 local node = NodeLookup[object]
1961 if node then
1962 table.insert(SelectionList,object)
1963 SelectionSet[object] = true
1964 node.Selected = true
1965
1966 -- expand all ancestors so that selected node becomes visible
1967 node = node.Parent
1968 while node do
1969 if not node.Expanded then
1970 node.Expanded = true
1971 lupdate = true
1972 end
1973 node = node.Parent
1974 end
1975 supdate = true
1976 end
1977 end
1978 return lupdate,supdate
1979 end
1980
1981 function Selection:Set(objects)
1982 local lupdate = false
1983 local supdate = false
1984
1985 if #SelectionList > 0 then
1986 for i = 1,#SelectionList do
1987 local object = SelectionList[i]
1988 local node = NodeLookup[object]
1989 if node then
1990 node.Selected = false
1991 SelectionSet[object] = nil
1992 end
1993 end
1994
1995 SelectionList = {}
1996 Selection.List = SelectionList
1997 supdate = true
1998 end
1999
2000 for i = 1,#objects do
2001 local l,s = addObject(objects[i])
2002 lupdate = l or lupdate
2003 supdate = s or supdate
2004 end
2005
2006 if lupdate then
2007 rawUpdateList()
2008 supdate = true
2009 elseif supdate then
2010 scrollBar:Update()
2011 end
2012
2013 if supdate then
2014 bindSelectionChanged:Fire()
2015 end
2016 end
2017
2018 function Selection:Add(object)
2019 local l,s = addObject(object)
2020 if l then
2021 rawUpdateList()
2022 if Updates then
2023 bindSelectionChanged:Fire()
2024 end
2025 elseif s then
2026 scrollBar:Update()
2027 if Updates then
2028 bindSelectionChanged:Fire()
2029 end
2030 end
2031 end
2032
2033 function Selection:StopUpdates()
2034 Updates = false
2035 end
2036
2037 function Selection:ResumeUpdates()
2038 Updates = true
2039 bindSelectionChanged:Fire()
2040 end
2041
2042 function Selection:Remove(object,noupdate)
2043 if SelectionSet[object] then
2044 local node = NodeLookup[object]
2045 if node then
2046 node.Selected = false
2047 SelectionSet[object] = nil
2048 for i = 1,#SelectionList do
2049 if SelectionList[i] == object then
2050 table.remove(SelectionList,i)
2051 break
2052 end
2053 end
2054
2055 if not noupdate then
2056 scrollBar:Update()
2057 end
2058 bindSelectionChanged:Fire()
2059 end
2060 end
2061 end
2062
2063 function Selection:Get()
2064 local list = {}
2065 for i = 1,#SelectionList do
2066 list[i] = SelectionList[i]
2067 end
2068 return list
2069 end
2070
2071 bindSetSelection.OnInvoke = function(...)
2072 Selection:Set(...)
2073 end
2074
2075 bindGetSelection.OnInvoke = function()
2076 return Selection:Get()
2077 end
2078end
2079
2080function CreateCaution(title,msg)
2081 local newCaution = CautionWindow:Clone()
2082 newCaution.Title.Text = title
2083 newCaution.MainWindow.Desc.Text = msg
2084 newCaution.Parent = explorerPanel.Parent
2085 newCaution.Visible = true
2086 newCaution.MainWindow.Ok.MouseButton1Up:connect(function()
2087 newCaution:Destroy()
2088 end)
2089end
2090
2091function CreateTableCaution(title,msg)
2092 if type(msg) ~= "table" then return CreateCaution(title,tostring(msg)) end
2093 local newCaution = TableCautionWindow:Clone()
2094 newCaution.Title.Text = title
2095
2096 local TableList = newCaution.MainWindow.TableResults
2097 local TableTemplate = newCaution.MainWindow.TableTemplate
2098
2099 for i,v in pairs(msg) do
2100 local newResult = TableTemplate:Clone()
2101 newResult.Type.Text = type(v)
2102 newResult.Value.Text = tostring(v)
2103 newResult.Position = UDim2.new(0,0,0,#TableList:GetChildren() * 20)
2104 newResult.Parent = TableList
2105 TableList.CanvasSize = UDim2.new(0,0,0,#TableList:GetChildren() * 20)
2106 newResult.Visible = true
2107 end
2108 newCaution.Parent = explorerPanel.Parent
2109 newCaution.Visible = true
2110 newCaution.MainWindow.Ok.MouseButton1Up:connect(function()
2111 newCaution:Destroy()
2112 end)
2113end
2114
2115local function Split(str, delimiter)
2116 local start = 1
2117 local t = {}
2118 while true do
2119 local pos = string.find (str, delimiter, start, true)
2120 if not pos then
2121 break
2122 end
2123 table.insert (t, string.sub (str, start, pos - 1))
2124 start = pos + string.len (delimiter)
2125 end
2126 table.insert (t, string.sub (str, start))
2127 return t
2128end
2129
2130local function ToValue(value,type)
2131 if type == "Vector2" then
2132 local list = Split(value,",")
2133 if #list < 2 then return nil end
2134 local x = tonumber(list[1]) or 0
2135 local y = tonumber(list[2]) or 0
2136 return Vector2.new(x,y)
2137 elseif type == "Vector3" then
2138 local list = Split(value,",")
2139 if #list < 3 then return nil end
2140 local x = tonumber(list[1]) or 0
2141 local y = tonumber(list[2]) or 0
2142 local z = tonumber(list[3]) or 0
2143 return Vector3.new(x,y,z)
2144 elseif type == "Color3" then
2145 local list = Split(value,",")
2146 if #list < 3 then return nil end
2147 local r = tonumber(list[1]) or 0
2148 local g = tonumber(list[2]) or 0
2149 local b = tonumber(list[3]) or 0
2150 return Color3.new(r/255,g/255, b/255)
2151 elseif type == "UDim2" then
2152 local list = Split(string.gsub(string.gsub(value, "{", ""),"}",""),",")
2153 if #list < 4 then return nil end
2154 local xScale = tonumber(list[1]) or 0
2155 local xOffset = tonumber(list[2]) or 0
2156 local yScale = tonumber(list[3]) or 0
2157 local yOffset = tonumber(list[4]) or 0
2158 return UDim2.new(xScale, xOffset, yScale, yOffset)
2159 elseif type == "Number" then
2160 return tonumber(value)
2161 elseif type == "String" then
2162 return value
2163 elseif type == "NumberRange" then
2164 local list = Split(value,",")
2165 if #list == 1 then
2166 if tonumber(list[1]) == nil then return nil end
2167 local newVal = tonumber(list[1]) or 0
2168 return NumberRange.new(newVal)
2169 end
2170 if #list < 2 then return nil end
2171 local x = tonumber(list[1]) or 0
2172 local y = tonumber(list[2]) or 0
2173 return NumberRange.new(x,y)
2174 elseif type == "Script" then
2175 local success,err = ypcall(function()
2176 _G.D_E_X_DONOTUSETHISPLEASE = nil
2177 loadstring(
2178 "_G.D_E_X_DONOTUSETHISPLEASE = "..value
2179 )()
2180 return _G.D_E_X_DONOTUSETHISPLEASE
2181 end)
2182 if err then
2183 return nil
2184 end
2185 else
2186 return nil
2187 end
2188end
2189
2190function PromptRemoteCaller(inst)
2191 if CurrentRemoteWindow then
2192 CurrentRemoteWindow:Destroy()
2193 CurrentRemoteWindow = nil
2194 end
2195 CurrentRemoteWindow = RemoteWindow:Clone()
2196 CurrentRemoteWindow.Parent = explorerPanel.Parent
2197 CurrentRemoteWindow.Visible = true
2198
2199 local displayValues = false
2200
2201 local ArgumentList = CurrentRemoteWindow.MainWindow.Arguments
2202 local ArgumentTemplate = CurrentRemoteWindow.MainWindow.ArgumentTemplate
2203
2204 if inst:IsA("RemoteEvent") then
2205 CurrentRemoteWindow.Title.Text = "Fire Event"
2206 CurrentRemoteWindow.MainWindow.Ok.Text = "Fire"
2207 CurrentRemoteWindow.MainWindow.DisplayReturned.Visible = false
2208 CurrentRemoteWindow.MainWindow.Desc2.Visible = false
2209 end
2210
2211 local newArgument = ArgumentTemplate:Clone()
2212 newArgument.Parent = ArgumentList
2213 newArgument.Visible = true
2214 newArgument.Type.MouseButton1Down:connect(function()
2215 createDDown(newArgument.Type,function(choice)
2216 newArgument.Type.Text = choice
2217 end,"Script","Number","String","Color3","Vector3","Vector2","UDim2","NumberRange")
2218 end)
2219
2220 CurrentRemoteWindow.MainWindow.Ok.MouseButton1Up:connect(function()
2221 if CurrentRemoteWindow and inst.Parent ~= nil then
2222 local MyArguments = {}
2223 for i,v in pairs(ArgumentList:GetChildren()) do
2224 table.insert(MyArguments,ToValue(v.Value.Text,v.Type.Text))
2225 end
2226 if inst:IsA("RemoteFunction") then
2227 if displayValues then
2228 spawn(function()
2229 local myResults = inst:InvokeServer(unpack(MyArguments))
2230 if myResults then
2231 CreateTableCaution("Remote Caller",myResults)
2232 else
2233 CreateCaution("Remote Caller","This remote did not return anything.")
2234 end
2235 end)
2236 else
2237 spawn(function()
2238 inst:InvokeServer(unpack(MyArguments))
2239 end)
2240 end
2241 else
2242 inst:FireServer(unpack(MyArguments))
2243 end
2244 CurrentRemoteWindow:Destroy()
2245 CurrentRemoteWindow = nil
2246 end
2247 end)
2248
2249 CurrentRemoteWindow.MainWindow.Add.MouseButton1Up:connect(function()
2250 if CurrentRemoteWindow then
2251 local newArgument = ArgumentTemplate:Clone()
2252 newArgument.Position = UDim2.new(0,0,0,#ArgumentList:GetChildren() * 20)
2253 newArgument.Parent = ArgumentList
2254 ArgumentList.CanvasSize = UDim2.new(0,0,0,#ArgumentList:GetChildren() * 20)
2255 newArgument.Visible = true
2256 newArgument.Type.MouseButton1Down:connect(function()
2257 createDDown(newArgument.Type,function(choice)
2258 newArgument.Type.Text = choice
2259 end,"Script","Number","String","Color3","Vector3","Vector2","UDim2","NumberRange")
2260 end)
2261 end
2262 end)
2263
2264 CurrentRemoteWindow.MainWindow.Subtract.MouseButton1Up:connect(function()
2265 if CurrentRemoteWindow then
2266 if #ArgumentList:GetChildren() > 1 then
2267 ArgumentList:GetChildren()[#ArgumentList:GetChildren()]:Destroy()
2268 ArgumentList.CanvasSize = UDim2.new(0,0,0,#ArgumentList:GetChildren() * 20)
2269 end
2270 end
2271 end)
2272
2273 CurrentRemoteWindow.MainWindow.Cancel.MouseButton1Up:connect(function()
2274 if CurrentRemoteWindow then
2275 CurrentRemoteWindow:Destroy()
2276 CurrentRemoteWindow = nil
2277 end
2278 end)
2279
2280 CurrentRemoteWindow.MainWindow.DisplayReturned.MouseButton1Up:connect(function()
2281 if displayValues then
2282 displayValues = false
2283 CurrentRemoteWindow.MainWindow.DisplayReturned.enabled.Visible = false
2284 else
2285 displayValues = true
2286 CurrentRemoteWindow.MainWindow.DisplayReturned.enabled.Visible = true
2287 end
2288 end)
2289end
2290
2291function PromptSaveInstance(inst)
2292 if not SaveInstance and not _G.SaveInstance then CreateCaution("SaveInstance Missing","You do not have the SaveInstance function installed. Please go to RaspberryPi's thread to retrieve it.") return end
2293 if CurrentSaveInstanceWindow then
2294 CurrentSaveInstanceWindow:Destroy()
2295 CurrentSaveInstanceWindow = nil
2296 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2297 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2298 end
2299 end
2300 CurrentSaveInstanceWindow = SaveInstanceWindow:Clone()
2301 CurrentSaveInstanceWindow.Parent = explorerPanel.Parent
2302 CurrentSaveInstanceWindow.Visible = true
2303
2304 local filename = CurrentSaveInstanceWindow.MainWindow.FileName
2305 local saveObjects = true
2306 local overwriteCaution = false
2307
2308 CurrentSaveInstanceWindow.MainWindow.Save.MouseButton1Up:connect(function()
2309 if readfile and getelysianpath then
2310 if readfile(getelysianpath()..filename.Text..".rbxmx") then
2311 if not overwriteCaution then
2312 overwriteCaution = true
2313 local newCaution = ConfirmationWindow:Clone()
2314 newCaution.Name = "SaveInstanceOverwriteCaution"
2315 newCaution.MainWindow.Desc.Text = "The file, "..filename.Text..".rbxmx, already exists. Overwrite?"
2316 newCaution.Parent = explorerPanel.Parent
2317 newCaution.Visible = true
2318 newCaution.MainWindow.Yes.MouseButton1Up:connect(function()
2319 ypcall(function()
2320 SaveInstance(inst,filename.Text..".rbxmx",not saveObjects)
2321 end)
2322 overwriteCaution = false
2323 newCaution:Destroy()
2324 if CurrentSaveInstanceWindow then
2325 CurrentSaveInstanceWindow:Destroy()
2326 CurrentSaveInstanceWindow = nil
2327 end
2328 end)
2329 newCaution.MainWindow.No.MouseButton1Up:connect(function()
2330 overwriteCaution = false
2331 newCaution:Destroy()
2332 end)
2333 end
2334 else
2335 ypcall(function()
2336 SaveInstance(inst,filename.Text..".rbxmx",not saveObjects)
2337 end)
2338 if CurrentSaveInstanceWindow then
2339 CurrentSaveInstanceWindow:Destroy()
2340 CurrentSaveInstanceWindow = nil
2341 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2342 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2343 end
2344 end
2345 end
2346 else
2347 ypcall(function()
2348 if SaveInstance then
2349 SaveInstance(inst,filename.Text..".rbxmx",not saveObjects)
2350 else
2351 _G.SaveInstance(inst,filename.Text,not saveObjects)
2352 end
2353 end)
2354 if CurrentSaveInstanceWindow then
2355 CurrentSaveInstanceWindow:Destroy()
2356 CurrentSaveInstanceWindow = nil
2357 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2358 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2359 end
2360 end
2361 end
2362 end)
2363 CurrentSaveInstanceWindow.MainWindow.Cancel.MouseButton1Up:connect(function()
2364 if CurrentSaveInstanceWindow then
2365 CurrentSaveInstanceWindow:Destroy()
2366 CurrentSaveInstanceWindow = nil
2367 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2368 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2369 end
2370 end
2371 end)
2372 CurrentSaveInstanceWindow.MainWindow.SaveObjects.MouseButton1Up:connect(function()
2373 if saveObjects then
2374 saveObjects = false
2375 CurrentSaveInstanceWindow.MainWindow.SaveObjects.enabled.Visible = false
2376 else
2377 saveObjects = true
2378 CurrentSaveInstanceWindow.MainWindow.SaveObjects.enabled.Visible = true
2379 end
2380 end)
2381end
2382
2383function DestroyRightClick()
2384 if currentRightClickMenu then
2385 currentRightClickMenu:Destroy()
2386 currentRightClickMenu = nil
2387 end
2388 if CurrentInsertObjectWindow and CurrentInsertObjectWindow.Visible then
2389 CurrentInsertObjectWindow.Visible = false
2390 end
2391end
2392
2393function rightClickMenu(sObj)
2394 local mouse = game.Players.LocalPlayer:GetMouse()
2395
2396 currentRightClickMenu = CreateRightClickMenu(
2397 {"Cut","Copy","Paste Into","Duplicate","Delete","Group","Ungroup","Select Children","Teleport To","Insert Part","Insert Object","Save Instance","Call Function","Call Remote"},
2398 "",
2399 false,
2400 function(option)
2401 if option == "Cut" then
2402 if not Option.Modifiable then return end
2403 clipboard = {}
2404 local list = Selection.List
2405 local cut = {}
2406 for i = 1,#list do
2407 local obj = list[i]:Clone()
2408 if obj then
2409 table.insert(clipboard,obj)
2410 table.insert(cut,list[i])
2411 end
2412 end
2413 for i = 1,#cut do
2414 pcall(delete,cut[i])
2415 end
2416 elseif option == "Copy" then
2417 if not Option.Modifiable then return end
2418 clipboard = {}
2419 local list = Selection.List
2420 for i = 1,#list do
2421 table.insert(clipboard,list[i]:Clone())
2422 end
2423 elseif option == "Paste Into" then
2424 if not Option.Modifiable then return end
2425 local parent = Selection.List[1] or workspace
2426 for i = 1,#clipboard do
2427 clipboard[i]:Clone().Parent = parent
2428 end
2429 elseif option == "Duplicate" then
2430 if not Option.Modifiable then return end
2431 local list = Selection:Get()
2432 for i = 1,#list do
2433 list[i]:Clone().Parent = Selection.List[1].Parent or workspace
2434 end
2435 elseif option == "Delete" then
2436 if not Option.Modifiable then return end
2437 local list = Selection:Get()
2438 for i = 1,#list do
2439 pcall(delete,list[i])
2440 end
2441 Selection:Set({})
2442 elseif option == "Group" then
2443 if not Option.Modifiable then return end
2444 local newModel = Instance.new("Model")
2445 local list = Selection:Get()
2446 newModel.Parent = Selection.List[1].Parent or workspace
2447 for i = 1,#list do
2448 list[i].Parent = newModel
2449 end
2450 Selection:Set({})
2451 elseif option == "Ungroup" then
2452 if not Option.Modifiable then return end
2453 local ungrouped = {}
2454 local list = Selection:Get()
2455 for i = 1,#list do
2456 if list[i]:IsA("Model") then
2457 for i2,v2 in pairs(list[i]:GetChildren()) do
2458 v2.Parent = list[i].Parent or workspace
2459 table.insert(ungrouped,v2)
2460 end
2461 pcall(delete,list[i])
2462 end
2463 end
2464 Selection:Set({})
2465 if SettingsRemote:Invoke("SelectUngrouped") then
2466 for i,v in pairs(ungrouped) do
2467 Selection:Add(v)
2468 end
2469 end
2470 elseif option == "Select Children" then
2471 if not Option.Modifiable then return end
2472 local list = Selection:Get()
2473 Selection:Set({})
2474 Selection:StopUpdates()
2475 for i = 1,#list do
2476 for i2,v2 in pairs(list[i]:GetChildren()) do
2477 Selection:Add(v2)
2478 end
2479 end
2480 Selection:ResumeUpdates()
2481 elseif option == "Teleport To" then
2482 if not Option.Modifiable then return end
2483 local list = Selection:Get()
2484 for i = 1,#list do
2485 if list[i]:IsA("BasePart") then
2486 pcall(function()
2487 game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = list[i].CFrame
2488 end)
2489 break
2490 end
2491 end
2492 elseif option == "Insert Part" then
2493 if not Option.Modifiable then return end
2494 local insertedParts = {}
2495 local list = Selection:Get()
2496 for i = 1,#list do
2497 pcall(function()
2498 local newPart = Instance.new("Part")
2499 newPart.Parent = list[i]
2500 newPart.CFrame = CFrame.new(game.Players.LocalPlayer.Character.Head.Position) + Vector3.new(0,3,0)
2501 table.insert(insertedParts,newPart)
2502 end)
2503 end
2504 elseif option == "Save Instance" then
2505 if not Option.Modifiable then return end
2506 local list = Selection:Get()
2507 if #list == 1 then
2508 list[1].Archivable = true
2509 ypcall(function()PromptSaveInstance(list[1]:Clone())end)
2510 elseif #list > 1 then
2511 local newModel = Instance.new("Model")
2512 newModel.Name = "SavedInstances"
2513 for i = 1,#list do
2514 ypcall(function()
2515 list[i].Archivable = true
2516 list[i]:Clone().Parent = newModel
2517 end)
2518 end
2519 PromptSaveInstance(newModel)
2520 end
2521 elseif option == "Call Remote" then
2522 if not Option.Modifiable then return end
2523 local list = Selection:Get()
2524 for i = 1,#list do
2525 if list[i]:IsA("RemoteFunction") or list[i]:IsA("RemoteEvent") then
2526 PromptRemoteCaller(list[i])
2527 break
2528 end
2529 end
2530 end
2531 end)
2532 currentRightClickMenu.Parent = explorerPanel.Parent
2533 currentRightClickMenu.Position = UDim2.new(0,mouse.X,0,mouse.Y)
2534 if currentRightClickMenu.AbsolutePosition.X + currentRightClickMenu.AbsoluteSize.X > explorerPanel.AbsolutePosition.X + explorerPanel.AbsoluteSize.X then
2535 currentRightClickMenu.Position = UDim2.new(0, explorerPanel.AbsolutePosition.X + explorerPanel.AbsoluteSize.X - currentRightClickMenu.AbsoluteSize.X, 0, mouse.Y)
2536 end
2537end
2538
2539local function cancelReparentDrag()end
2540local function cancelSelectDrag()end
2541do
2542 local listEntries = {}
2543 local nameConnLookup = {}
2544
2545 local mouseDrag = Create('ImageButton',{
2546 Name = "MouseDrag";
2547 Position = UDim2.new(-0.25,0,-0.25,0);
2548 Size = UDim2.new(1.5,0,1.5,0);
2549 Transparency = 1;
2550 AutoButtonColor = false;
2551 Active = true;
2552 ZIndex = 10;
2553 })
2554 local function dragSelect(last,add,button)
2555 local connDrag
2556 local conUp
2557
2558 conDrag = mouseDrag.MouseMoved:connect(function(x,y)
2559 local pos = Vector2.new(x,y) - listFrame.AbsolutePosition
2560 local size = listFrame.AbsoluteSize
2561 if pos.x < 0 or pos.x > size.x or pos.y < 0 or pos.y > size.y then return end
2562
2563 local i = math.ceil(pos.y/ENTRY_BOUND) + scrollBar.ScrollIndex
2564 -- Mouse may have made a large step, so interpolate between the
2565 -- last index and the current.
2566 for n = i<last and i or last, i>last and i or last do
2567 local node = TreeList[n]
2568 if node then
2569 if add then
2570 Selection:Add(node.Object)
2571 else
2572 Selection:Remove(node.Object)
2573 end
2574 end
2575 end
2576 last = i
2577 end)
2578
2579 function cancelSelectDrag()
2580 mouseDrag.Parent = nil
2581 conDrag:disconnect()
2582 conUp:disconnect()
2583 function cancelSelectDrag()end
2584 end
2585
2586 conUp = mouseDrag[button]:connect(cancelSelectDrag)
2587
2588 mouseDrag.Parent = GetScreen(listFrame)
2589 end
2590
2591 local function dragReparent(object,dragGhost,clickPos,ghostOffset)
2592 local connDrag
2593 local conUp
2594 local conUp2
2595
2596 local parentIndex = nil
2597 local dragged = false
2598
2599 local parentHighlight = Create('Frame',{
2600 Transparency = 1;
2601 Visible = false;
2602 Create('Frame',{
2603 BorderSizePixel = 0;
2604 BackgroundColor3 = Color3.new(0,0,0);
2605 BackgroundTransparency = 0.1;
2606 Position = UDim2.new(0,0,0,0);
2607 Size = UDim2.new(1,0,0,1);
2608 });
2609 Create('Frame',{
2610 BorderSizePixel = 0;
2611 BackgroundColor3 = Color3.new(0,0,0);
2612 BackgroundTransparency = 0.1;
2613 Position = UDim2.new(1,0,0,0);
2614 Size = UDim2.new(0,1,1,0);
2615 });
2616 Create('Frame',{
2617 BorderSizePixel = 0;
2618 BackgroundColor3 = Color3.new(0,0,0);
2619 BackgroundTransparency = 0.1;
2620 Position = UDim2.new(0,0,1,0);
2621 Size = UDim2.new(1,0,0,1);
2622 });
2623 Create('Frame',{
2624 BorderSizePixel = 0;
2625 BackgroundColor3 = Color3.new(0,0,0);
2626 BackgroundTransparency = 0.1;
2627 Position = UDim2.new(0,0,0,0);
2628 Size = UDim2.new(0,1,1,0);
2629 });
2630 })
2631 SetZIndex(parentHighlight,9)
2632
2633 conDrag = mouseDrag.MouseMoved:connect(function(x,y)
2634 local dragPos = Vector2.new(x,y)
2635 if dragged then
2636 local pos = dragPos - listFrame.AbsolutePosition
2637 local size = listFrame.AbsoluteSize
2638
2639 parentIndex = nil
2640 parentHighlight.Visible = false
2641 if pos.x >= 0 and pos.x <= size.x and pos.y >= 0 and pos.y <= size.y + ENTRY_SIZE*2 then
2642 local i = math.ceil(pos.y/ENTRY_BOUND-2)
2643 local node = TreeList[i + scrollBar.ScrollIndex]
2644 if node and node.Object ~= object and not object:IsAncestorOf(node.Object) then
2645 parentIndex = i
2646 local entry = listEntries[i]
2647 if entry then
2648 parentHighlight.Visible = true
2649 parentHighlight.Position = UDim2.new(0,1,0,entry.AbsolutePosition.y-listFrame.AbsolutePosition.y)
2650 parentHighlight.Size = UDim2.new(0,size.x-4,0,entry.AbsoluteSize.y)
2651 end
2652 end
2653 end
2654
2655 dragGhost.Position = UDim2.new(0,dragPos.x+ghostOffset.x,0,dragPos.y+ghostOffset.y)
2656 elseif (clickPos-dragPos).magnitude > 8 then
2657 dragged = true
2658 SetZIndex(dragGhost,9)
2659 dragGhost.IndentFrame.Transparency = 0.25
2660 dragGhost.IndentFrame.EntryText.TextColor3 = GuiColor.TextSelected
2661 dragGhost.Position = UDim2.new(0,dragPos.x+ghostOffset.x,0,dragPos.y+ghostOffset.y)
2662 dragGhost.Parent = GetScreen(listFrame)
2663 parentHighlight.Parent = listFrame
2664 end
2665 end)
2666
2667 function cancelReparentDrag()
2668 mouseDrag.Parent = nil
2669 conDrag:disconnect()
2670 conUp:disconnect()
2671 conUp2:disconnect()
2672 dragGhost:Destroy()
2673 parentHighlight:Destroy()
2674 function cancelReparentDrag()end
2675 end
2676
2677 local wasSelected = Selection.Selected[object]
2678 if not wasSelected and Option.Selectable then
2679 Selection:Set({object})
2680 end
2681
2682 conUp = mouseDrag.MouseButton1Up:connect(function()
2683 cancelReparentDrag()
2684 if dragged then
2685 if parentIndex then
2686 local parentNode = TreeList[parentIndex + scrollBar.ScrollIndex]
2687 if parentNode then
2688 parentNode.Expanded = true
2689
2690 local parentObj = parentNode.Object
2691 local function parent(a,b)
2692 a.Parent = b
2693 end
2694 if Option.Selectable then
2695 local list = Selection.List
2696 for i = 1,#list do
2697 pcall(parent,list[i],parentObj)
2698 end
2699 else
2700 pcall(parent,object,parentObj)
2701 end
2702 end
2703 end
2704 else
2705 -- do selection click
2706 if wasSelected and Option.Selectable then
2707 Selection:Set({})
2708 end
2709 end
2710 end)
2711 conUp2 = mouseDrag.MouseButton2Down:connect(function()
2712 cancelReparentDrag()
2713 end)
2714
2715 mouseDrag.Parent = GetScreen(listFrame)
2716 end
2717
2718 local entryTemplate = Create('ImageButton',{
2719 Name = "Entry";
2720 Transparency = 1;
2721 AutoButtonColor = false;
2722 Position = UDim2.new(0,0,0,0);
2723 Size = UDim2.new(1,0,0,ENTRY_SIZE);
2724 Create('Frame',{
2725 Name = "IndentFrame";
2726 BackgroundTransparency = 1;
2727 BackgroundColor3 = GuiColor.Selected;
2728 BorderColor3 = GuiColor.BorderSelected;
2729 Position = UDim2.new(0,0,0,0);
2730 Size = UDim2.new(1,0,1,0);
2731 Create(Icon('ImageButton',0),{
2732 Name = "Expand";
2733 AutoButtonColor = false;
2734 Position = UDim2.new(0,-GUI_SIZE,0.5,-GUI_SIZE/2);
2735 Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
2736 });
2737 Create(Icon(nil,0),{
2738 Name = "ExplorerIcon";
2739 Position = UDim2.new(0,2+ENTRY_PADDING,0.5,-GUI_SIZE/2);
2740 Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
2741 });
2742 Create('TextLabel',{
2743 Name = "EntryText";
2744 BackgroundTransparency = 1;
2745 TextColor3 = GuiColor.Text;
2746 TextXAlignment = 'Left';
2747 TextYAlignment = 'Center';
2748 Font = FONT;
2749 FontSize = FONT_SIZE;
2750 Text = "";
2751 Position = UDim2.new(0,2+ENTRY_SIZE+4,0,0);
2752 Size = UDim2.new(1,-2,1,0);
2753 });
2754 });
2755 })
2756
2757 function scrollBar.UpdateCallback(self)
2758 for i = 1,self.VisibleSpace do
2759 local node = TreeList[i + self.ScrollIndex]
2760 if node then
2761 local entry = listEntries[i]
2762 if not entry then
2763 entry = Create(entryTemplate:Clone(),{
2764 Position = UDim2.new(0,2,0,ENTRY_BOUND*(i-1)+2);
2765 Size = UDim2.new(0,nodeWidth,0,ENTRY_SIZE);
2766 ZIndex = listFrame.ZIndex;
2767 })
2768 listEntries[i] = entry
2769
2770 local expand = entry.IndentFrame.Expand
2771 expand.MouseEnter:connect(function()
2772 local node = TreeList[i + self.ScrollIndex]
2773 if #node > 0 then
2774 if node.Expanded then
2775 Icon(expand,NODE_EXPANDED_OVER)
2776 else
2777 Icon(expand,NODE_COLLAPSED_OVER)
2778 end
2779 end
2780 end)
2781 expand.MouseLeave:connect(function()
2782 local node = TreeList[i + self.ScrollIndex]
2783 if #node > 0 then
2784 if node.Expanded then
2785 Icon(expand,NODE_EXPANDED)
2786 else
2787 Icon(expand,NODE_COLLAPSED)
2788 end
2789 end
2790 end)
2791 expand.MouseButton1Down:connect(function()
2792 local node = TreeList[i + self.ScrollIndex]
2793 if #node > 0 then
2794 node.Expanded = not node.Expanded
2795 -- use raw update so the list updates instantly
2796 rawUpdateList()
2797 end
2798 end)
2799
2800 entry.MouseButton1Down:connect(function(x,y)
2801 local node = TreeList[i + self.ScrollIndex]
2802 DestroyRightClick()
2803 if GetAwaitRemote:Invoke() then
2804 bindSetAwaiting:Fire(node.Object)
2805 return
2806 end
2807
2808 if not HoldingShift then
2809 lastSelectedNode = i + self.ScrollIndex
2810 end
2811
2812 if HoldingShift and not filteringWorkspace() then
2813 if lastSelectedNode then
2814 if i + self.ScrollIndex - lastSelectedNode > 0 then
2815 Selection:StopUpdates()
2816 for i2 = 1, i + self.ScrollIndex - lastSelectedNode do
2817 local newNode = TreeList[lastSelectedNode + i2]
2818 if newNode then
2819 Selection:Add(newNode.Object)
2820 end
2821 end
2822 Selection:ResumeUpdates()
2823 else
2824 Selection:StopUpdates()
2825 for i2 = i + self.ScrollIndex - lastSelectedNode, 1 do
2826 local newNode = TreeList[lastSelectedNode + i2]
2827 if newNode then
2828 Selection:Add(newNode.Object)
2829 end
2830 end
2831 Selection:ResumeUpdates()
2832 end
2833 end
2834 return
2835 end
2836
2837 if HoldingCtrl then
2838 if Selection.Selected[node.Object] then
2839 Selection:Remove(node.Object)
2840 else
2841 Selection:Add(node.Object)
2842 end
2843 return
2844 end
2845 if Option.Modifiable then
2846 local pos = Vector2.new(x,y)
2847 dragReparent(node.Object,entry:Clone(),pos,entry.AbsolutePosition-pos)
2848 elseif Option.Selectable then
2849 if Selection.Selected[node.Object] then
2850 Selection:Set({})
2851 else
2852 Selection:Set({node.Object})
2853 end
2854 dragSelect(i+self.ScrollIndex,true,'MouseButton1Up')
2855 end
2856 end)
2857
2858 entry.MouseButton2Down:connect(function()
2859 if not Option.Selectable then return end
2860
2861 DestroyRightClick()
2862
2863 curSelect = entry
2864
2865 local node = TreeList[i + self.ScrollIndex]
2866
2867 if GetAwaitRemote:Invoke() then
2868 bindSetAwaiting:Fire(node.Object)
2869 return
2870 end
2871
2872 if not Selection.Selected[node.Object] then
2873 Selection:Set({node.Object})
2874 end
2875 end)
2876
2877
2878 entry.MouseButton2Up:connect(function()
2879 if not Option.Selectable then return end
2880
2881 local node = TreeList[i + self.ScrollIndex]
2882
2883 if checkMouseInGui(curSelect) then
2884 rightClickMenu(node.Object)
2885 end
2886 end)
2887
2888 entry.Parent = listFrame
2889 end
2890
2891 entry.Visible = true
2892
2893 local object = node.Object
2894
2895 -- update expand icon
2896 if #node == 0 then
2897 entry.IndentFrame.Expand.Visible = false
2898 elseif node.Expanded then
2899 Icon(entry.IndentFrame.Expand,NODE_EXPANDED)
2900 entry.IndentFrame.Expand.Visible = true
2901 else
2902 Icon(entry.IndentFrame.Expand,NODE_COLLAPSED)
2903 entry.IndentFrame.Expand.Visible = true
2904 end
2905
2906 -- update explorer icon
2907 Icon(entry.IndentFrame.ExplorerIcon,ExplorerIndex[object.ClassName] or 0)
2908
2909 -- update indentation
2910 local w = (node.Depth)*(2+ENTRY_PADDING+GUI_SIZE)
2911 entry.IndentFrame.Position = UDim2.new(0,w,0,0)
2912 entry.IndentFrame.Size = UDim2.new(1,-w,1,0)
2913
2914 -- update name change detection
2915 if nameConnLookup[entry] then
2916 nameConnLookup[entry]:disconnect()
2917 end
2918 local text = entry.IndentFrame.EntryText
2919 text.Text = object.Name
2920 nameConnLookup[entry] = node.Object.Changed:connect(function(p)
2921 if p == 'Name' then
2922 text.Text = object.Name
2923 end
2924 end)
2925
2926 -- update selection
2927 entry.IndentFrame.Transparency = node.Selected and 0 or 1
2928 text.TextColor3 = GuiColor[node.Selected and 'TextSelected' or 'Text']
2929
2930 entry.Size = UDim2.new(0,nodeWidth,0,ENTRY_SIZE)
2931 elseif listEntries[i] then
2932 listEntries[i].Visible = false
2933 end
2934 end
2935 for i = self.VisibleSpace+1,self.TotalSpace do
2936 local entry = listEntries[i]
2937 if entry then
2938 listEntries[i] = nil
2939 entry:Destroy()
2940 end
2941 end
2942 end
2943
2944 function scrollBarH.UpdateCallback(self)
2945 for i = 1,scrollBar.VisibleSpace do
2946 local node = TreeList[i + scrollBar.ScrollIndex]
2947 if node then
2948 local entry = listEntries[i]
2949 if entry then
2950 entry.Position = UDim2.new(0,2 - scrollBarH.ScrollIndex,0,ENTRY_BOUND*(i-1)+2)
2951 end
2952 end
2953 end
2954 end
2955
2956 Connect(listFrame.Changed,function(p)
2957 if p == 'AbsoluteSize' then
2958 rawUpdateSize()
2959 end
2960 end)
2961
2962 local wheelAmount = 6
2963 explorerPanel.MouseWheelForward:connect(function()
2964 if scrollBar.VisibleSpace - 1 > wheelAmount then
2965 scrollBar:ScrollTo(scrollBar.ScrollIndex - wheelAmount)
2966 else
2967 scrollBar:ScrollTo(scrollBar.ScrollIndex - scrollBar.VisibleSpace)
2968 end
2969 end)
2970 explorerPanel.MouseWheelBackward:connect(function()
2971 if scrollBar.VisibleSpace - 1 > wheelAmount then
2972 scrollBar:ScrollTo(scrollBar.ScrollIndex + wheelAmount)
2973 else
2974 scrollBar:ScrollTo(scrollBar.ScrollIndex + scrollBar.VisibleSpace)
2975 end
2976 end)
2977end
2978
2979----------------------------------------------------------------
2980----------------------------------------------------------------
2981----------------------------------------------------------------
2982----------------------------------------------------------------
2983---- Object detection
2984
2985-- Inserts `v` into `t` at `i`. Also sets `Index` field in `v`.
2986local function insert(t,i,v)
2987 for n = #t,i,-1 do
2988 local v = t[n]
2989 v.Index = n+1
2990 t[n+1] = v
2991 end
2992 v.Index = i
2993 t[i] = v
2994end
2995
2996-- Removes `i` from `t`. Also sets `Index` field in removed value.
2997local function remove(t,i)
2998 local v = t[i]
2999 for n = i+1,#t do
3000 local v = t[n]
3001 v.Index = n-1
3002 t[n-1] = v
3003 end
3004 t[#t] = nil
3005 v.Index = 0
3006 return v
3007end
3008
3009-- Returns how deep `o` is in the tree.
3010local function depth(o)
3011 local d = -1
3012 while o do
3013 o = o.Parent
3014 d = d + 1
3015 end
3016 return d
3017end
3018
3019
3020local connLookup = {}
3021
3022-- Returns whether a node would be present in the tree list
3023local function nodeIsVisible(node)
3024 local visible = true
3025 node = node.Parent
3026 while node and visible do
3027 visible = visible and node.Expanded
3028 node = node.Parent
3029 end
3030 return visible
3031end
3032
3033-- Removes an object's tree node. Called when the object stops existing in the
3034-- game tree.
3035local function removeObject(object)
3036 local objectNode = NodeLookup[object]
3037 if not objectNode then
3038 return
3039 end
3040
3041 local visible = nodeIsVisible(objectNode)
3042
3043 Selection:Remove(object,true)
3044
3045 local parent = objectNode.Parent
3046 remove(parent,objectNode.Index)
3047 NodeLookup[object] = nil
3048 connLookup[object]:disconnect()
3049 connLookup[object] = nil
3050
3051 if visible then
3052 updateList()
3053 elseif nodeIsVisible(parent) then
3054 updateScroll()
3055 end
3056end
3057
3058-- Moves a tree node to a new parent. Called when an existing object's parent
3059-- changes.
3060local function moveObject(object,parent)
3061 local objectNode = NodeLookup[object]
3062 if not objectNode then
3063 return
3064 end
3065
3066 local parentNode = NodeLookup[parent]
3067 if not parentNode then
3068 return
3069 end
3070
3071 local visible = nodeIsVisible(objectNode)
3072
3073 remove(objectNode.Parent,objectNode.Index)
3074 objectNode.Parent = parentNode
3075
3076 objectNode.Depth = depth(object)
3077 local function r(node,d)
3078 for i = 1,#node do
3079 node[i].Depth = d
3080 r(node[i],d+1)
3081 end
3082 end
3083 r(objectNode,objectNode.Depth+1)
3084
3085 insert(parentNode,#parentNode+1,objectNode)
3086
3087 if visible or nodeIsVisible(objectNode) then
3088 updateList()
3089 elseif nodeIsVisible(objectNode.Parent) then
3090 updateScroll()
3091 end
3092end
3093
3094-- ScriptContext['/Libraries/LibraryRegistration/LibraryRegistration']
3095-- This RobloxLocked object lets me index its properties for some reason
3096
3097local function check(object)
3098 return object.AncestryChanged
3099end
3100
3101-- Creates a new tree node from an object. Called when an object starts
3102-- existing in the game tree.
3103local function addObject(object,noupdate)
3104 if script then
3105 -- protect against naughty RobloxLocked objects
3106 local s = pcall(check,object)
3107 if not s then
3108 return
3109 end
3110 end
3111
3112 local parentNode = NodeLookup[object.Parent]
3113 if not parentNode then
3114 return
3115 end
3116
3117 local objectNode = {
3118 Object = object;
3119 Parent = parentNode;
3120 Index = 0;
3121 Expanded = false;
3122 Selected = false;
3123 Depth = depth(object);
3124 }
3125
3126 connLookup[object] = Connect(object.AncestryChanged,function(c,p)
3127 if c == object then
3128 if p == nil then
3129 removeObject(c)
3130 else
3131 moveObject(c,p)
3132 end
3133 end
3134 end)
3135
3136 NodeLookup[object] = objectNode
3137 insert(parentNode,#parentNode+1,objectNode)
3138
3139 if not noupdate then
3140 if nodeIsVisible(objectNode) then
3141 updateList()
3142 elseif nodeIsVisible(objectNode.Parent) then
3143 updateScroll()
3144 end
3145 end
3146end
3147
3148do
3149 NodeLookup[workspace.Parent] = {
3150 Object = workspace.Parent;
3151 Parent = nil;
3152 Index = 0;
3153 Expanded = true;
3154 }
3155
3156 Connect(game.DescendantAdded,addObject)
3157 Connect(game.DescendantRemoving,removeObject)
3158
3159 local function get(o)
3160 return o:GetChildren()
3161 end
3162
3163 local function r(o)
3164 local s,children = pcall(get,o)
3165 if s then
3166 for i = 1,#children do
3167 addObject(children[i],true)
3168 r(children[i])
3169 end
3170 end
3171 end
3172
3173 r(workspace.Parent)
3174
3175 scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
3176 updateList()
3177end
3178
3179----------------------------------------------------------------
3180----------------------------------------------------------------
3181----------------------------------------------------------------
3182----------------------------------------------------------------
3183---- Actions
3184
3185local actionButtons do
3186 actionButtons = {}
3187
3188 local totalActions = (4) + 1
3189 local currentActions = totalActions
3190 local function makeButton(icon,over,name)
3191 local button = Create(Icon('ImageButton',icon),{
3192 Name = name .. "Button";
3193 Visible = Option.Modifiable and Option.Selectable;
3194 Position = UDim2.new(1,-(GUI_SIZE+2)*currentActions+2,0.5,-GUI_SIZE/2);
3195 Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
3196 Parent = headerFrame;
3197 })
3198
3199 local tipText = Create('TextLabel',{
3200 Name = name .. "Text";
3201 Text = name;
3202 Visible = false;
3203 BackgroundTransparency = 1;
3204 TextXAlignment = 'Right';
3205 Font = FONT;
3206 FontSize = FONT_SIZE;
3207 Position = UDim2.new(0,0,0,0);
3208 Size = UDim2.new(1,-(GUI_SIZE+2)*totalActions,1,0);
3209 Parent = headerFrame;
3210 })
3211
3212
3213 button.MouseEnter:connect(function()
3214 Icon(button,over)
3215 tipText.Visible = true
3216 end)
3217 button.MouseLeave:connect(function()
3218 Icon(button,icon)
3219 tipText.Visible = false
3220 end)
3221
3222 currentActions = currentActions - 1
3223 actionButtons[#actionButtons+1] = button
3224 return button
3225 end
3226
3227 local clipboard = {}
3228 local function delete(o)
3229 o.Parent = nil
3230 end
3231
3232 --[[
3233 -- CUT
3234 makeButton(ACTION_CUT,ACTION_CUT_OVER,"Cut").MouseButton1Click:connect(function()
3235 if not Option.Modifiable then return end
3236 clipboard = {}
3237 local list = Selection.List
3238 local cut = {}
3239 for i = 1,#list do
3240 local obj = list[i]:Clone()
3241 if obj then
3242 table.insert(clipboard,obj)
3243 table.insert(cut,list[i])
3244 end
3245 end
3246 for i = 1,#cut do
3247 pcall(delete,cut[i])
3248 end
3249 end)
3250
3251 -- COPY
3252 makeButton(ACTION_COPY,ACTION_COPY_OVER,"Copy").MouseButton1Click:connect(function()
3253 if not Option.Modifiable then return end
3254 clipboard = {}
3255 local list = Selection.List
3256 for i = 1,#list do
3257 table.insert(clipboard,list[i]:Clone())
3258 end
3259 end)
3260
3261 -- PASTE
3262 makeButton(ACTION_PASTE,ACTION_PASTE_OVER,"Paste").MouseButton1Click:connect(function()
3263 if not Option.Modifiable then return end
3264 local parent = Selection.List[1] or workspace
3265 for i = 1,#clipboard do
3266 clipboard[i]:Clone().Parent = parent
3267 end
3268 end)
3269
3270 -- DELETE
3271 makeButton(ACTION_DELETE,ACTION_DELETE_OVER,"Delete").MouseButton1Click:connect(function()
3272 if not Option.Modifiable then return end
3273 local list = Selection:Get()
3274 for i = 1,#list do
3275 pcall(delete,list[i])
3276 end
3277 Selection:Set({})
3278 end)
3279 ]]--
3280
3281 -- SORT
3282 -- local actionSort = makeButton(ACTION_SORT,ACTION_SORT_OVER,"Sort")
3283end
3284
3285----------------------------------------------------------------
3286----------------------------------------------------------------
3287----------------------------------------------------------------
3288----------------------------------------------------------------
3289---- Option Bindables
3290
3291do
3292 local optionCallback = {
3293 Modifiable = function(value)
3294 for i = 1,#actionButtons do
3295 actionButtons[i].Visible = value and Option.Selectable
3296 end
3297 cancelReparentDrag()
3298 end;
3299 Selectable = function(value)
3300 for i = 1,#actionButtons do
3301 actionButtons[i].Visible = value and Option.Modifiable
3302 end
3303 cancelSelectDrag()
3304 Selection:Set({})
3305 end;
3306 }
3307
3308 local bindSetOption = explorerPanel:FindFirstChild("SetOption")
3309 if not bindSetOption then
3310 bindSetOption = Create('BindableFunction',{Name = "SetOption"})
3311 bindSetOption.Parent = explorerPanel
3312 end
3313
3314 bindSetOption.OnInvoke = function(optionName,value)
3315 if optionCallback[optionName] then
3316 Option[optionName] = value
3317 optionCallback[optionName](value)
3318 end
3319 end
3320
3321 local bindGetOption = explorerPanel:FindFirstChild("GetOption")
3322 if not bindGetOption then
3323 bindGetOption = Create('BindableFunction',{Name = "GetOption"})
3324 bindGetOption.Parent = explorerPanel
3325 end
3326
3327 bindGetOption.OnInvoke = function(optionName)
3328 if optionName then
3329 return Option[optionName]
3330 else
3331 local options = {}
3332 for k,v in pairs(Option) do
3333 options[k] = v
3334 end
3335 return options
3336 end
3337 end
3338end
3339
3340function SelectionVar()
3341 return Selection
3342end
3343
3344Input.InputBegan:connect(function(key)
3345 if key.KeyCode == Enum.KeyCode.LeftControl then
3346 HoldingCtrl = true
3347 end
3348 if key.KeyCode == Enum.KeyCode.LeftShift then
3349 HoldingShift = true
3350 end
3351end)
3352
3353Input.InputEnded:connect(function(key)
3354 if key.KeyCode == Enum.KeyCode.LeftControl then
3355 HoldingCtrl = false
3356 end
3357 if key.KeyCode == Enum.KeyCode.LeftShift then
3358 HoldingShift = false
3359 end
3360end)
3361
3362while RbxApi == nil do
3363 RbxApi = GetApiRemote:Invoke()
3364 wait()
3365end
3366
3367explorerFilter.Changed:connect(function(prop)
3368 if prop == "Text" then
3369 rawUpdateList()
3370 end
3371end)
3372
3373CurrentInsertObjectWindow = CreateInsertObjectMenu(
3374 GetClasses(),
3375 "",
3376 false,
3377 function(option)
3378 CurrentInsertObjectWindow.Visible = false
3379 local list = SelectionVar():Get()
3380 for i = 1,#list do
3381 pcall(function() Instance.new(option,list[i]) end)
3382 end
3383 DestroyRightClick()
3384 end
3385)
3386end)
3387spawn(function()
3388--[[
3389
3390Change log:
3391
339209/18
3393 Fixed checkbox mouseover sprite
3394 Encapsulated checkbox creation into separate method
3395 Fixed another checkbox issue
3396
339709/15
3398 Invalid input is ignored instead of setting to default of that data type
3399 Consolidated control methods and simplified them
3400 All input goes through ToValue method
3401 Fixed position of BrickColor palette
3402 Made DropDown appear above row if it would otherwise exceed the page height
3403 Cleaned up stylesheets
3404
340509/14
3406 Made properties window scroll when mouse wheel scrolled
3407 Object/Instance and Color3 data types handled properly
3408 Multiple BrickColor controls interfering with each other fixed
3409 Added support for Content data type
3410
3411--]]
3412
3413wait(0.2)
3414
3415local print = function(s)
3416 print(tostring(s))
3417end
3418
3419-- Services
3420local Teams = game:GetService("Teams")
3421local Workspace = game:GetService("Workspace")
3422local Debris = game:GetService("Debris")
3423local ContentProvider = game:GetService("ContentProvider")
3424local Players = game:GetService("Players")
3425local ReplicatedStorage = game:GetService("ReplicatedStorage")
3426
3427-- Functions
3428function httpGet(url)
3429 return game:HttpGet(url,true)
3430end
3431
3432-- RbxApi Stuff
3433
3434local apiUrl = "http://anaminus.github.io/rbx/json/api/latest.json"
3435local maxChunkSize = 100 * 1000
3436local ApiJson
3437
3438function splitStringIntoChunks(jsonStr)
3439 -- Splits up a string into a table with a given size
3440 local t = {}
3441 for i = 1, math.ceil(string.len(jsonStr)/maxChunkSize) do
3442 local str = jsonStr:sub((i-1)*maxChunkSize+1, i*maxChunkSize)
3443 table.insert(t, str)
3444 end
3445 return t
3446end
3447
3448local jsonToParse = httpGet(apiUrl)
3449local apiChunks = splitStringIntoChunks(jsonToParse)
3450
3451function getRbxApi()
3452--[[
3453 Api.Classes
3454 Api.Enums
3455 Api.GetProperties(className)
3456 Api.IsEnum(valueType)
3457--]]
3458
3459-- Services
3460local HttpService = game:GetService("HttpService")
3461local ServerStorage = game:GetService("ServerStorage")
3462local ReplicatedStorage = game:GetService("ReplicatedStorage")
3463
3464-- Remotes
3465--local Remotes = ReplicatedStorage:WaitForChild("OnlineStudio"):WaitForChild("Remotes")
3466--local GetApiJsonFunction = Remotes:WaitForChild("GetApiJson")
3467
3468-- Functions
3469local JsonDecode = function(s) return HttpService:JSONDecode(s) end
3470
3471local function GetApiRemoteFunction(index)
3472 if (apiChunks[index]) then
3473 return apiChunks[index], #apiChunks
3474 else
3475 print("Bad index for GetApiJson")
3476 return nil
3477 end
3478end
3479
3480local function getApiJson()
3481 local apiTable = {}
3482 local firstPage, pageCount = GetApiRemoteFunction(1)
3483 table.insert(apiTable, firstPage)
3484 for i = 2, pageCount do
3485 --print("Fetching API page # " .. tostring(i))
3486 local result = GetApiRemoteFunction(i)
3487 table.insert(apiTable, result)
3488 end
3489 return table.concat(apiTable)
3490end
3491
3492local json = getApiJson()
3493local apiDump = JsonDecode(json)
3494
3495local Classes = {}
3496local Enums = {}
3497
3498local function sortAlphabetic(t, property)
3499 table.sort(t,
3500 function(x,y) return x[property] < y[property]
3501 end)
3502end
3503
3504local function isEnum(name)
3505 return Enums[name] ~= nil
3506end
3507
3508local function getProperties(className)
3509 local class = Classes[className]
3510 local properties = {}
3511
3512 if not class then return properties end
3513
3514 while class do
3515 for _,property in pairs(class.Properties) do
3516 table.insert(properties, property)
3517 end
3518 class = Classes[class.Superclass]
3519 end
3520
3521 sortAlphabetic(properties, "Name")
3522
3523 return properties
3524end
3525
3526for _,item in pairs(apiDump) do
3527 local itemType = item.type
3528-- Classes --
3529 if (itemType == 'Class') then
3530 Classes[item.Name] = item
3531 item.Properties = {}
3532 item.Functions = {}
3533 item.YieldFunctions = {}
3534 item.Events = {}
3535 item.Callbacks = {}
3536-- Members --
3537 elseif (itemType == 'Property') then
3538 table.insert(Classes[item.Class].Properties, item)
3539 elseif (itemType == 'Function') then
3540 table.insert(Classes[item.Class].Functions, item)
3541 elseif (itemType == 'YieldFunction') then
3542 table.insert(Classes[item.Class].YieldFunctions, item)
3543 elseif (itemType == 'Event') then
3544 table.insert(Classes[item.Class].Events, item)
3545 elseif (itemType == 'Callback') then
3546 table.insert(Classes[item.Class].Callbacks, item)
3547-- Enums --
3548 elseif (itemType == 'Enum') then
3549 Enums[item.Name] = item
3550 item.EnumItems = {}
3551 elseif (itemType == 'EnumItem') then
3552 Enums[item.Enum].EnumItems[item.Name] = item
3553 end
3554end
3555
3556return {
3557 Classes = Classes;
3558 Enums = Enums;
3559 GetProperties = getProperties;
3560 IsEnum = isEnum;
3561}
3562end
3563
3564-- Modules
3565local Permissions = {CanEdit = true}
3566local RbxApi = getRbxApi()
3567
3568--[[
3569 RbxApi.Classes
3570 RbxApi.Enums
3571 RbxApi.GetProperties(className)
3572 RbxApi.IsEnum(valueType)
3573--]]
3574
3575-- Styles
3576
3577local function CreateColor3(r, g, b) return Color3.new(r/255,g/255,b/255) end
3578
3579local Styles = {
3580 Font = Enum.Font.Arial;
3581 Margin = 5;
3582 Black = CreateColor3(0,0,0);
3583 White = CreateColor3(255,255,255);
3584}
3585
3586local Row = {
3587 Font = Styles.Font;
3588 FontSize = Enum.FontSize.Size14;
3589 TextXAlignment = Enum.TextXAlignment.Left;
3590 TextColor = Styles.Black;
3591 TextColorOver = Styles.White;
3592 TextLockedColor = CreateColor3(120,120,120);
3593 Height = 24;
3594 BorderColor = CreateColor3(216,216,216);
3595 BackgroundColor = Styles.White;
3596 BackgroundColorAlternate = CreateColor3(246,246,246);
3597 BackgroundColorMouseover = CreateColor3(211,224,244);
3598 TitleMarginLeft = 15;
3599}
3600
3601local DropDown = {
3602 Font = Styles.Font;
3603 FontSize = Enum.FontSize.Size14;
3604 TextColor = CreateColor3(0,0,0);
3605 TextColorOver = Styles.White;
3606 TextXAlignment = Enum.TextXAlignment.Left;
3607 Height = 16;
3608 BackColor = Styles.White;
3609 BackColorOver = CreateColor3(86,125,188);
3610 BorderColor = CreateColor3(216,216,216);
3611 BorderSizePixel = 2;
3612 ArrowColor = CreateColor3(160,160,160);
3613 ArrowColorOver = Styles.Black;
3614}
3615
3616local BrickColors = {
3617 BoxSize = 13;
3618 BorderSizePixel = 1;
3619 BorderColor = CreateColor3(160,160,160);
3620 FrameColor = CreateColor3(160,160,160);
3621 Size = 20;
3622 Padding = 4;
3623 ColorsPerRow = 8;
3624 OuterBorder = 1;
3625 OuterBorderColor = Styles.Black;
3626}
3627
3628wait(1)
3629
3630local Gui = script.Parent
3631local PropertiesFrame = Gui:WaitForChild("PropertiesFrame")
3632local ExplorerFrame = Gui:WaitForChild("ExplorerPanel")
3633
3634local bindGetSelection = ExplorerFrame.GetSelection
3635local bindSelectionChanged = ExplorerFrame.SelectionChanged
3636local bindGetApi = PropertiesFrame.GetApi
3637local bindGetAwait = PropertiesFrame.GetAwaiting
3638local bindSetAwait = PropertiesFrame.SetAwaiting
3639
3640local ContentUrl = ContentProvider.BaseUrl .. "asset/?id="
3641
3642local SettingsRemote = Gui:WaitForChild("SettingsPanel"):WaitForChild("GetSetting")
3643
3644local propertiesSearch = PropertiesFrame.Header.TextBox
3645
3646local AwaitingObjectValue = false
3647local AwaitingObjectObj
3648local AwaitingObjectProp
3649
3650function searchingProperties()
3651 if propertiesSearch.Text ~= "" and propertiesSearch.Text ~= "Search Properties" then
3652 return true
3653 end
3654 return false
3655end
3656
3657local function GetSelection()
3658 local selection = bindGetSelection:Invoke()
3659 if #selection == 0 then
3660 return nil
3661 else
3662 return selection
3663 end
3664end
3665
3666-- Number
3667
3668local function Round(number, decimalPlaces)
3669 return tonumber(string.format("%." .. (decimalPlaces or 0) .. "f", number))
3670end
3671
3672-- Strings
3673
3674local function Split(str, delimiter)
3675 local start = 1
3676 local t = {}
3677 while true do
3678 local pos = string.find (str, delimiter, start, true)
3679 if not pos then
3680 break
3681 end
3682 table.insert (t, string.sub (str, start, pos - 1))
3683 start = pos + string.len (delimiter)
3684 end
3685 table.insert (t, string.sub (str, start))
3686 return t
3687end
3688
3689-- Data Type Handling
3690
3691local function ToString(value, type)
3692 if type == "float" then
3693 return tostring(Round(value,2))
3694 elseif type == "Content" then
3695 if string.find(value,"/asset") then
3696 local match = string.find(value, "=") + 1
3697 local id = string.sub(value, match)
3698 return id
3699 else
3700 return tostring(value)
3701 end
3702 elseif type == "Vector2" then
3703 local x = value.x
3704 local y = value.y
3705 return string.format("%g, %g", x,y)
3706 elseif type == "Vector3" then
3707 local x = value.x
3708 local y = value.y
3709 local z = value.z
3710 return string.format("%g, %g, %g", x,y,z)
3711 elseif type == "Color3" then
3712 local r = value.r
3713 local g = value.g
3714 local b = value.b
3715 return string.format("%d, %d, %d", r*255,g*255,b*255)
3716 elseif type == "UDim2" then
3717 local xScale = value.X.Scale
3718 local xOffset = value.X.Offset
3719 local yScale = value.Y.Scale
3720 local yOffset = value.Y.Offset
3721 return string.format("{%d, %d}, {%d, %d}", xScale, xOffset, yScale, yOffset)
3722 else
3723 return tostring(value)
3724 end
3725end
3726
3727local function ToValue(value,type)
3728 if type == "Vector2" then
3729 local list = Split(value,",")
3730 if #list < 2 then return nil end
3731 local x = tonumber(list[1]) or 0
3732 local y = tonumber(list[2]) or 0
3733 return Vector2.new(x,y)
3734 elseif type == "Vector3" then
3735 local list = Split(value,",")
3736 if #list < 3 then return nil end
3737 local x = tonumber(list[1]) or 0
3738 local y = tonumber(list[2]) or 0
3739 local z = tonumber(list[3]) or 0
3740 return Vector3.new(x,y,z)
3741 elseif type == "Color3" then
3742 local list = Split(value,",")
3743 if #list < 3 then return nil end
3744 local r = tonumber(list[1]) or 0
3745 local g = tonumber(list[2]) or 0
3746 local b = tonumber(list[3]) or 0
3747 return Color3.new(r/255,g/255, b/255)
3748 elseif type == "UDim2" then
3749 local list = Split(string.gsub(string.gsub(value, "{", ""),"}",""),",")
3750 if #list < 4 then return nil end
3751 local xScale = tonumber(list[1]) or 0
3752 local xOffset = tonumber(list[2]) or 0
3753 local yScale = tonumber(list[3]) or 0
3754 local yOffset = tonumber(list[4]) or 0
3755 return UDim2.new(xScale, xOffset, yScale, yOffset)
3756 elseif type == "Content" then
3757 if tonumber(value) ~= nil then
3758 value = ContentUrl .. value
3759 end
3760 return value
3761 elseif type == "float" or type == "int" or type == "double" then
3762 return tonumber(value)
3763 elseif type == "string" then
3764 return value
3765 elseif type == "NumberRange" then
3766 local list = Split(value,",")
3767 if #list == 1 then
3768 if tonumber(list[1]) == nil then return nil end
3769 local newVal = tonumber(list[1]) or 0
3770 return NumberRange.new(newVal)
3771 end
3772 if #list < 2 then return nil end
3773 local x = tonumber(list[1]) or 0
3774 local y = tonumber(list[2]) or 0
3775 return NumberRange.new(x,y)
3776 else
3777 return nil
3778 end
3779end
3780
3781
3782-- Tables
3783
3784local function CopyTable(T)
3785 local t2 = {}
3786 for k,v in pairs(T) do
3787 t2[k] = v
3788 end
3789 return t2
3790end
3791
3792local function SortTable(T)
3793 table.sort(T,
3794 function(x,y) return x.Name < y.Name
3795 end)
3796end
3797
3798-- Spritesheet
3799local Sprite = {
3800 Width = 13;
3801 Height = 13;
3802}
3803
3804local Spritesheet = {
3805 Image = "http://www.roblox.com/asset/?id=128896947";
3806 Height = 256;
3807 Width = 256;
3808}
3809
3810local Images = {
3811 "unchecked",
3812 "checked",
3813 "unchecked_over",
3814 "checked_over",
3815 "unchecked_disabled",
3816 "checked_disabled"
3817}
3818
3819local function SpritePosition(spriteName)
3820 local x = 0
3821 local y = 0
3822 for i,v in pairs(Images) do
3823 if (v == spriteName) then
3824 return {x, y}
3825 end
3826 x = x + Sprite.Height
3827 if (x + Sprite.Width) > Spritesheet.Width then
3828 x = 0
3829 y = y + Sprite.Height
3830 end
3831 end
3832end
3833
3834local function GetCheckboxImageName(checked, readOnly, mouseover)
3835 if checked then
3836 if readOnly then
3837 return "checked_disabled"
3838 elseif mouseover then
3839 return "checked_over"
3840 else
3841 return "checked"
3842 end
3843 else
3844 if readOnly then
3845 return "unchecked_disabled"
3846 elseif mouseover then
3847 return "unchecked_over"
3848 else
3849 return "unchecked"
3850 end
3851 end
3852end
3853
3854local MAP_ID = 418720155
3855
3856-- Gui Controls --
3857
3858---- IconMap ----
3859-- Image size: 256px x 256px
3860-- Icon size: 16px x 16px
3861-- Padding between each icon: 2px
3862-- Padding around image edge: 1px
3863-- Total icons: 14 x 14 (196)
3864local Icon do
3865 local iconMap = 'http://www.roblox.com/asset/?id=' .. MAP_ID
3866 game:GetService('ContentProvider'):Preload(iconMap)
3867 local iconDehash do
3868 -- 14 x 14, 0-based input, 0-based output
3869 local f=math.floor
3870 function iconDehash(h)
3871 return f(h/14%14),f(h%14)
3872 end
3873 end
3874
3875 function Icon(IconFrame,index)
3876 local row,col = iconDehash(index)
3877 local mapSize = Vector2.new(256,256)
3878 local pad,border = 2,1
3879 local iconSize = 16
3880
3881 local class = 'Frame'
3882 if type(IconFrame) == 'string' then
3883 class = IconFrame
3884 IconFrame = nil
3885 end
3886
3887 if not IconFrame then
3888 IconFrame = Create(class,{
3889 Name = "Icon";
3890 BackgroundTransparency = 1;
3891 ClipsDescendants = true;
3892 Create('ImageLabel',{
3893 Name = "IconMap";
3894 Active = false;
3895 BackgroundTransparency = 1;
3896 Image = iconMap;
3897 Size = UDim2.new(mapSize.x/iconSize,0,mapSize.y/iconSize,0);
3898 });
3899 })
3900 end
3901
3902 IconFrame.IconMap.Position = UDim2.new(-col - (pad*(col+1) + border)/iconSize,0,-row - (pad*(row+1) + border)/iconSize,0)
3903 return IconFrame
3904 end
3905end
3906
3907local function CreateCell()
3908 local tableCell = Instance.new("Frame")
3909 tableCell.Size = UDim2.new(0.5, -1, 1, 0)
3910 tableCell.BackgroundColor3 = Row.BackgroundColor
3911 tableCell.BorderColor3 = Row.BorderColor
3912 return tableCell
3913end
3914
3915local function CreateLabel(readOnly)
3916 local label = Instance.new("TextLabel")
3917 label.Font = Row.Font
3918 label.FontSize = Row.FontSize
3919 label.TextXAlignment = Row.TextXAlignment
3920 label.BackgroundTransparency = 1
3921
3922 if readOnly then
3923 label.TextColor3 = Row.TextLockedColor
3924 else
3925 label.TextColor3 = Row.TextColor
3926 end
3927 return label
3928end
3929
3930local function CreateTextButton(readOnly, onClick)
3931 local button = Instance.new("TextButton")
3932 button.Font = Row.Font
3933 button.FontSize = Row.FontSize
3934 button.TextXAlignment = Row.TextXAlignment
3935 button.BackgroundTransparency = 1
3936 if readOnly then
3937 button.TextColor3 = Row.TextLockedColor
3938 else
3939 button.TextColor3 = Row.TextColor
3940 button.MouseButton1Click:connect(function()
3941 onClick()
3942 end)
3943 end
3944 return button
3945end
3946
3947local function CreateObject(readOnly)
3948 local button = Instance.new("TextButton")
3949 button.Font = Row.Font
3950 button.FontSize = Row.FontSize
3951 button.TextXAlignment = Row.TextXAlignment
3952 button.BackgroundTransparency = 1
3953 if readOnly then
3954 button.TextColor3 = Row.TextLockedColor
3955 else
3956 button.TextColor3 = Row.TextColor
3957 end
3958 local cancel = Create(Icon('ImageButton',177),{
3959 Name = "Cancel";
3960 Visible = false;
3961 Position = UDim2.new(1,-20,0,0);
3962 Size = UDim2.new(0,20,0,20);
3963 Parent = button;
3964 })
3965 return button
3966end
3967
3968local function CreateTextBox(readOnly)
3969 if readOnly then
3970 local box = CreateLabel(readOnly)
3971 return box
3972 else
3973 local box = Instance.new("TextBox")
3974 if not SettingsRemote:Invoke("ClearProps") then
3975 box.ClearTextOnFocus = false
3976 end
3977 box.Font = Row.Font
3978 box.FontSize = Row.FontSize
3979 box.TextXAlignment = Row.TextXAlignment
3980 box.BackgroundTransparency = 1
3981 box.TextColor3 = Row.TextColor
3982 return box
3983 end
3984end
3985
3986local function CreateDropDownItem(text, onClick)
3987 local button = Instance.new("TextButton")
3988 button.Font = DropDown.Font
3989 button.FontSize = DropDown.FontSize
3990 button.TextColor3 = DropDown.TextColor
3991 button.TextXAlignment = DropDown.TextXAlignment
3992 button.BackgroundColor3 = DropDown.BackColor
3993 button.AutoButtonColor = false
3994 button.BorderSizePixel = 0
3995 button.Active = true
3996 button.Text = text
3997
3998 button.MouseEnter:connect(function()
3999 button.TextColor3 = DropDown.TextColorOver
4000 button.BackgroundColor3 = DropDown.BackColorOver
4001 end)
4002 button.MouseLeave:connect(function()
4003 button.TextColor3 = DropDown.TextColor
4004 button.BackgroundColor3 = DropDown.BackColor
4005 end)
4006 button.MouseButton1Click:connect(function()
4007 onClick(text)
4008 end)
4009 return button
4010end
4011
4012local function CreateDropDown(choices, currentChoice, readOnly, onClick)
4013 local frame = Instance.new("Frame")
4014 frame.Name = "DropDown"
4015 frame.Size = UDim2.new(1, 0, 1, 0)
4016 frame.BackgroundTransparency = 1
4017 frame.Active = true
4018
4019 local menu = nil
4020 local arrow = nil
4021 local expanded = false
4022 local margin = DropDown.BorderSizePixel;
4023
4024 local button = Instance.new("TextButton")
4025 button.Font = Row.Font
4026 button.FontSize = Row.FontSize
4027 button.TextXAlignment = Row.TextXAlignment
4028 button.BackgroundTransparency = 1
4029 button.TextColor3 = Row.TextColor
4030 if readOnly then
4031 button.TextColor3 = Row.TextLockedColor
4032 end
4033 button.Text = currentChoice
4034 button.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
4035 button.Position = UDim2.new(0, Styles.Margin, 0, 0)
4036 button.Parent = frame
4037
4038 local function showArrow(color)
4039 if arrow then arrow:Destroy() end
4040
4041 local graphicTemplate = Create('Frame',{
4042 Name="Graphic";
4043 BorderSizePixel = 0;
4044 BackgroundColor3 = color;
4045 })
4046 local graphicSize = 16/2
4047
4048 arrow = ArrowGraphic(graphicSize,'Down',true,graphicTemplate)
4049 arrow.Position = UDim2.new(1,-graphicSize * 2,0.5,-graphicSize/2)
4050 arrow.Parent = frame
4051 end
4052
4053 local function hideMenu()
4054 expanded = false
4055 showArrow(DropDown.ArrowColor)
4056 if menu then menu:Destroy() end
4057 end
4058
4059 local function showMenu()
4060 expanded = true
4061 menu = Instance.new("Frame")
4062 menu.Size = UDim2.new(1, -2 * margin, 0, #choices * DropDown.Height)
4063 menu.Position = UDim2.new(0, margin, 0, Row.Height + margin)
4064 menu.BackgroundTransparency = 0
4065 menu.BackgroundColor3 = DropDown.BackColor
4066 menu.BorderColor3 = DropDown.BorderColor
4067 menu.BorderSizePixel = DropDown.BorderSizePixel
4068 menu.Active = true
4069 menu.ZIndex = 5
4070 menu.Parent = frame
4071
4072 local parentFrameHeight = menu.Parent.Parent.Parent.Parent.Size.Y.Offset
4073 local rowHeight = menu.Parent.Parent.Parent.Position.Y.Offset
4074 if (rowHeight + menu.Size.Y.Offset) > math.max(parentFrameHeight,PropertiesFrame.AbsoluteSize.y) then
4075 menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
4076 end
4077
4078 local function choice(name)
4079 onClick(name)
4080 hideMenu()
4081 end
4082
4083 for i,name in pairs(choices) do
4084 local option = CreateDropDownItem(name, function()
4085 choice(name)
4086 end)
4087 option.Size = UDim2.new(1, 0, 0, 16)
4088 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
4089 option.ZIndex = menu.ZIndex
4090 option.Parent = menu
4091 end
4092 end
4093
4094 showArrow(DropDown.ArrowColor)
4095
4096 if not readOnly then
4097
4098 button.MouseEnter:connect(function()
4099 button.TextColor3 = Row.TextColor
4100 showArrow(DropDown.ArrowColorOver)
4101 end)
4102 button.MouseLeave:connect(function()
4103 button.TextColor3 = Row.TextColor
4104 if not expanded then
4105 showArrow(DropDown.ArrowColor)
4106 end
4107 end)
4108 button.MouseButton1Click:connect(function()
4109 if expanded then
4110 hideMenu()
4111 else
4112 showMenu()
4113 end
4114 end)
4115 end
4116
4117 return frame,button
4118end
4119
4120local function CreateBrickColor(readOnly, onClick)
4121 local frame = Instance.new("Frame")
4122 frame.Size = UDim2.new(1,0,1,0)
4123 frame.BackgroundTransparency = 1
4124
4125 local colorPalette = Instance.new("Frame")
4126 colorPalette.BackgroundTransparency = 0
4127 colorPalette.SizeConstraint = Enum.SizeConstraint.RelativeXX
4128 colorPalette.Size = UDim2.new(1, -2 * BrickColors.OuterBorder, 1, -2 * BrickColors.OuterBorder)
4129 colorPalette.BorderSizePixel = BrickColors.BorderSizePixel
4130 colorPalette.BorderColor3 = BrickColors.BorderColor
4131 colorPalette.Position = UDim2.new(0, BrickColors.OuterBorder, 0, BrickColors.OuterBorder + Row.Height)
4132 colorPalette.ZIndex = 5
4133 colorPalette.Visible = false
4134 colorPalette.BorderSizePixel = BrickColors.OuterBorder
4135 colorPalette.BorderColor3 = BrickColors.OuterBorderColor
4136 colorPalette.Parent = frame
4137
4138 local function show()
4139 colorPalette.Visible = true
4140 end
4141
4142 local function hide()
4143 colorPalette.Visible = false
4144 end
4145
4146 local function toggle()
4147 colorPalette.Visible = not colorPalette.Visible
4148 end
4149
4150 local colorBox = Instance.new("TextButton", frame)
4151 colorBox.Position = UDim2.new(0, Styles.Margin, 0, Styles.Margin)
4152 colorBox.Size = UDim2.new(0, BrickColors.BoxSize, 0, BrickColors.BoxSize)
4153 colorBox.Text = ""
4154 colorBox.MouseButton1Click:connect(function()
4155 if not readOnly then
4156 toggle()
4157 end
4158 end)
4159
4160 if readOnly then
4161 colorBox.AutoButtonColor = false
4162 end
4163
4164 local spacingBefore = (Styles.Margin * 2) + BrickColors.BoxSize
4165
4166 local propertyLabel = CreateTextButton(readOnly, function()
4167 if not readOnly then
4168 toggle()
4169 end
4170 end)
4171 propertyLabel.Size = UDim2.new(1, (-1 * spacingBefore) - Styles.Margin, 1, 0)
4172 propertyLabel.Position = UDim2.new(0, spacingBefore, 0, 0)
4173 propertyLabel.Parent = frame
4174
4175 local size = (1 / BrickColors.ColorsPerRow)
4176
4177 for index = 0, 127 do
4178 local brickColor = BrickColor.palette(index)
4179 local color3 = brickColor.Color
4180
4181 local x = size * (index % BrickColors.ColorsPerRow)
4182 local y = size * math.floor(index / BrickColors.ColorsPerRow)
4183
4184 local brickColorBox = Instance.new("TextButton")
4185 brickColorBox.Text = ""
4186 brickColorBox.Size = UDim2.new(size,0,size,0)
4187 brickColorBox.BackgroundColor3 = color3
4188 brickColorBox.Position = UDim2.new(x, 0, y, 0)
4189 brickColorBox.ZIndex = colorPalette.ZIndex
4190 brickColorBox.Parent = colorPalette
4191
4192 brickColorBox.MouseButton1Click:connect(function()
4193 hide()
4194 onClick(brickColor)
4195 end)
4196 end
4197
4198 return frame,propertyLabel,colorBox
4199end
4200
4201local function CreateColor3Control(readOnly, onClick)
4202 local frame = Instance.new("Frame")
4203 frame.Size = UDim2.new(1,0,1,0)
4204 frame.BackgroundTransparency = 1
4205
4206 local colorBox = Instance.new("TextButton", frame)
4207 colorBox.Position = UDim2.new(0, Styles.Margin, 0, Styles.Margin)
4208 colorBox.Size = UDim2.new(0, BrickColors.BoxSize, 0, BrickColors.BoxSize)
4209 colorBox.Text = ""
4210 colorBox.AutoButtonColor = false
4211
4212 local spacingBefore = (Styles.Margin * 2) + BrickColors.BoxSize
4213 local box = CreateTextBox(readOnly)
4214 box.Size = UDim2.new(1, (-1 * spacingBefore) - Styles.Margin, 1, 0)
4215 box.Position = UDim2.new(0, spacingBefore, 0, 0)
4216 box.Parent = frame
4217
4218 return frame,box,colorBox
4219end
4220
4221function CreateCheckbox(value, readOnly, onClick)
4222 local checked = value
4223 local mouseover = false
4224
4225 local checkboxFrame = Instance.new("ImageButton")
4226 checkboxFrame.Size = UDim2.new(0, Sprite.Width, 0, Sprite.Height)
4227 checkboxFrame.BackgroundTransparency = 1
4228 checkboxFrame.ClipsDescendants = true
4229 --checkboxFrame.Position = UDim2.new(0, Styles.Margin, 0, Styles.Margin)
4230
4231 local spritesheetImage = Instance.new("ImageLabel", checkboxFrame)
4232 spritesheetImage.Name = "SpritesheetImageLabel"
4233 spritesheetImage.Size = UDim2.new(0, Spritesheet.Width, 0, Spritesheet.Height)
4234 spritesheetImage.Image = Spritesheet.Image
4235 spritesheetImage.BackgroundTransparency = 1
4236
4237 local function updateSprite()
4238 local spriteName = GetCheckboxImageName(checked, readOnly, mouseover)
4239 local spritePosition = SpritePosition(spriteName)
4240 spritesheetImage.Position = UDim2.new(0, -1 * spritePosition[1], 0, -1 * spritePosition[2])
4241 end
4242
4243 local function setValue(val)
4244 checked = val
4245 updateSprite()
4246 end
4247
4248 if not readOnly then
4249 checkboxFrame.MouseEnter:connect(function() mouseover = true updateSprite() end)
4250 checkboxFrame.MouseLeave:connect(function() mouseover = false updateSprite() end)
4251 checkboxFrame.MouseButton1Click:connect(function()
4252 onClick(checked)
4253 end)
4254 end
4255
4256 updateSprite()
4257
4258 return checkboxFrame, setValue
4259end
4260
4261
4262
4263-- Code for handling controls of various data types --
4264
4265local Controls = {}
4266
4267Controls["default"] = function(object, propertyData, readOnly)
4268 local propertyName = propertyData["Name"]
4269 local propertyType = propertyData["ValueType"]
4270
4271 local box = CreateTextBox(readOnly)
4272 box.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
4273 box.Position = UDim2.new(0, Styles.Margin, 0, 0)
4274
4275 local function update()
4276 local value = object[propertyName]
4277 box.Text = ToString(value, propertyType)
4278 end
4279
4280 if not readOnly then
4281 box.FocusLost:connect(function(enterPressed)
4282 Set(object, propertyData, ToValue(box.Text,propertyType))
4283 update()
4284 end)
4285 end
4286
4287 update()
4288
4289 object.Changed:connect(function(property)
4290 if (property == propertyName) then
4291 update()
4292 end
4293 end)
4294
4295 return box
4296end
4297
4298Controls["bool"] = function(object, propertyData, readOnly)
4299 local propertyName = propertyData["Name"]
4300 local checked = object[propertyName]
4301
4302 local checkbox, setValue = CreateCheckbox(checked, readOnly, function(value)
4303 Set(object, propertyData, not checked)
4304 end)
4305 checkbox.Position = UDim2.new(0, Styles.Margin, 0, Styles.Margin)
4306
4307 setValue(checked)
4308
4309 local function update()
4310 checked = object[propertyName]
4311 setValue(checked)
4312 end
4313
4314 object.Changed:connect(function(property)
4315 if (property == propertyName) then
4316 update()
4317 end
4318 end)
4319
4320 if object:IsA("BoolValue") then
4321 object.Changed:connect(function(val)
4322 update()
4323 end)
4324 end
4325
4326 update()
4327
4328 return checkbox
4329end
4330
4331Controls["BrickColor"] = function(object, propertyData, readOnly)
4332 local propertyName = propertyData["Name"]
4333
4334 local frame,label,brickColorBox = CreateBrickColor(readOnly, function(brickColor)
4335 Set(object, propertyData, brickColor)
4336 end)
4337
4338 local function update()
4339 local value = object[propertyName]
4340 brickColorBox.BackgroundColor3 = value.Color
4341 label.Text = tostring(value)
4342 end
4343
4344 update()
4345
4346 object.Changed:connect(function(property)
4347 if (property == propertyName) then
4348 update()
4349 end
4350 end)
4351
4352 return frame
4353end
4354
4355Controls["Color3"] = function(object, propertyData, readOnly)
4356 local propertyName = propertyData["Name"]
4357
4358 local frame,textBox,colorBox = CreateColor3Control(readOnly)
4359
4360 textBox.FocusLost:connect(function(enterPressed)
4361 Set(object, propertyData, ToValue(textBox.Text,"Color3"))
4362 local value = object[propertyName]
4363 colorBox.BackgroundColor3 = value
4364 textBox.Text = ToString(value, "Color3")
4365 end)
4366
4367 local function update()
4368 local value = object[propertyName]
4369 colorBox.BackgroundColor3 = value
4370 textBox.Text = ToString(value, "Color3")
4371 end
4372
4373 update()
4374
4375 object.Changed:connect(function(property)
4376 if (property == propertyName) then
4377 update()
4378 end
4379 end)
4380
4381 return frame
4382end
4383
4384Controls["Enum"] = function(object, propertyData, readOnly)
4385 local propertyName = propertyData["Name"]
4386 local propertyType = propertyData["ValueType"]
4387
4388 local enumName = object[propertyName].Name
4389
4390 local enumNames = {}
4391 for _,enum in pairs(Enum[tostring(propertyType)]:GetEnumItems()) do
4392 table.insert(enumNames, enum.Name)
4393 end
4394
4395 local dropdown, propertyLabel = CreateDropDown(enumNames, enumName, readOnly, function(value)
4396 Set(object, propertyData, value)
4397 end)
4398 --dropdown.Parent = frame
4399
4400 local function update()
4401 local value = object[propertyName].Name
4402 propertyLabel.Text = tostring(value)
4403 end
4404
4405 update()
4406
4407 object.Changed:connect(function(property)
4408 if (property == propertyName) then
4409 update()
4410 end
4411 end)
4412
4413 return dropdown
4414end
4415
4416Controls["Object"] = function(object, propertyData, readOnly)
4417 local propertyName = propertyData["Name"]
4418 local propertyType = propertyData["ValueType"]
4419
4420 local box = CreateObject(readOnly,function()end)
4421 box.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
4422 box.Position = UDim2.new(0, Styles.Margin, 0, 0)
4423
4424 local function update()
4425 if AwaitingObjectObj == object then
4426 if AwaitingObjectValue == true then
4427 box.Text = "Select an Object"
4428 return
4429 end
4430 end
4431 local value = object[propertyName]
4432 box.Text = ToString(value, propertyType)
4433 end
4434
4435 if not readOnly then
4436 box.MouseButton1Click:connect(function()
4437 if AwaitingObjectValue then
4438 AwaitingObjectValue = false
4439 update()
4440 return
4441 end
4442 AwaitingObjectValue = true
4443 AwaitingObjectObj = object
4444 AwaitingObjectProp = propertyData
4445 box.Text = "Select an Object"
4446 end)
4447
4448 box.Cancel.Visible = true
4449 box.Cancel.MouseButton1Click:connect(function()
4450 object[propertyName] = nil
4451 end)
4452 end
4453
4454 update()
4455
4456 object.Changed:connect(function(property)
4457 if (property == propertyName) then
4458 update()
4459 end
4460 end)
4461
4462 if object:IsA("ObjectValue") then
4463 object.Changed:connect(function(val)
4464 update()
4465 end)
4466 end
4467
4468 return box
4469end
4470
4471function GetControl(object, propertyData, readOnly)
4472 local propertyType = propertyData["ValueType"]
4473 local control = nil
4474
4475 if Controls[propertyType] then
4476 control = Controls[propertyType](object, propertyData, readOnly)
4477 elseif RbxApi.IsEnum(propertyType) then
4478 control = Controls["Enum"](object, propertyData, readOnly)
4479 else
4480 control = Controls["default"](object, propertyData, readOnly)
4481 end
4482 return control
4483end
4484-- Permissions
4485
4486function CanEditObject(object)
4487 local player = Players.LocalPlayer
4488 local character = player.Character
4489 return Permissions.CanEdit
4490end
4491
4492function CanEditProperty(object,propertyData)
4493 local tags = propertyData["tags"]
4494 for _,name in pairs(tags) do
4495 if name == "readonly" then
4496 return false
4497 end
4498 end
4499 return CanEditObject(object)
4500end
4501
4502--RbxApi
4503local function PropertyIsHidden(propertyData)
4504 local tags = propertyData["tags"]
4505 for _,name in pairs(tags) do
4506 if name == "deprecated"
4507 or name == "hidden"
4508 or name == "writeonly" then
4509 return true
4510 end
4511 end
4512 return false
4513end
4514
4515function Set(object, propertyData, value)
4516 local propertyName = propertyData["Name"]
4517 local propertyType = propertyData["ValueType"]
4518
4519 if value == nil then return end
4520
4521 for i,v in pairs(GetSelection()) do
4522 if CanEditProperty(v,propertyData) then
4523 pcall(function()
4524 --print("Setting " .. propertyName .. " to " .. tostring(value))
4525 v[propertyName] = value
4526 end)
4527 end
4528 end
4529end
4530
4531function CreateRow(object, propertyData, isAlternateRow)
4532 local propertyName = propertyData["Name"]
4533 local propertyType = propertyData["ValueType"]
4534 local propertyValue = object[propertyName]
4535 --rowValue, rowValueType, isAlternate
4536 local backColor = Row.BackgroundColor;
4537 if (isAlternateRow) then
4538 backColor = Row.BackgroundColorAlternate
4539 end
4540
4541 local readOnly = not CanEditProperty(object, propertyData)
4542 if propertyType == "Instance" or propertyName == "Parent" then readOnly = true end
4543
4544 local rowFrame = Instance.new("Frame")
4545 rowFrame.Size = UDim2.new(1,0,0,Row.Height)
4546 rowFrame.BackgroundTransparency = 1
4547 rowFrame.Name = 'Row'
4548
4549 local propertyLabelFrame = CreateCell()
4550 propertyLabelFrame.Parent = rowFrame
4551 propertyLabelFrame.ClipsDescendants = true
4552
4553 local propertyLabel = CreateLabel(readOnly)
4554 propertyLabel.Text = propertyName
4555 propertyLabel.Size = UDim2.new(1, -1 * Row.TitleMarginLeft, 1, 0)
4556 propertyLabel.Position = UDim2.new(0, Row.TitleMarginLeft, 0, 0)
4557 propertyLabel.Parent = propertyLabelFrame
4558
4559 local propertyValueFrame = CreateCell()
4560 propertyValueFrame.Size = UDim2.new(0.5, -1, 1, 0)
4561 propertyValueFrame.Position = UDim2.new(0.5, 0, 0, 0)
4562 propertyValueFrame.Parent = rowFrame
4563
4564 local control = GetControl(object, propertyData, readOnly)
4565 control.Parent = propertyValueFrame
4566
4567 rowFrame.MouseEnter:connect(function()
4568 propertyLabelFrame.BackgroundColor3 = Row.BackgroundColorMouseover
4569 propertyValueFrame.BackgroundColor3 = Row.BackgroundColorMouseover
4570 end)
4571 rowFrame.MouseLeave:connect(function()
4572 propertyLabelFrame.BackgroundColor3 = backColor
4573 propertyValueFrame.BackgroundColor3 = backColor
4574 end)
4575
4576 propertyLabelFrame.BackgroundColor3 = backColor
4577 propertyValueFrame.BackgroundColor3 = backColor
4578
4579 return rowFrame
4580end
4581
4582function ClearPropertiesList()
4583 for _,instance in pairs(ContentFrame:GetChildren()) do
4584 instance:Destroy()
4585 end
4586end
4587
4588local selection = Gui:FindFirstChild("Selection", 1)
4589print(selection)
4590
4591function displayProperties(props)
4592 for i,v in pairs(props) do
4593 pcall(function()
4594 local a = CreateRow(v.object, v.propertyData, ((numRows % 2) == 0))
4595 a.Position = UDim2.new(0,0,0,numRows*Row.Height)
4596 a.Parent = ContentFrame
4597 numRows = numRows + 1
4598 end)
4599 end
4600end
4601
4602function checkForDupe(prop,props)
4603 for i,v in pairs(props) do
4604 if v.propertyData.Name == prop.Name and v.propertyData.ValueType == prop.ValueType then
4605 return true
4606 end
4607 end
4608 return false
4609end
4610
4611function sortProps(t)
4612 table.sort(t,
4613 function(x,y) return x.propertyData.Name < y.propertyData.Name
4614 end)
4615end
4616
4617function showProperties(obj)
4618 ClearPropertiesList()
4619 if obj == nil then return end
4620 local propHolder = {}
4621 local foundProps = {}
4622 numRows = 0
4623 for _,nextObj in pairs(obj) do
4624 if not foundProps[nextObj.className] then
4625 foundProps[nextObj.className] = true
4626 for i,v in pairs(RbxApi.GetProperties(nextObj.className)) do
4627 local suc, err = pcall(function()
4628 if not (PropertyIsHidden(v)) and not checkForDupe(v,propHolder) then
4629 if string.find(string.lower(v.Name),string.lower(propertiesSearch.Text)) or not searchingProperties() then
4630 table.insert(propHolder,{propertyData = v, object = nextObj})
4631 end
4632 end
4633 end)
4634 --[[if not suc then
4635 warn("Problem getting the value of property " .. v.Name .. " | " .. err)
4636 end --]]
4637 end
4638 end
4639 end
4640 sortProps(propHolder)
4641 displayProperties(propHolder)
4642 ContentFrame.Size = UDim2.new(1, 0, 0, numRows * Row.Height)
4643 scrollBar.ScrollIndex = 0
4644 scrollBar.TotalSpace = numRows * Row.Height
4645 scrollBar.Update()
4646end
4647
4648----------------------------------------------------------------
4649-----------------------SCROLLBAR STUFF--------------------------
4650----------------------------------------------------------------
4651----------------------------------------------------------------
4652local ScrollBarWidth = 16
4653
4654local ScrollStyles = {
4655 Background = Color3.new(233/255, 233/255, 233/255);
4656 Border = Color3.new(149/255, 149/255, 149/255);
4657 Selected = Color3.new( 63/255, 119/255, 189/255);
4658 BorderSelected = Color3.new( 55/255, 106/255, 167/255);
4659 Text = Color3.new( 0/255, 0/255, 0/255);
4660 TextDisabled = Color3.new(128/255, 128/255, 128/255);
4661 TextSelected = Color3.new(255/255, 255/255, 255/255);
4662 Button = Color3.new(221/255, 221/255, 221/255);
4663 ButtonBorder = Color3.new(149/255, 149/255, 149/255);
4664 ButtonSelected = Color3.new(255/255, 0/255, 0/255);
4665 Field = Color3.new(255/255, 255/255, 255/255);
4666 FieldBorder = Color3.new(191/255, 191/255, 191/255);
4667 TitleBackground = Color3.new(178/255, 178/255, 178/255);
4668}
4669do
4670 local ZIndexLock = {}
4671 function SetZIndex(object,z)
4672 if not ZIndexLock[object] then
4673 ZIndexLock[object] = true
4674 if object:IsA'GuiObject' then
4675 object.ZIndex = z
4676 end
4677 local children = object:GetChildren()
4678 for i = 1,#children do
4679 SetZIndex(children[i],z)
4680 end
4681 ZIndexLock[object] = nil
4682 end
4683 end
4684end
4685function SetZIndexOnChanged(object)
4686 return object.Changed:connect(function(p)
4687 if p == "ZIndex" then
4688 SetZIndex(object,object.ZIndex)
4689 end
4690 end)
4691end
4692function Create(ty,data)
4693 local obj
4694 if type(ty) == 'string' then
4695 obj = Instance.new(ty)
4696 else
4697 obj = ty
4698 end
4699 for k, v in pairs(data) do
4700 if type(k) == 'number' then
4701 v.Parent = obj
4702 else
4703 obj[k] = v
4704 end
4705 end
4706 return obj
4707end
4708-- returns the ascendant ScreenGui of an object
4709function GetScreen(screen)
4710 if screen == nil then return nil end
4711 while not screen:IsA("ScreenGui") do
4712 screen = screen.Parent
4713 if screen == nil then return nil end
4714 end
4715 return screen
4716end
4717-- AutoButtonColor doesn't always reset properly
4718function ResetButtonColor(button)
4719 local active = button.Active
4720 button.Active = not active
4721 button.Active = active
4722end
4723
4724function ArrowGraphic(size,dir,scaled,template)
4725 local Frame = Create('Frame',{
4726 Name = "Arrow Graphic";
4727 BorderSizePixel = 0;
4728 Size = UDim2.new(0,size,0,size);
4729 Transparency = 1;
4730 })
4731 if not template then
4732 template = Instance.new("Frame")
4733 template.BorderSizePixel = 0
4734 end
4735
4736 local transform
4737 if dir == nil or dir == 'Up' then
4738 function transform(p,s) return p,s end
4739 elseif dir == 'Down' then
4740 function transform(p,s) return UDim2.new(0,p.X.Offset,0,size-p.Y.Offset-1),s end
4741 elseif dir == 'Left' then
4742 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
4743 elseif dir == 'Right' then
4744 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
4745 end
4746
4747 local scale
4748 if scaled then
4749 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
4750 else
4751 function scale(p,s) return p,s end
4752 end
4753
4754 local o = math.floor(size/4)
4755 if size%2 == 0 then
4756 local n = size/2-1
4757 for i = 0,n do
4758 local t = template:Clone()
4759 local p,s = scale(transform(
4760 UDim2.new(0,n-i,0,o+i),
4761 UDim2.new(0,(i+1)*2,0,1)
4762 ))
4763 t.Position = p
4764 t.Size = s
4765 t.Parent = Frame
4766 end
4767 else
4768 local n = (size-1)/2
4769 for i = 0,n do
4770 local t = template:Clone()
4771 local p,s = scale(transform(
4772 UDim2.new(0,n-i,0,o+i),
4773 UDim2.new(0,i*2+1,0,1)
4774 ))
4775 t.Position = p
4776 t.Size = s
4777 t.Parent = Frame
4778 end
4779 end
4780 if size%4 > 1 then
4781 local t = template:Clone()
4782 local p,s = scale(transform(
4783 UDim2.new(0,0,0,size-o-1),
4784 UDim2.new(0,size,0,1)
4785 ))
4786 t.Position = p
4787 t.Size = s
4788 t.Parent = Frame
4789 end
4790 return Frame
4791end
4792
4793function GripGraphic(size,dir,spacing,scaled,template)
4794 local Frame = Create('Frame',{
4795 Name = "Grip Graphic";
4796 BorderSizePixel = 0;
4797 Size = UDim2.new(0,size.x,0,size.y);
4798 Transparency = 1;
4799 })
4800 if not template then
4801 template = Instance.new("Frame")
4802 template.BorderSizePixel = 0
4803 end
4804
4805 spacing = spacing or 2
4806
4807 local scale
4808 if scaled then
4809 function scale(p) return UDim2.new(p.X.Offset/size.x,0,p.Y.Offset/size.y,0) end
4810 else
4811 function scale(p) return p end
4812 end
4813
4814 if dir == 'Vertical' then
4815 for i=0,size.x-1,spacing do
4816 local t = template:Clone()
4817 t.Size = scale(UDim2.new(0,1,0,size.y))
4818 t.Position = scale(UDim2.new(0,i,0,0))
4819 t.Parent = Frame
4820 end
4821 elseif dir == nil or dir == 'Horizontal' then
4822 for i=0,size.y-1,spacing do
4823 local t = template:Clone()
4824 t.Size = scale(UDim2.new(0,size.x,0,1))
4825 t.Position = scale(UDim2.new(0,0,0,i))
4826 t.Parent = Frame
4827 end
4828 end
4829
4830 return Frame
4831end
4832
4833do
4834 local mt = {
4835 __index = {
4836 GetScrollPercent = function(self)
4837 return self.ScrollIndex/(self.TotalSpace-self.VisibleSpace)
4838 end;
4839 CanScrollDown = function(self)
4840 return self.ScrollIndex + self.VisibleSpace < self.TotalSpace
4841 end;
4842 CanScrollUp = function(self)
4843 return self.ScrollIndex > 0
4844 end;
4845 ScrollDown = function(self)
4846 self.ScrollIndex = self.ScrollIndex + self.PageIncrement
4847 self:Update()
4848 end;
4849 ScrollUp = function(self)
4850 self.ScrollIndex = self.ScrollIndex - self.PageIncrement
4851 self:Update()
4852 end;
4853 ScrollTo = function(self,index)
4854 self.ScrollIndex = index
4855 self:Update()
4856 end;
4857 SetScrollPercent = function(self,percent)
4858 self.ScrollIndex = math.floor((self.TotalSpace - self.VisibleSpace)*percent + 0.5)
4859 self:Update()
4860 end;
4861 };
4862 }
4863 mt.__index.CanScrollRight = mt.__index.CanScrollDown
4864 mt.__index.CanScrollLeft = mt.__index.CanScrollUp
4865 mt.__index.ScrollLeft = mt.__index.ScrollUp
4866 mt.__index.ScrollRight = mt.__index.ScrollDown
4867
4868 function ScrollBar(horizontal)
4869 -- create row scroll bar
4870 local ScrollFrame = Create('Frame',{
4871 Name = "ScrollFrame";
4872 Position = horizontal and UDim2.new(0,0,1,-ScrollBarWidth) or UDim2.new(1,-ScrollBarWidth,0,0);
4873 Size = horizontal and UDim2.new(1,0,0,ScrollBarWidth) or UDim2.new(0,ScrollBarWidth,1,0);
4874 BackgroundTransparency = 1;
4875 Create('ImageButton',{
4876 Name = "ScrollDown";
4877 Position = horizontal and UDim2.new(1,-ScrollBarWidth,0,0) or UDim2.new(0,0,1,-ScrollBarWidth);
4878 Size = UDim2.new(0, ScrollBarWidth, 0, ScrollBarWidth);
4879 BackgroundColor3 = ScrollStyles.Button;
4880 BorderColor3 = ScrollStyles.Border;
4881 --BorderSizePixel = 0;
4882 });
4883 Create('ImageButton',{
4884 Name = "ScrollUp";
4885 Size = UDim2.new(0, ScrollBarWidth, 0, ScrollBarWidth);
4886 BackgroundColor3 = ScrollStyles.Button;
4887 BorderColor3 = ScrollStyles.Border;
4888 --BorderSizePixel = 0;
4889 });
4890 Create('ImageButton',{
4891 Name = "ScrollBar";
4892 Size = horizontal and UDim2.new(1,-ScrollBarWidth*2,1,0) or UDim2.new(1,0,1,-ScrollBarWidth*2);
4893 Position = horizontal and UDim2.new(0,ScrollBarWidth,0,0) or UDim2.new(0,0,0,ScrollBarWidth);
4894 AutoButtonColor = false;
4895 BackgroundColor3 = Color3.new(0.94902, 0.94902, 0.94902);
4896 BorderColor3 = ScrollStyles.Border;
4897 --BorderSizePixel = 0;
4898 Create('ImageButton',{
4899 Name = "ScrollThumb";
4900 AutoButtonColor = false;
4901 Size = UDim2.new(0, ScrollBarWidth, 0, ScrollBarWidth);
4902 BackgroundColor3 = ScrollStyles.Button;
4903 BorderColor3 = ScrollStyles.Border;
4904 --BorderSizePixel = 0;
4905 });
4906 });
4907 })
4908
4909 local graphicTemplate = Create('Frame',{
4910 Name="Graphic";
4911 BorderSizePixel = 0;
4912 BackgroundColor3 = ScrollStyles.Border;
4913 })
4914 local graphicSize = ScrollBarWidth/2
4915
4916 local ScrollDownFrame = ScrollFrame.ScrollDown
4917 local ScrollDownGraphic = ArrowGraphic(graphicSize,horizontal and 'Right' or 'Down',true,graphicTemplate)
4918 ScrollDownGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
4919 ScrollDownGraphic.Parent = ScrollDownFrame
4920 local ScrollUpFrame = ScrollFrame.ScrollUp
4921 local ScrollUpGraphic = ArrowGraphic(graphicSize,horizontal and 'Left' or 'Up',true,graphicTemplate)
4922 ScrollUpGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
4923 ScrollUpGraphic.Parent = ScrollUpFrame
4924 local ScrollBarFrame = ScrollFrame.ScrollBar
4925 local ScrollThumbFrame = ScrollBarFrame.ScrollThumb
4926 do
4927 local size = ScrollBarWidth*3/8
4928 local Decal = GripGraphic(Vector2.new(size,size),horizontal and 'Vertical' or 'Horizontal',2,graphicTemplate)
4929 Decal.Position = UDim2.new(0.5,-size/2,0.5,-size/2)
4930 Decal.Parent = ScrollThumbFrame
4931 end
4932
4933 local MouseDrag = Create('ImageButton',{
4934 Name = "MouseDrag";
4935 Position = UDim2.new(-0.25,0,-0.25,0);
4936 Size = UDim2.new(1.5,0,1.5,0);
4937 Transparency = 1;
4938 AutoButtonColor = false;
4939 Active = true;
4940 ZIndex = 10;
4941 })
4942
4943 local Class = setmetatable({
4944 GUI = ScrollFrame;
4945 ScrollIndex = 0;
4946 VisibleSpace = 0;
4947 TotalSpace = 0;
4948 PageIncrement = 1;
4949 },mt)
4950
4951 local UpdateScrollThumb
4952 if horizontal then
4953 function UpdateScrollThumb()
4954 ScrollThumbFrame.Size = UDim2.new(Class.VisibleSpace/Class.TotalSpace,0,0,ScrollBarWidth)
4955 if ScrollThumbFrame.AbsoluteSize.x < ScrollBarWidth then
4956 ScrollThumbFrame.Size = UDim2.new(0,ScrollBarWidth,0,ScrollBarWidth)
4957 end
4958 local barSize = ScrollBarFrame.AbsoluteSize.x
4959 ScrollThumbFrame.Position = UDim2.new(Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.x)/barSize,0,0,0)
4960 end
4961 else
4962 function UpdateScrollThumb()
4963 ScrollThumbFrame.Size = UDim2.new(0,ScrollBarWidth,Class.VisibleSpace/Class.TotalSpace,0)
4964 if ScrollThumbFrame.AbsoluteSize.y < ScrollBarWidth then
4965 ScrollThumbFrame.Size = UDim2.new(0,ScrollBarWidth,0,ScrollBarWidth)
4966 end
4967 local barSize = ScrollBarFrame.AbsoluteSize.y
4968 ScrollThumbFrame.Position = UDim2.new(0,0,Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.y)/barSize,0)
4969 end
4970 end
4971
4972 local lastDown
4973 local lastUp
4974 local scrollStyle = {BackgroundColor3=ScrollStyles.Border,BackgroundTransparency=0}
4975 local scrollStyle_ds = {BackgroundColor3=ScrollStyles.Border,BackgroundTransparency=0.7}
4976
4977 local function Update()
4978 local t = Class.TotalSpace
4979 local v = Class.VisibleSpace
4980 local s = Class.ScrollIndex
4981 if v <= t then
4982 if s > 0 then
4983 if s + v > t then
4984 Class.ScrollIndex = t - v
4985 end
4986 else
4987 Class.ScrollIndex = 0
4988 end
4989 else
4990 Class.ScrollIndex = 0
4991 end
4992
4993 if Class.UpdateCallback then
4994 if Class.UpdateCallback(Class) == false then
4995 return
4996 end
4997 end
4998
4999 local down = Class:CanScrollDown()
5000 local up = Class:CanScrollUp()
5001 if down ~= lastDown then
5002 lastDown = down
5003 ScrollDownFrame.Active = down
5004 ScrollDownFrame.AutoButtonColor = down
5005 local children = ScrollDownGraphic:GetChildren()
5006 local style = down and scrollStyle or scrollStyle_ds
5007 for i = 1,#children do
5008 Create(children[i],style)
5009 end
5010 end
5011 if up ~= lastUp then
5012 lastUp = up
5013 ScrollUpFrame.Active = up
5014 ScrollUpFrame.AutoButtonColor = up
5015 local children = ScrollUpGraphic:GetChildren()
5016 local style = up and scrollStyle or scrollStyle_ds
5017 for i = 1,#children do
5018 Create(children[i],style)
5019 end
5020 end
5021 ScrollThumbFrame.Visible = down or up
5022 UpdateScrollThumb()
5023 end
5024 Class.Update = Update
5025
5026 SetZIndexOnChanged(ScrollFrame)
5027
5028 local scrollEventID = 0
5029 ScrollDownFrame.MouseButton1Down:connect(function()
5030 scrollEventID = tick()
5031 local current = scrollEventID
5032 local up_con
5033 up_con = MouseDrag.MouseButton1Up:connect(function()
5034 scrollEventID = tick()
5035 MouseDrag.Parent = nil
5036 ResetButtonColor(ScrollDownFrame)
5037 up_con:disconnect(); drag = nil
5038 end)
5039 MouseDrag.Parent = GetScreen(ScrollFrame)
5040 Class:ScrollDown()
5041 wait(0.2) -- delay before auto scroll
5042 while scrollEventID == current do
5043 Class:ScrollDown()
5044 if not Class:CanScrollDown() then break end
5045 wait()
5046 end
5047 end)
5048
5049 ScrollDownFrame.MouseButton1Up:connect(function()
5050 scrollEventID = tick()
5051 end)
5052
5053 ScrollUpFrame.MouseButton1Down:connect(function()
5054 scrollEventID = tick()
5055 local current = scrollEventID
5056 local up_con
5057 up_con = MouseDrag.MouseButton1Up:connect(function()
5058 scrollEventID = tick()
5059 MouseDrag.Parent = nil
5060 ResetButtonColor(ScrollUpFrame)
5061 up_con:disconnect(); drag = nil
5062 end)
5063 MouseDrag.Parent = GetScreen(ScrollFrame)
5064 Class:ScrollUp()
5065 wait(0.2)
5066 while scrollEventID == current do
5067 Class:ScrollUp()
5068 if not Class:CanScrollUp() then break end
5069 wait()
5070 end
5071 end)
5072
5073 ScrollUpFrame.MouseButton1Up:connect(function()
5074 scrollEventID = tick()
5075 end)
5076
5077 if horizontal then
5078 ScrollBarFrame.MouseButton1Down:connect(function(x,y)
5079 scrollEventID = tick()
5080 local current = scrollEventID
5081 local up_con
5082 up_con = MouseDrag.MouseButton1Up:connect(function()
5083 scrollEventID = tick()
5084 MouseDrag.Parent = nil
5085 ResetButtonColor(ScrollUpFrame)
5086 up_con:disconnect(); drag = nil
5087 end)
5088 MouseDrag.Parent = GetScreen(ScrollFrame)
5089 if x > ScrollThumbFrame.AbsolutePosition.x then
5090 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
5091 wait(0.2)
5092 while scrollEventID == current do
5093 if x < ScrollThumbFrame.AbsolutePosition.x + ScrollThumbFrame.AbsoluteSize.x then break end
5094 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
5095 wait()
5096 end
5097 else
5098 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
5099 wait(0.2)
5100 while scrollEventID == current do
5101 if x > ScrollThumbFrame.AbsolutePosition.x then break end
5102 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
5103 wait()
5104 end
5105 end
5106 end)
5107 else
5108 ScrollBarFrame.MouseButton1Down:connect(function(x,y)
5109 scrollEventID = tick()
5110 local current = scrollEventID
5111 local up_con
5112 up_con = MouseDrag.MouseButton1Up:connect(function()
5113 scrollEventID = tick()
5114 MouseDrag.Parent = nil
5115 ResetButtonColor(ScrollUpFrame)
5116 up_con:disconnect(); drag = nil
5117 end)
5118 MouseDrag.Parent = GetScreen(ScrollFrame)
5119 if y > ScrollThumbFrame.AbsolutePosition.y then
5120 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
5121 wait(0.2)
5122 while scrollEventID == current do
5123 if y < ScrollThumbFrame.AbsolutePosition.y + ScrollThumbFrame.AbsoluteSize.y then break end
5124 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
5125 wait()
5126 end
5127 else
5128 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
5129 wait(0.2)
5130 while scrollEventID == current do
5131 if y > ScrollThumbFrame.AbsolutePosition.y then break end
5132 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
5133 wait()
5134 end
5135 end
5136 end)
5137 end
5138
5139 if horizontal then
5140 ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
5141 scrollEventID = tick()
5142 local mouse_offset = x - ScrollThumbFrame.AbsolutePosition.x
5143 local drag_con
5144 local up_con
5145 drag_con = MouseDrag.MouseMoved:connect(function(x,y)
5146 local bar_abs_pos = ScrollBarFrame.AbsolutePosition.x
5147 local bar_drag = ScrollBarFrame.AbsoluteSize.x - ScrollThumbFrame.AbsoluteSize.x
5148 local bar_abs_one = bar_abs_pos + bar_drag
5149 x = x - mouse_offset
5150 x = x < bar_abs_pos and bar_abs_pos or x > bar_abs_one and bar_abs_one or x
5151 x = x - bar_abs_pos
5152 Class:SetScrollPercent(x/(bar_drag))
5153 end)
5154 up_con = MouseDrag.MouseButton1Up:connect(function()
5155 scrollEventID = tick()
5156 MouseDrag.Parent = nil
5157 ResetButtonColor(ScrollThumbFrame)
5158 drag_con:disconnect(); drag_con = nil
5159 up_con:disconnect(); drag = nil
5160 end)
5161 MouseDrag.Parent = GetScreen(ScrollFrame)
5162 end)
5163 else
5164 ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
5165 scrollEventID = tick()
5166 local mouse_offset = y - ScrollThumbFrame.AbsolutePosition.y
5167 local drag_con
5168 local up_con
5169 drag_con = MouseDrag.MouseMoved:connect(function(x,y)
5170 local bar_abs_pos = ScrollBarFrame.AbsolutePosition.y
5171 local bar_drag = ScrollBarFrame.AbsoluteSize.y - ScrollThumbFrame.AbsoluteSize.y
5172 local bar_abs_one = bar_abs_pos + bar_drag
5173 y = y - mouse_offset
5174 y = y < bar_abs_pos and bar_abs_pos or y > bar_abs_one and bar_abs_one or y
5175 y = y - bar_abs_pos
5176 Class:SetScrollPercent(y/(bar_drag))
5177 end)
5178 up_con = MouseDrag.MouseButton1Up:connect(function()
5179 scrollEventID = tick()
5180 MouseDrag.Parent = nil
5181 ResetButtonColor(ScrollThumbFrame)
5182 drag_con:disconnect(); drag_con = nil
5183 up_con:disconnect(); drag = nil
5184 end)
5185 MouseDrag.Parent = GetScreen(ScrollFrame)
5186 end)
5187 end
5188
5189 function Class:Destroy()
5190 ScrollFrame:Destroy()
5191 MouseDrag:Destroy()
5192 for k in pairs(Class) do
5193 Class[k] = nil
5194 end
5195 setmetatable(Class,nil)
5196 end
5197
5198 Update()
5199
5200 return Class
5201 end
5202end
5203
5204----------------------------------------------------------------
5205----------------------------------------------------------------
5206----------------------------------------------------------------
5207----------------------------------------------------------------
5208
5209local MainFrame = Instance.new("Frame")
5210MainFrame.Name = "MainFrame"
5211MainFrame.Size = UDim2.new(1, -1 * ScrollBarWidth, 1, 0)
5212MainFrame.Position = UDim2.new(0, 0, 0, 0)
5213MainFrame.BackgroundTransparency = 1
5214MainFrame.ClipsDescendants = true
5215MainFrame.Parent = PropertiesFrame
5216
5217ContentFrame = Instance.new("Frame")
5218ContentFrame.Name = "ContentFrame"
5219ContentFrame.Size = UDim2.new(1, 0, 0, 0)
5220ContentFrame.BackgroundTransparency = 1
5221ContentFrame.Parent = MainFrame
5222
5223scrollBar = ScrollBar(false)
5224scrollBar.PageIncrement = 1
5225Create(scrollBar.GUI,{
5226 Position = UDim2.new(1,-ScrollBarWidth,0,0);
5227 Size = UDim2.new(0,ScrollBarWidth,1,0);
5228 Parent = PropertiesFrame;
5229})
5230
5231scrollBarH = ScrollBar(true)
5232scrollBarH.PageIncrement = ScrollBarWidth
5233Create(scrollBarH.GUI,{
5234 Position = UDim2.new(0,0,1,-ScrollBarWidth);
5235 Size = UDim2.new(1,-ScrollBarWidth,0,ScrollBarWidth);
5236 Visible = false;
5237 Parent = PropertiesFrame;
5238})
5239
5240do
5241 local listEntries = {}
5242 local nameConnLookup = {}
5243
5244 function scrollBar.UpdateCallback(self)
5245 scrollBar.TotalSpace = ContentFrame.AbsoluteSize.Y
5246 scrollBar.VisibleSpace = MainFrame.AbsoluteSize.Y
5247 ContentFrame.Position = UDim2.new(ContentFrame.Position.X.Scale,ContentFrame.Position.X.Offset,0,-1*scrollBar.ScrollIndex)
5248 end
5249
5250 function scrollBarH.UpdateCallback(self)
5251
5252 end
5253
5254 MainFrame.Changed:connect(function(p)
5255 if p == 'AbsoluteSize' then
5256 scrollBarH.VisibleSpace = math.ceil(MainFrame.AbsoluteSize.x)
5257 scrollBarH:Update()
5258 scrollBar.VisibleSpace = math.ceil(MainFrame.AbsoluteSize.y)
5259 scrollBar:Update()
5260 end
5261 end)
5262
5263 local wheelAmount = Row.Height
5264 PropertiesFrame.MouseWheelForward:connect(function()
5265 if scrollBar.VisibleSpace - 1 > wheelAmount then
5266 scrollBar:ScrollTo(scrollBar.ScrollIndex - wheelAmount)
5267 else
5268 scrollBar:ScrollTo(scrollBar.ScrollIndex - scrollBar.VisibleSpace)
5269 end
5270 end)
5271 PropertiesFrame.MouseWheelBackward:connect(function()
5272 if scrollBar.VisibleSpace - 1 > wheelAmount then
5273 scrollBar:ScrollTo(scrollBar.ScrollIndex + wheelAmount)
5274 else
5275 scrollBar:ScrollTo(scrollBar.ScrollIndex + scrollBar.VisibleSpace)
5276 end
5277 end)
5278end
5279
5280scrollBar.VisibleSpace = math.ceil(MainFrame.AbsoluteSize.y)
5281scrollBar:Update()
5282
5283showProperties(GetSelection())
5284
5285bindSelectionChanged.Event:connect(function()
5286 showProperties(GetSelection())
5287end)
5288
5289bindSetAwait.Event:connect(function(obj)
5290 if AwaitingObjectValue then
5291 AwaitingObjectValue = false
5292 local mySel = obj
5293 if mySel then
5294 pcall(function()
5295 Set(AwaitingObjectObj, AwaitingObjectProp, mySel)
5296 end)
5297 end
5298 end
5299end)
5300
5301propertiesSearch.Changed:connect(function(prop)
5302 if prop == "Text" then
5303 showProperties(GetSelection())
5304 end
5305end)
5306
5307bindGetApi.OnInvoke = function()
5308 return RbxApi
5309end
5310
5311bindGetAwait.OnInvoke = function()
5312 return AwaitingObjectValue
5313end
5314end)