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