· 9 years ago · Jan 31, 2017, 09:36 PM
1local GUI = Instance.new('ScreenGui');
2GUI.Parent = game:GetService('CoreGui');
3
4-- initial states
5local Option = {
6 -- can modify object parents in the hierarchy
7 Modifiable = false;
8 -- can select objects
9 Selectable = true;
10}
11
12-- MERELY
13
14Option.Modifiable = true
15
16-- END MERELY
17
18-- general size of GUI objects, in pixels
19local GUI_SIZE = 16
20-- padding between items within each entry
21local ENTRY_PADDING = 1
22-- padding between each entry
23local ENTRY_MARGIN = 1
24
25local Input = game:GetService("UserInputService")
26local HoldingCtrl = false
27local HoldingShift = false
28
29--[[
30
31# Explorer Panel
32
33A GUI panel that displays the game hierarchy.
34
35
36## Selection Bindables
37
38- `Function GetSelection ( )`
39
40 Returns an array of objects representing the objects currently
41 selected in the panel.
42
43- `Function SetSelection ( Objects selection )`
44
45 Sets the objects that are selected in the panel. `selection` is an array
46 of objects.
47
48- `Event SelectionChanged ( )`
49
50 Fired after the selection changes.
51
52
53## Option Bindables
54
55- `Function GetOption ( string optionName )`
56
57 If `optionName` is given, returns the value of that option. Otherwise,
58 returns a table of options and their current values.
59
60- `Function SetOption ( string optionName, bool value )`
61
62 Sets `optionName` to `value`.
63
64 Options:
65
66 - Modifiable
67
68 Whether objects can be modified by the panel.
69
70 Note that modifying objects depends on being able to select them. If
71 Selectable is false, then Actions will not be available. Reparenting
72 is still possible, but only for the dragged object.
73
74 - Selectable
75
76 Whether objects can be selected.
77
78 If Modifiable is false, then left-clicking will perform a drag
79 selection.
80
81## Updates
82
83- 2013-09-18
84 - Fixed explorer icons to match studio explorer.
85
86- 2013-09-14
87 - Added GetOption and SetOption bindables.
88 - Option: Modifiable; sets whether objects can be modified by the panel.
89 - Option: Selectable; sets whether objects can be selected.
90 - Slight modification to left-click selection behavior.
91 - Improved layout and scaling.
92
93- 2013-09-13
94 - Added drag to reparent objects.
95 - Left-click to select/deselect object.
96 - Left-click and drag unselected object to reparent single object.
97 - Left-click and drag selected object to move reparent entire selection.
98 - Right-click while dragging to cancel.
99
100- 2013-09-11
101 - Added explorer panel header with actions.
102 - Added Cut action.
103 - Added Copy action.
104 - Added Paste action.
105 - Added Delete action.
106 - Added drag selection.
107 - Left-click: Add to selection on drag.
108 - Right-click: Add to or remove from selection on drag.
109 - Ensured SelectionChanged fires only when the selection actually changes.
110 - Added documentation and change log.
111 - Fixed thread issue.
112
113- 2013-09-09
114 - Added basic multi-selection.
115 - Left-click to set selection.
116 - Right-click to add to or remove from selection.
117 - Removed "Selection" ObjectValue.
118 - Added GetSelection BindableFunction.
119 - Added SetSelection BindableFunction.
120 - Added SelectionChanged BindableEvent.
121 - Changed font to SourceSans.
122
123- 2013-08-31
124 - Improved GUI sizing based off of `GUI_SIZE` constant.
125 - Automatic font size detection.
126
127- 2013-08-27
128 - Initial explorer panel.
129
130
131## Todo
132
133- Sorting
134 - by ExplorerOrder
135 - by children
136 - by name
137- Drag objects to reparent
138
139]]
140
141local ENTRY_SIZE = GUI_SIZE + ENTRY_PADDING*2
142local ENTRY_BOUND = ENTRY_SIZE + ENTRY_MARGIN
143local HEADER_SIZE = ENTRY_SIZE*2
144
145local FONT = 'SourceSans'
146local FONT_SIZE do
147 local size = {8,9,10,11,12,14,18,24,36,48}
148 local s
149 local n = math.huge
150 for i = 1,#size do
151 if size[i] <= GUI_SIZE then
152 FONT_SIZE = i - 1
153 end
154 end
155end
156
157local GuiColor = {
158 Background = Color3.new(233/255, 233/255, 233/255);
159 Border = Color3.new(149/255, 149/255, 149/255);
160 Selected = Color3.new( 96/255, 140/255, 211/255);
161 BorderSelected = Color3.new( 86/255, 125/255, 188/255);
162 Text = Color3.new( 0/255, 0/255, 0/255);
163 TextDisabled = Color3.new(128/255, 128/255, 128/255);
164 TextSelected = Color3.new(255/255, 255/255, 255/255);
165 Button = Color3.new(221/255, 221/255, 221/255);
166 ButtonBorder = Color3.new(149/255, 149/255, 149/255);
167 ButtonSelected = Color3.new(255/255, 0/255, 0/255);
168 Field = Color3.new(255/255, 255/255, 255/255);
169 FieldBorder = Color3.new(191/255, 191/255, 191/255);
170 TitleBackground = Color3.new(178/255, 178/255, 178/255);
171}
172
173----------------------------------------------------------------
174----------------------------------------------------------------
175----------------------------------------------------------------
176----------------------------------------------------------------
177---- Icon map constants
178
179local MAP_ID = 483448923
180
181-- Indices based on implementation of Icon function.
182local ACTION_CUT = 160
183local ACTION_COPY = 161
184local ACTION_PASTE = 162
185local ACTION_DELETE = 163
186local ACTION_SORT = 164
187local ACTION_CUT_OVER = 174
188local ACTION_COPY_OVER = 175
189local ACTION_PASTE_OVER = 176
190local ACTION_DELETE_OVER = 177
191local ACTION_SORT_OVER = 178
192local ACTION_EDITQUICKACCESS = 190
193local ACTION_FREEZE = 188
194local ACTION_STARRED = 189
195local ACTION_ADDSTAR = 184
196local ACTION_ADDSTAR_OVER = 187
197
198local NODE_COLLAPSED = 165
199local NODE_EXPANDED = 166
200local NODE_COLLAPSED_OVER = 179
201local NODE_EXPANDED_OVER = 180
202
203local ExplorerIndex = {
204 ["Accessory"] = 32;
205 ["Accoutrement"] = 32;
206 ["AdService"] = 73;
207 ["Animation"] = 60;
208 ["AnimationController"] = 60;
209 ["AnimationTrack"] = 60;
210 ["Animator"] = 60;
211 ["ArcHandles"] = 56;
212 ["AssetService"] = 72;
213 ["Attachment"] = 34;
214 ["Backpack"] = 20;
215 ["BadgeService"] = 75;
216 ["BallSocketConstraint"] = 89;
217 ["BillboardGui"] = 64;
218 ["BinaryStringValue"] = 4;
219 ["BindableEvent"] = 67;
220 ["BindableFunction"] = 66;
221 ["BlockMesh"] = 8;
222 ["BloomEffect"] = 90;
223 ["BlurEffect"] = 90;
224 ["BodyAngularVelocity"] = 14;
225 ["BodyForce"] = 14;
226 ["BodyGyro"] = 14;
227 ["BodyPosition"] = 14;
228 ["BodyThrust"] = 14;
229 ["BodyVelocity"] = 14;
230 ["BoolValue"] = 4;
231 ["BoxHandleAdornment"] = 54;
232 ["BrickColorValue"] = 4;
233 ["Camera"] = 5;
234 ["CFrameValue"] = 4;
235 ["CharacterMesh"] = 60;
236 ["Chat"] = 33;
237 ["ClickDetector"] = 41;
238 ["CollectionService"] = 30;
239 ["Color3Value"] = 4;
240 ["ColorCorrectionEffect"] = 90;
241 ["ConeHandleAdornment"] = 54;
242 ["Configuration"] = 58;
243 ["ContentProvider"] = 72;
244 ["ContextActionService"] = 41;
245 ["CoreGui"] = 46;
246 ["CoreScript"] = 18;
247 ["CornerWedgePart"] = 1;
248 ["CustomEvent"] = 4;
249 ["CustomEventReceiver"] = 4;
250 ["CylinderHandleAdornment"] = 54;
251 ["CylinderMesh"] = 8;
252 ["CylindricalConstraint"] = 89;
253 ["Debris"] = 30;
254 ["Decal"] = 7;
255 ["Dialog"] = 62;
256 ["DialogChoice"] = 63;
257 ["DoubleConstrainedValue"] = 4;
258 ["Explosion"] = 36;
259 ["FileMesh"] = 8;
260 ["Fire"] = 61;
261 ["Flag"] = 38;
262 ["FlagStand"] = 39;
263 ["FloorWire"] = 4;
264 ["Folder"] = 70;
265 ["ForceField"] = 37;
266 ["Frame"] = 48;
267 ["GamePassService"] = 19;
268 ["Glue"] = 34;
269 ["GuiButton"] = 52;
270 ["GuiMain"] = 47;
271 ["GuiService"] = 47;
272 ["Handles"] = 53;
273 ["HapticService"] = 84;
274 ["Hat"] = 45;
275 ["HingeConstraint"] = 89;
276 ["Hint"] = 33;
277 ["HopperBin"] = 22;
278 ["HttpService"] = 76;
279 ["Humanoid"] = 9;
280 ["ImageButton"] = 52;
281 ["ImageLabel"] = 49;
282 ["InsertService"] = 72;
283 ["IntConstrainedValue"] = 4;
284 ["IntValue"] = 4;
285 ["JointInstance"] = 34;
286 ["JointsService"] = 34;
287 ["Keyframe"] = 60;
288 ["KeyframeSequence"] = 60;
289 ["KeyframeSequenceProvider"] = 60;
290 ["Lighting"] = 13;
291 ["LineHandleAdornment"] = 54;
292 ["LocalScript"] = 18;
293 ["LogService"] = 87;
294 ["MarketplaceService"] = 46;
295 ["Message"] = 33;
296 ["Model"] = 2;
297 ["ModuleScript"] = 71;
298 ["Motor"] = 34;
299 ["Motor6D"] = 34;
300 ["MoveToConstraint"] = 89;
301 ["NegateOperation"] = 78;
302 ["NetworkClient"] = 16;
303 ["NetworkReplicator"] = 29;
304 ["NetworkServer"] = 15;
305 ["NumberValue"] = 4;
306 ["ObjectValue"] = 4;
307 ["Pants"] = 44;
308 ["ParallelRampPart"] = 1;
309 ["Part"] = 1;
310 ["ParticleEmitter"] = 69;
311 ["PartPairLasso"] = 57;
312 ["PathfindingService"] = 37;
313 ["Platform"] = 35;
314 ["Player"] = 12;
315 ["PlayerGui"] = 46;
316 ["Players"] = 21;
317 ["PlayerScripts"] = 82;
318 ["PointLight"] = 13;
319 ["PointsService"] = 83;
320 ["Pose"] = 60;
321 ["PrismaticConstraint"] = 89;
322 ["PrismPart"] = 1;
323 ["PyramidPart"] = 1;
324 ["RayValue"] = 4;
325 ["ReflectionMetadata"] = 86;
326 ["ReflectionMetadataCallbacks"] = 86;
327 ["ReflectionMetadataClass"] = 86;
328 ["ReflectionMetadataClasses"] = 86;
329 ["ReflectionMetadataEnum"] = 86;
330 ["ReflectionMetadataEnumItem"] = 86;
331 ["ReflectionMetadataEnums"] = 86;
332 ["ReflectionMetadataEvents"] = 86;
333 ["ReflectionMetadataFunctions"] = 86;
334 ["ReflectionMetadataMember"] = 86;
335 ["ReflectionMetadataProperties"] = 86;
336 ["ReflectionMetadataYieldFunctions"] = 86;
337 ["RemoteEvent"] = 80;
338 ["RemoteFunction"] = 79;
339 ["ReplicatedFirst"] = 72;
340 ["ReplicatedStorage"] = 72;
341 ["RightAngleRampPart"] = 1;
342 ["RocketPropulsion"] = 14;
343 ["RodConstraint"] = 89;
344 ["RopeConstraint"] = 89;
345 ["Rotate"] = 34;
346 ["RotateP"] = 34;
347 ["RotateV"] = 34;
348 ["RunService"] = 66;
349 ["ScreenGui"] = 47;
350 ["Script"] = 6;
351 ["ScrollingFrame"] = 48;
352 ["Seat"] = 35;
353 ["Selection"] = 55;
354 ["SelectionBox"] = 54;
355 ["SelectionPartLasso"] = 57;
356 ["SelectionPointLasso"] = 57;
357 ["SelectionSphere"] = 54;
358 ["ServerScriptService"] = 0;
359 ["ServerStorage"] = 74;
360 ["Shirt"] = 43;
361 ["ShirtGraphic"] = 40;
362 ["SkateboardPlatform"] = 35;
363 ["Sky"] = 28;
364 ["SlidingBallConstraint"] = 89;
365 ["Smoke"] = 59;
366 ["Snap"] = 34;
367 ["Sound"] = 11;
368 ["SoundService"] = 31;
369 ["Sparkles"] = 42;
370 ["SpawnLocation"] = 25;
371 ["SpecialMesh"] = 8;
372 ["SphereHandleAdornment"] = 54;
373 ["SpotLight"] = 13;
374 ["SpringConstraint"] = 89;
375 ["StarterCharacterScripts"] = 82;
376 ["StarterGear"] = 20;
377 ["StarterGui"] = 46;
378 ["StarterPack"] = 20;
379 ["StarterPlayer"] = 88;
380 ["StarterPlayerScripts"] = 82;
381 ["Status"] = 2;
382 ["StringValue"] = 4;
383 ["SunRaysEffect"] = 90;
384 ["SurfaceGui"] = 64;
385 ["SurfaceLight"] = 13;
386 ["SurfaceSelection"] = 55;
387 ["Team"] = 24;
388 ["Teams"] = 23;
389 ["TeleportService"] = 81;
390 ["Terrain"] = 65;
391 ["TerrainRegion"] = 65;
392 ["TestService"] = 68;
393 ["TextBox"] = 51;
394 ["TextButton"] = 51;
395 ["TextLabel"] = 50;
396 ["Texture"] = 10;
397 ["TextureTrail"] = 4;
398 ["Tool"] = 17;
399 ["TouchTransmitter"] = 37;
400 ["TrussPart"] = 1;
401 ["UnionOperation"] = 77;
402 ["UserInputService"] = 84;
403 ["Vector3Value"] = 4;
404 ["VehicleSeat"] = 35;
405 ["VelocityMotor"] = 34;
406 ["WedgePart"] = 1;
407 ["Weld"] = 34;
408 ["Workspace"] = 19;
409}
410
411----------------------------------------------------------------
412----------------------------------------------------------------
413----------------------------------------------------------------
414----------------------------------------------------------------
415----------------------------------------------------------------
416
417function Create(ty,data)
418 local obj
419 if type(ty) == 'string' then
420 obj = Instance.new(ty)
421 else
422 obj = ty
423 end
424 for k, v in pairs(data) do
425 if type(k) == 'number' then
426 v.Parent = obj
427 else
428 obj[k] = v
429 end
430 end
431 return obj
432end
433
434local barActive = false
435local activeOptions = {}
436
437function createDDown(dBut, callback,...)
438 if barActive then
439 for i,v in pairs(activeOptions) do
440 v:Destroy()
441 end
442 activeOptions = {}
443 barActive = false
444 return
445 else
446 barActive = true
447 end
448 local slots = {...}
449 local base = dBut
450 for i,v in pairs(slots) do
451 local newOption = base:Clone()
452 newOption.ZIndex = 5
453 newOption.Name = "Option "..tostring(i)
454 newOption.Parent = base.Parent.Parent.Parent
455 newOption.BackgroundTransparency = 0
456 newOption.ZIndex = 2
457 table.insert(activeOptions,newOption)
458 newOption.Position = UDim2.new(-0.4, dBut.Position.X.Offset, dBut.Position.Y.Scale, dBut.Position.Y.Offset + (#activeOptions * dBut.Size.Y.Offset))
459 newOption.Text = slots[i]
460 newOption.MouseButton1Down:connect(function()
461 dBut.Text = slots[i]
462 callback(slots[i])
463 for i,v in pairs(activeOptions) do
464 v:Destroy()
465 end
466 activeOptions = {}
467 barActive = false
468 end)
469 end
470end
471
472-- Connects a function to an event such that it fires asynchronously
473function Connect(event,func)
474 return event:connect(function(...)
475 local a = {...}
476 spawn(function() func(unpack(a)) end)
477 end)
478end
479
480-- returns the ascendant ScreenGui of an object
481function GetScreen(screen)
482 if screen == nil then return nil end
483 while not screen:IsA("ScreenGui") do
484 screen = screen.Parent
485 if screen == nil then return nil end
486 end
487 return screen
488end
489
490do
491 local ZIndexLock = {}
492 -- Sets the ZIndex of an object and its descendants. Objects are locked so
493 -- that SetZIndexOnChanged doesn't spawn multiple threads that set the
494 -- ZIndex of the same object.
495 function SetZIndex(object,z)
496 if not ZIndexLock[object] then
497 ZIndexLock[object] = true
498 if object:IsA'GuiObject' then
499 object.ZIndex = z
500 end
501 local children = object:GetChildren()
502 for i = 1,#children do
503 SetZIndex(children[i],z)
504 end
505 ZIndexLock[object] = nil
506 end
507 end
508
509 function SetZIndexOnChanged(object)
510 return object.Changed:connect(function(p)
511 if p == "ZIndex" then
512 SetZIndex(object,object.ZIndex)
513 end
514 end)
515 end
516end
517
518---- IconMap ----
519-- Image size: 256px x 256px
520-- Icon size: 16px x 16px
521-- Padding between each icon: 2px
522-- Padding around image edge: 1px
523-- Total icons: 14 x 14 (196)
524local Icon do
525 local iconMap = 'http://www.roblox.com/asset/?id=' .. MAP_ID
526 game:GetService('ContentProvider'):Preload(iconMap)
527 local iconDehash do
528 -- 14 x 14, 0-based input, 0-based output
529 local f=math.floor
530 function iconDehash(h)
531 return f(h/14%14),f(h%14)
532 end
533 end
534
535 function Icon(IconFrame,index)
536 local row,col = iconDehash(index)
537 local mapSize = Vector2.new(256,256)
538 local pad,border = 2,1
539 local iconSize = 16
540
541 local class = 'Frame'
542 if type(IconFrame) == 'string' then
543 class = IconFrame
544 IconFrame = nil
545 end
546
547 if not IconFrame then
548 IconFrame = Create(class,{
549 Name = "Icon";
550 BackgroundTransparency = 1;
551 ClipsDescendants = true;
552 Create('ImageLabel',{
553 Name = "IconMap";
554 Active = false;
555 BackgroundTransparency = 1;
556 Image = iconMap;
557 Size = UDim2.new(mapSize.x/iconSize,0,mapSize.y/iconSize,0);
558 });
559 })
560 end
561
562 IconFrame.IconMap.Position = UDim2.new(-col - (pad*(col+1) + border)/iconSize,0,-row - (pad*(row+1) + border)/iconSize,0)
563 return IconFrame
564 end
565end
566
567----------------------------------------------------------------
568----------------------------------------------------------------
569----------------------------------------------------------------
570----------------------------------------------------------------
571---- ScrollBar
572do
573 -- AutoButtonColor doesn't always reset properly
574 local function ResetButtonColor(button)
575 local active = button.Active
576 button.Active = not active
577 button.Active = active
578 end
579
580 local function ArrowGraphic(size,dir,scaled,template)
581 local Frame = Create('Frame',{
582 Name = "Arrow Graphic";
583 BorderSizePixel = 0;
584 Size = UDim2.new(0,size,0,size);
585 Transparency = 1;
586 })
587 if not template then
588 template = Instance.new("Frame")
589 template.BorderSizePixel = 0
590 end
591
592 local transform
593 if dir == nil or dir == 'Up' then
594 function transform(p,s) return p,s end
595 elseif dir == 'Down' then
596 function transform(p,s) return UDim2.new(0,p.X.Offset,0,size-p.Y.Offset-1),s end
597 elseif dir == 'Left' then
598 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
599 elseif dir == 'Right' then
600 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
601 end
602
603 local scale
604 if scaled then
605 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
606 else
607 function scale(p,s) return p,s end
608 end
609
610 local o = math.floor(size/4)
611 if size%2 == 0 then
612 local n = size/2-1
613 for i = 0,n do
614 local t = template:Clone()
615 local p,s = scale(transform(
616 UDim2.new(0,n-i,0,o+i),
617 UDim2.new(0,(i+1)*2,0,1)
618 ))
619 t.Position = p
620 t.Size = s
621 t.Parent = Frame
622 end
623 else
624 local n = (size-1)/2
625 for i = 0,n do
626 local t = template:Clone()
627 local p,s = scale(transform(
628 UDim2.new(0,n-i,0,o+i),
629 UDim2.new(0,i*2+1,0,1)
630 ))
631 t.Position = p
632 t.Size = s
633 t.Parent = Frame
634 end
635 end
636 if size%4 > 1 then
637 local t = template:Clone()
638 local p,s = scale(transform(
639 UDim2.new(0,0,0,size-o-1),
640 UDim2.new(0,size,0,1)
641 ))
642 t.Position = p
643 t.Size = s
644 t.Parent = Frame
645 end
646 return Frame
647 end
648
649
650 local function GripGraphic(size,dir,spacing,scaled,template)
651 local Frame = Create('Frame',{
652 Name = "Grip Graphic";
653 BorderSizePixel = 0;
654 Size = UDim2.new(0,size.x,0,size.y);
655 Transparency = 1;
656 })
657 if not template then
658 template = Instance.new("Frame")
659 template.BorderSizePixel = 0
660 end
661
662 spacing = spacing or 2
663
664 local scale
665 if scaled then
666 function scale(p) return UDim2.new(p.X.Offset/size.x,0,p.Y.Offset/size.y,0) end
667 else
668 function scale(p) return p end
669 end
670
671 if dir == 'Vertical' then
672 for i=0,size.x-1,spacing do
673 local t = template:Clone()
674 t.Size = scale(UDim2.new(0,1,0,size.y))
675 t.Position = scale(UDim2.new(0,i,0,0))
676 t.Parent = Frame
677 end
678 elseif dir == nil or dir == 'Horizontal' then
679 for i=0,size.y-1,spacing do
680 local t = template:Clone()
681 t.Size = scale(UDim2.new(0,size.x,0,1))
682 t.Position = scale(UDim2.new(0,0,0,i))
683 t.Parent = Frame
684 end
685 end
686
687 return Frame
688 end
689
690 local mt = {
691 __index = {
692 GetScrollPercent = function(self)
693 return self.ScrollIndex/(self.TotalSpace-self.VisibleSpace)
694 end;
695 CanScrollDown = function(self)
696 return self.ScrollIndex + self.VisibleSpace < self.TotalSpace
697 end;
698 CanScrollUp = function(self)
699 return self.ScrollIndex > 0
700 end;
701 ScrollDown = function(self)
702 self.ScrollIndex = self.ScrollIndex + self.PageIncrement
703 self:Update()
704 end;
705 ScrollUp = function(self)
706 self.ScrollIndex = self.ScrollIndex - self.PageIncrement
707 self:Update()
708 end;
709 ScrollTo = function(self,index)
710 self.ScrollIndex = index
711 self:Update()
712 end;
713 SetScrollPercent = function(self,percent)
714 self.ScrollIndex = math.floor((self.TotalSpace - self.VisibleSpace)*percent + 0.5)
715 self:Update()
716 end;
717 };
718 }
719 mt.__index.CanScrollRight = mt.__index.CanScrollDown
720 mt.__index.CanScrollLeft = mt.__index.CanScrollUp
721 mt.__index.ScrollLeft = mt.__index.ScrollUp
722 mt.__index.ScrollRight = mt.__index.ScrollDown
723
724 function ScrollBar(horizontal)
725 -- create row scroll bar
726 local ScrollFrame = Create('Frame',{
727 Name = "ScrollFrame";
728 Position = horizontal and UDim2.new(0,0,1,-GUI_SIZE) or UDim2.new(1,-GUI_SIZE,0,0);
729 Size = horizontal and UDim2.new(1,0,0,GUI_SIZE) or UDim2.new(0,GUI_SIZE,1,0);
730 BackgroundTransparency = 1;
731 Create('ImageButton',{
732 Name = "ScrollDown";
733 Position = horizontal and UDim2.new(1,-GUI_SIZE,0,0) or UDim2.new(0,0,1,-GUI_SIZE);
734 Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
735 BackgroundColor3 = GuiColor.Button;
736 BorderColor3 = GuiColor.Border;
737 --BorderSizePixel = 0;
738 });
739 Create('ImageButton',{
740 Name = "ScrollUp";
741 Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
742 BackgroundColor3 = GuiColor.Button;
743 BorderColor3 = GuiColor.Border;
744 --BorderSizePixel = 0;
745 });
746 Create('ImageButton',{
747 Name = "ScrollBar";
748 Size = horizontal and UDim2.new(1,-GUI_SIZE*2,1,0) or UDim2.new(1,0,1,-GUI_SIZE*2);
749 Position = horizontal and UDim2.new(0,GUI_SIZE,0,0) or UDim2.new(0,0,0,GUI_SIZE);
750 AutoButtonColor = false;
751 BackgroundColor3 = Color3.new(0.94902, 0.94902, 0.94902);
752 BorderColor3 = GuiColor.Border;
753 --BorderSizePixel = 0;
754 Create('ImageButton',{
755 Name = "ScrollThumb";
756 AutoButtonColor = false;
757 Size = UDim2.new(0, GUI_SIZE, 0, GUI_SIZE);
758 BackgroundColor3 = GuiColor.Button;
759 BorderColor3 = GuiColor.Border;
760 --BorderSizePixel = 0;
761 });
762 });
763 })
764
765 local graphicTemplate = Create('Frame',{
766 Name="Graphic";
767 BorderSizePixel = 0;
768 BackgroundColor3 = GuiColor.Border;
769 })
770 local graphicSize = GUI_SIZE/2
771
772 local ScrollDownFrame = ScrollFrame.ScrollDown
773 local ScrollDownGraphic = ArrowGraphic(graphicSize,horizontal and 'Right' or 'Down',true,graphicTemplate)
774 ScrollDownGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
775 ScrollDownGraphic.Parent = ScrollDownFrame
776 local ScrollUpFrame = ScrollFrame.ScrollUp
777 local ScrollUpGraphic = ArrowGraphic(graphicSize,horizontal and 'Left' or 'Up',true,graphicTemplate)
778 ScrollUpGraphic.Position = UDim2.new(0.5,-graphicSize/2,0.5,-graphicSize/2)
779 ScrollUpGraphic.Parent = ScrollUpFrame
780 local ScrollBarFrame = ScrollFrame.ScrollBar
781 local ScrollThumbFrame = ScrollBarFrame.ScrollThumb
782 do
783 local size = GUI_SIZE*3/8
784 local Decal = GripGraphic(Vector2.new(size,size),horizontal and 'Vertical' or 'Horizontal',2,graphicTemplate)
785 Decal.Position = UDim2.new(0.5,-size/2,0.5,-size/2)
786 Decal.Parent = ScrollThumbFrame
787 end
788
789 local Class = setmetatable({
790 GUI = ScrollFrame;
791 ScrollIndex = 0;
792 VisibleSpace = 0;
793 TotalSpace = 0;
794 PageIncrement = 1;
795 },mt)
796
797 local UpdateScrollThumb
798 if horizontal then
799 function UpdateScrollThumb()
800 ScrollThumbFrame.Size = UDim2.new(Class.VisibleSpace/Class.TotalSpace,0,0,GUI_SIZE)
801 if ScrollThumbFrame.AbsoluteSize.x < GUI_SIZE then
802 ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE)
803 end
804 local barSize = ScrollBarFrame.AbsoluteSize.x
805 ScrollThumbFrame.Position = UDim2.new(Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.x)/barSize,0,0,0)
806 end
807 else
808 function UpdateScrollThumb()
809 ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,Class.VisibleSpace/Class.TotalSpace,0)
810 if ScrollThumbFrame.AbsoluteSize.y < GUI_SIZE then
811 ScrollThumbFrame.Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE)
812 end
813 local barSize = ScrollBarFrame.AbsoluteSize.y
814 ScrollThumbFrame.Position = UDim2.new(0,0,Class:GetScrollPercent()*(barSize - ScrollThumbFrame.AbsoluteSize.y)/barSize,0)
815 end
816 end
817
818 local lastDown
819 local lastUp
820 local scrollStyle = {BackgroundColor3=GuiColor.Border,BackgroundTransparency=0}
821 local scrollStyle_ds = {BackgroundColor3=GuiColor.Border,BackgroundTransparency=0.7}
822
823 local function Update()
824 local t = Class.TotalSpace
825 local v = Class.VisibleSpace
826 local s = Class.ScrollIndex
827 if v <= t then
828 if s > 0 then
829 if s + v > t then
830 Class.ScrollIndex = t - v
831 end
832 else
833 Class.ScrollIndex = 0
834 end
835 else
836 Class.ScrollIndex = 0
837 end
838
839 if Class.UpdateCallback then
840 if Class.UpdateCallback(Class) == false then
841 return
842 end
843 end
844
845 local down = Class:CanScrollDown()
846 local up = Class:CanScrollUp()
847 if down ~= lastDown then
848 lastDown = down
849 ScrollDownFrame.Active = down
850 ScrollDownFrame.AutoButtonColor = down
851 local children = ScrollDownGraphic:GetChildren()
852 local style = down and scrollStyle or scrollStyle_ds
853 for i = 1,#children do
854 Create(children[i],style)
855 end
856 end
857 if up ~= lastUp then
858 lastUp = up
859 ScrollUpFrame.Active = up
860 ScrollUpFrame.AutoButtonColor = up
861 local children = ScrollUpGraphic:GetChildren()
862 local style = up and scrollStyle or scrollStyle_ds
863 for i = 1,#children do
864 Create(children[i],style)
865 end
866 end
867 ScrollThumbFrame.Visible = down or up
868 UpdateScrollThumb()
869 end
870 Class.Update = Update
871
872 SetZIndexOnChanged(ScrollFrame)
873
874 local MouseDrag = Create('ImageButton',{
875 Name = "MouseDrag";
876 Position = UDim2.new(-0.25,0,-0.25,0);
877 Size = UDim2.new(1.5,0,1.5,0);
878 Transparency = 1;
879 AutoButtonColor = false;
880 Active = true;
881 ZIndex = 10;
882 })
883
884 local scrollEventID = 0
885 ScrollDownFrame.MouseButton1Down:connect(function()
886 scrollEventID = tick()
887 local current = scrollEventID
888 local up_con
889 up_con = MouseDrag.MouseButton1Up:connect(function()
890 scrollEventID = tick()
891 MouseDrag.Parent = nil
892 ResetButtonColor(ScrollDownFrame)
893 up_con:disconnect(); drag = nil
894 end)
895 MouseDrag.Parent = GetScreen(ScrollFrame)
896 Class:ScrollDown()
897 wait(0.2) -- delay before auto scroll
898 while scrollEventID == current do
899 Class:ScrollDown()
900 if not Class:CanScrollDown() then break end
901 wait()
902 end
903 end)
904
905 ScrollDownFrame.MouseButton1Up:connect(function()
906 scrollEventID = tick()
907 end)
908
909 ScrollUpFrame.MouseButton1Down:connect(function()
910 scrollEventID = tick()
911 local current = scrollEventID
912 local up_con
913 up_con = MouseDrag.MouseButton1Up:connect(function()
914 scrollEventID = tick()
915 MouseDrag.Parent = nil
916 ResetButtonColor(ScrollUpFrame)
917 up_con:disconnect(); drag = nil
918 end)
919 MouseDrag.Parent = GetScreen(ScrollFrame)
920 Class:ScrollUp()
921 wait(0.2)
922 while scrollEventID == current do
923 Class:ScrollUp()
924 if not Class:CanScrollUp() then break end
925 wait()
926 end
927 end)
928
929 ScrollUpFrame.MouseButton1Up:connect(function()
930 scrollEventID = tick()
931 end)
932
933 if horizontal then
934 ScrollBarFrame.MouseButton1Down:connect(function(x,y)
935 scrollEventID = tick()
936 local current = scrollEventID
937 local up_con
938 up_con = MouseDrag.MouseButton1Up:connect(function()
939 scrollEventID = tick()
940 MouseDrag.Parent = nil
941 ResetButtonColor(ScrollUpFrame)
942 up_con:disconnect(); drag = nil
943 end)
944 MouseDrag.Parent = GetScreen(ScrollFrame)
945 if x > ScrollThumbFrame.AbsolutePosition.x then
946 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
947 wait(0.2)
948 while scrollEventID == current do
949 if x < ScrollThumbFrame.AbsolutePosition.x + ScrollThumbFrame.AbsoluteSize.x then break end
950 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
951 wait()
952 end
953 else
954 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
955 wait(0.2)
956 while scrollEventID == current do
957 if x > ScrollThumbFrame.AbsolutePosition.x then break end
958 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
959 wait()
960 end
961 end
962 end)
963 else
964 ScrollBarFrame.MouseButton1Down:connect(function(x,y)
965 scrollEventID = tick()
966 local current = scrollEventID
967 local up_con
968 up_con = MouseDrag.MouseButton1Up:connect(function()
969 scrollEventID = tick()
970 MouseDrag.Parent = nil
971 ResetButtonColor(ScrollUpFrame)
972 up_con:disconnect(); drag = nil
973 end)
974 MouseDrag.Parent = GetScreen(ScrollFrame)
975 if y > ScrollThumbFrame.AbsolutePosition.y then
976 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
977 wait(0.2)
978 while scrollEventID == current do
979 if y < ScrollThumbFrame.AbsolutePosition.y + ScrollThumbFrame.AbsoluteSize.y then break end
980 Class:ScrollTo(Class.ScrollIndex + Class.VisibleSpace)
981 wait()
982 end
983 else
984 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
985 wait(0.2)
986 while scrollEventID == current do
987 if y > ScrollThumbFrame.AbsolutePosition.y then break end
988 Class:ScrollTo(Class.ScrollIndex - Class.VisibleSpace)
989 wait()
990 end
991 end
992 end)
993 end
994
995 if horizontal then
996 ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
997 scrollEventID = tick()
998 local mouse_offset = x - ScrollThumbFrame.AbsolutePosition.x
999 local drag_con
1000 local up_con
1001 drag_con = MouseDrag.MouseMoved:connect(function(x,y)
1002 local bar_abs_pos = ScrollBarFrame.AbsolutePosition.x
1003 local bar_drag = ScrollBarFrame.AbsoluteSize.x - ScrollThumbFrame.AbsoluteSize.x
1004 local bar_abs_one = bar_abs_pos + bar_drag
1005 x = x - mouse_offset
1006 x = x < bar_abs_pos and bar_abs_pos or x > bar_abs_one and bar_abs_one or x
1007 x = x - bar_abs_pos
1008 Class:SetScrollPercent(x/(bar_drag))
1009 end)
1010 up_con = MouseDrag.MouseButton1Up:connect(function()
1011 scrollEventID = tick()
1012 MouseDrag.Parent = nil
1013 ResetButtonColor(ScrollThumbFrame)
1014 drag_con:disconnect(); drag_con = nil
1015 up_con:disconnect(); drag = nil
1016 end)
1017 MouseDrag.Parent = GetScreen(ScrollFrame)
1018 end)
1019 else
1020 ScrollThumbFrame.MouseButton1Down:connect(function(x,y)
1021 scrollEventID = tick()
1022 local mouse_offset = y - ScrollThumbFrame.AbsolutePosition.y
1023 local drag_con
1024 local up_con
1025 drag_con = MouseDrag.MouseMoved:connect(function(x,y)
1026 local bar_abs_pos = ScrollBarFrame.AbsolutePosition.y
1027 local bar_drag = ScrollBarFrame.AbsoluteSize.y - ScrollThumbFrame.AbsoluteSize.y
1028 local bar_abs_one = bar_abs_pos + bar_drag
1029 y = y - mouse_offset
1030 y = y < bar_abs_pos and bar_abs_pos or y > bar_abs_one and bar_abs_one or y
1031 y = y - bar_abs_pos
1032 Class:SetScrollPercent(y/(bar_drag))
1033 end)
1034 up_con = MouseDrag.MouseButton1Up:connect(function()
1035 scrollEventID = tick()
1036 MouseDrag.Parent = nil
1037 ResetButtonColor(ScrollThumbFrame)
1038 drag_con:disconnect(); drag_con = nil
1039 up_con:disconnect(); drag = nil
1040 end)
1041 MouseDrag.Parent = GetScreen(ScrollFrame)
1042 end)
1043 end
1044
1045 function Class:Destroy()
1046 ScrollFrame:Destroy()
1047 MouseDrag:Destroy()
1048 for k in pairs(Class) do
1049 Class[k] = nil
1050 end
1051 setmetatable(Class,nil)
1052 end
1053
1054 Update()
1055
1056 return Class
1057 end
1058end
1059
1060----------------------------------------------------------------
1061----------------------------------------------------------------
1062----------------------------------------------------------------
1063----------------------------------------------------------------
1064---- Explorer panel
1065
1066local explorerPanel = Instance.new('Frame')
1067explorerPanel.Parent = GUI;
1068explorerPanel.Name = 'ExplorerPanel';
1069Create(explorerPanel,{
1070 BackgroundColor3 = GuiColor.Field;
1071 BorderColor3 = GuiColor.Border;
1072 Active = true;
1073})
1074
1075local SettingsRemote = explorerPanel.Parent:WaitForChild("SettingsPanel"):WaitForChild("GetSetting")
1076local GetApiRemote = explorerPanel.Parent:WaitForChild("PropertiesFrame"):WaitForChild("GetApi")
1077local GetAwaitRemote = explorerPanel.Parent:WaitForChild("PropertiesFrame"):WaitForChild("GetAwaiting")
1078local bindSetAwaiting = explorerPanel.Parent:WaitForChild("PropertiesFrame"):WaitForChild("SetAwaiting")
1079
1080local SaveInstanceWindow = explorerPanel.Parent:WaitForChild("SaveInstance")
1081local ConfirmationWindow = explorerPanel.Parent:WaitForChild("Confirmation")
1082local CautionWindow = explorerPanel.Parent:WaitForChild("Caution")
1083local TableCautionWindow = explorerPanel.Parent:WaitForChild("TableCaution")
1084
1085local RemoteWindow = explorerPanel.Parent:WaitForChild("CallRemote")
1086
1087local ScriptEditor = explorerPanel.Parent:WaitForChild("ScriptEditor")
1088local ScriptEditorEvent = ScriptEditor:WaitForChild("OpenScript")
1089
1090local CurrentSaveInstanceWindow
1091local CurrentRemoteWindow
1092
1093local lastSelectedNode
1094
1095local DexStorage
1096local DexStorageMain
1097local DexStorageEnabled
1098
1099if saveinstance then DexStorageEnabled = true end
1100
1101if DexStorageEnabled then
1102 DexStorage = Instance.new("Folder")
1103 DexStorage.Name = "Dex"
1104 DexStorageMain = Instance.new("Folder",DexStorage)
1105 DexStorageMain.Name = "DexStorage"
1106end
1107
1108local NilStorage
1109local NilStorageMain
1110local NilStorageEnabled
1111
1112if get_nil_instances and IfThisFunctionWasStableEnough then NilStorageEnabled = true end
1113
1114if NilStorageEnabled then
1115 NilStorage = Instance.new("Folder")
1116 NilStorage.Name = "Dex Internal Storage"
1117 NilStorageMain = Instance.new("Folder",NilStorage)
1118 NilStorageMain.Name = "Nil Instances"
1119end
1120
1121local listFrame = Create('Frame',{
1122 Name = "List";
1123 BackgroundTransparency = 1;
1124 ClipsDescendants = true;
1125 Position = UDim2.new(0,0,0,HEADER_SIZE);
1126 Size = UDim2.new(1,-GUI_SIZE,1,-HEADER_SIZE);
1127 Parent = explorerPanel;
1128})
1129
1130local scrollBar = ScrollBar(false)
1131scrollBar.PageIncrement = 1
1132Create(scrollBar.GUI,{
1133 Position = UDim2.new(1,-GUI_SIZE,0,HEADER_SIZE);
1134 Size = UDim2.new(0,GUI_SIZE,1,-HEADER_SIZE);
1135 Parent = explorerPanel;
1136})
1137
1138local scrollBarH = ScrollBar(true)
1139scrollBarH.PageIncrement = GUI_SIZE
1140Create(scrollBarH.GUI,{
1141 Position = UDim2.new(0,0,1,-GUI_SIZE);
1142 Size = UDim2.new(1,-GUI_SIZE,0,GUI_SIZE);
1143 Visible = false;
1144 Parent = explorerPanel;
1145})
1146
1147local headerFrame = Create('Frame',{
1148 Name = "Header";
1149 BackgroundColor3 = GuiColor.Background;
1150 BorderColor3 = GuiColor.Border;
1151 Position = UDim2.new(0,0,0,0);
1152 Size = UDim2.new(1,0,0,HEADER_SIZE);
1153 Parent = explorerPanel;
1154 Create('TextLabel',{
1155 Text = "Explorer";
1156 BackgroundTransparency = 1;
1157 TextColor3 = GuiColor.Text;
1158 TextXAlignment = 'Left';
1159 Font = FONT;
1160 FontSize = FONT_SIZE;
1161 Position = UDim2.new(0,4,0,0);
1162 Size = UDim2.new(1,-4,0.5,0);
1163 });
1164})
1165
1166local explorerFilter = Create('TextBox',{
1167 Text = "Filter Workspace";
1168 BackgroundTransparency = 0.8;
1169 TextColor3 = GuiColor.Text;
1170 TextXAlignment = 'Left';
1171 Font = FONT;
1172 FontSize = FONT_SIZE;
1173 Position = UDim2.new(0,4,0.5,0);
1174 Size = UDim2.new(1,-8,0.5,-2);
1175});
1176explorerFilter.Parent = headerFrame
1177
1178SetZIndexOnChanged(explorerPanel)
1179
1180local function CreateColor3(r, g, b) return Color3.new(r/255,g/255,b/255) end
1181
1182local Styles = {
1183 Font = Enum.Font.Arial;
1184 Margin = 5;
1185 Black = CreateColor3(0,0,0);
1186 White = CreateColor3(255,255,255);
1187}
1188
1189local DropDown = {
1190 Font = Styles.Font;
1191 FontSize = Enum.FontSize.Size14;
1192 TextColor = CreateColor3(0,0,0);
1193 TextColorOver = Styles.White;
1194 TextXAlignment = Enum.TextXAlignment.Left;
1195 Height = 20;
1196 BackColor = Styles.White;
1197 BackColorOver = CreateColor3(86,125,188);
1198 BorderColor = CreateColor3(216,216,216);
1199 BorderSizePixel = 2;
1200 ArrowColor = CreateColor3(160,160,160);
1201 ArrowColorOver = Styles.Black;
1202}
1203
1204local Row = {
1205 Font = Styles.Font;
1206 FontSize = Enum.FontSize.Size14;
1207 TextXAlignment = Enum.TextXAlignment.Left;
1208 TextColor = Styles.Black;
1209 TextColorOver = Styles.White;
1210 TextLockedColor = CreateColor3(120,120,120);
1211 Height = 24;
1212 BorderColor = CreateColor3(216,216,216);
1213 BackgroundColor = Styles.White;
1214 BackgroundColorAlternate = CreateColor3(246,246,246);
1215 BackgroundColorMouseover = CreateColor3(211,224,244);
1216 TitleMarginLeft = 15;
1217}
1218
1219local currentRightClickMenu
1220local CurrentInsertObjectWindow
1221local CurrentFunctionCallerWindow
1222
1223local RbxApi
1224
1225function ClassCanCreate(IName)
1226 local success,err = pcall(function() Instance.new(IName) end)
1227 if err then
1228 return false
1229 else
1230 return true
1231 end
1232end
1233
1234function GetClasses()
1235 if RbxApi == nil then return {} end
1236 local classTable = {}
1237 for i,v in pairs(RbxApi.Classes) do
1238 if ClassCanCreate(v.Name) then
1239 table.insert(classTable,v.Name)
1240 end
1241 end
1242 return classTable
1243end
1244
1245local function sortAlphabetic(t, property)
1246 table.sort(t,
1247 function(x,y) return x[property] < y[property]
1248 end)
1249end
1250
1251local function FunctionIsHidden(functionData)
1252 local tags = functionData["tags"]
1253 for _,name in pairs(tags) do
1254 if name == "deprecated"
1255 or name == "hidden"
1256 or name == "writeonly" then
1257 return true
1258 end
1259 end
1260 return false
1261end
1262
1263local function GetAllFunctions(className)
1264 local class = RbxApi.Classes[className]
1265 local functions = {}
1266
1267 if not class then return functions end
1268
1269 while class do
1270 if class.Name == "Instance" then break end
1271 for _,nextFunction in pairs(class.Functions) do
1272 if not FunctionIsHidden(nextFunction) then
1273 table.insert(functions, nextFunction)
1274 end
1275 end
1276 class = RbxApi.Classes[class.Superclass]
1277 end
1278
1279 sortAlphabetic(functions, "Name")
1280
1281 return functions
1282end
1283
1284function GetFunctions()
1285 if RbxApi == nil then return {} end
1286 local List = SelectionVar():Get()
1287
1288 if #List == 0 then return end
1289
1290 local MyObject = List[1]
1291
1292 local functionTable = {}
1293 for i,v in pairs(GetAllFunctions(MyObject.ClassName)) do
1294 table.insert(functionTable,v)
1295 end
1296 return functionTable
1297end
1298
1299function CreateInsertObjectMenu(choices, currentChoice, readOnly, onClick)
1300 local mouse = game.Players.LocalPlayer:GetMouse()
1301 local totalSize = explorerPanel.Parent.AbsoluteSize.y
1302 if #choices == 0 then return end
1303
1304 table.sort(choices, function(a,b) return a < b end)
1305
1306 local frame = Instance.new("Frame")
1307 frame.Name = "InsertObject"
1308 frame.Size = UDim2.new(0, 200, 1, 0)
1309 frame.BackgroundTransparency = 1
1310 frame.Active = true
1311
1312 local menu = nil
1313 local arrow = nil
1314 local expanded = false
1315 local margin = DropDown.BorderSizePixel;
1316
1317 --[[
1318 local button = Instance.new("TextButton")
1319 button.Font = Row.Font
1320 button.FontSize = Row.FontSize
1321 button.TextXAlignment = Row.TextXAlignment
1322 button.BackgroundTransparency = 1
1323 button.TextColor3 = Row.TextColor
1324 if readOnly then
1325 button.TextColor3 = Row.TextLockedColor
1326 end
1327 button.Text = currentChoice
1328 button.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
1329 button.Position = UDim2.new(0, Styles.Margin, 0, 0)
1330 button.Parent = frame
1331 --]]
1332
1333 local function hideMenu()
1334 expanded = false
1335 --showArrow(DropDown.ArrowColor)
1336 if frame then
1337 --frame:Destroy()
1338 CurrentInsertObjectWindow.Visible = false
1339 end
1340 end
1341
1342 local function showMenu()
1343 expanded = true
1344 menu = Instance.new("ScrollingFrame")
1345 menu.Size = UDim2.new(0,200,1,0)
1346 menu.CanvasSize = UDim2.new(0, 200, 0, #choices * DropDown.Height)
1347 menu.Position = UDim2.new(0, margin, 0, 0)
1348 menu.BackgroundTransparency = 0
1349 menu.BackgroundColor3 = DropDown.BackColor
1350 menu.BorderColor3 = DropDown.BorderColor
1351 menu.BorderSizePixel = DropDown.BorderSizePixel
1352 menu.TopImage = "rbxasset://textures/blackBkg_square.png"
1353 menu.MidImage = "rbxasset://textures/blackBkg_square.png"
1354 menu.BottomImage = "rbxasset://textures/blackBkg_square.png"
1355 menu.Active = true
1356 menu.ZIndex = 5
1357 menu.Parent = frame
1358
1359 --local parentFrameHeight = script.Parent.List.Size.Y.Offset
1360 --local rowHeight = mouse.Y
1361 --if (rowHeight + menu.Size.Y.Offset) > parentFrameHeight then
1362 -- menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
1363 --end
1364
1365 local function choice(name)
1366 onClick(name)
1367 hideMenu()
1368 end
1369
1370 for i,name in pairs(choices) do
1371 local option = CreateRightClickMenuItem(name, function()
1372 choice(name)
1373 end,1)
1374 option.Size = UDim2.new(1, 0, 0, 20)
1375 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
1376 option.ZIndex = menu.ZIndex
1377 option.Parent = menu
1378 end
1379 end
1380
1381
1382 showMenu()
1383
1384
1385 return frame
1386end
1387
1388function CreateFunctionCallerMenu(choices, currentChoice, readOnly, onClick)
1389 local mouse = game.Players.LocalPlayer:GetMouse()
1390 local totalSize = explorerPanel.Parent.AbsoluteSize.y
1391 if #choices == 0 then return end
1392
1393 table.sort(choices, function(a,b) return a.Name < b.Name end)
1394
1395 local frame = Instance.new("Frame")
1396 frame.Name = "InsertObject"
1397 frame.Size = UDim2.new(0, 200, 1, 0)
1398 frame.BackgroundTransparency = 1
1399 frame.Active = true
1400
1401 local menu = nil
1402 local arrow = nil
1403 local expanded = false
1404 local margin = DropDown.BorderSizePixel;
1405
1406 local function hideMenu()
1407 expanded = false
1408 --showArrow(DropDown.ArrowColor)
1409 if frame then
1410 --frame:Destroy()
1411 CurrentInsertObjectWindow.Visible = false
1412 end
1413 end
1414
1415 local function showMenu()
1416 expanded = true
1417 menu = Instance.new("ScrollingFrame")
1418 menu.Size = UDim2.new(0,300,1,0)
1419 menu.CanvasSize = UDim2.new(0, 300, 0, #choices * DropDown.Height)
1420 menu.Position = UDim2.new(0, margin, 0, 0)
1421 menu.BackgroundTransparency = 0
1422 menu.BackgroundColor3 = DropDown.BackColor
1423 menu.BorderColor3 = DropDown.BorderColor
1424 menu.BorderSizePixel = DropDown.BorderSizePixel
1425 menu.TopImage = "rbxasset://textures/blackBkg_square.png"
1426 menu.MidImage = "rbxasset://textures/blackBkg_square.png"
1427 menu.BottomImage = "rbxasset://textures/blackBkg_square.png"
1428 menu.Active = true
1429 menu.ZIndex = 5
1430 menu.Parent = frame
1431
1432 --local parentFrameHeight = script.Parent.List.Size.Y.Offset
1433 --local rowHeight = mouse.Y
1434 --if (rowHeight + menu.Size.Y.Offset) > parentFrameHeight then
1435 -- menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
1436 --end
1437
1438 local function GetParameters(functionData)
1439 local paraString = ""
1440 paraString = paraString.."("
1441 for i,v in pairs(functionData.Arguments) do
1442 paraString = paraString..v.Type.." "..v.Name
1443 if i < #functionData.Arguments then
1444 paraString = paraString..", "
1445 end
1446 end
1447 paraString = paraString..")"
1448 return paraString
1449 end
1450
1451 local function choice(name)
1452 onClick(name)
1453 hideMenu()
1454 end
1455
1456 for i,name in pairs(choices) do
1457 local option = CreateRightClickMenuItem(name.ReturnType.." "..name.Name..GetParameters(name), function()
1458 choice(name)
1459 end,2)
1460 option.Size = UDim2.new(1, 0, 0, 20)
1461 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
1462 option.ZIndex = menu.ZIndex
1463 option.Parent = menu
1464 end
1465 end
1466
1467
1468 showMenu()
1469
1470
1471 return frame
1472end
1473
1474function CreateInsertObject()
1475 if not CurrentInsertObjectWindow then return end
1476 CurrentInsertObjectWindow.Visible = true
1477 if currentRightClickMenu and CurrentInsertObjectWindow.Visible then
1478 CurrentInsertObjectWindow.Position = UDim2.new(0,currentRightClickMenu.Position.X.Offset-currentRightClickMenu.Size.X.Offset-2,0,0)
1479 end
1480 if CurrentInsertObjectWindow.Visible then
1481 CurrentInsertObjectWindow.Parent = explorerPanel.Parent
1482 end
1483end
1484
1485function CreateFunctionCaller()
1486 if CurrentFunctionCallerWindow then
1487 CurrentFunctionCallerWindow:Destroy()
1488 CurrentFunctionCallerWindow = nil
1489 end
1490 CurrentFunctionCallerWindow = CreateFunctionCallerMenu(
1491 GetFunctions(),
1492 "",
1493 false,
1494 function(option)
1495 CurrentFunctionCallerWindow:Destroy()
1496 CurrentFunctionCallerWindow = nil
1497 local list = SelectionVar():Get()
1498 for i = 1,#list do
1499 pcall(function() Instance.new(option,list[i]) end)
1500 end
1501 print(option.Name .. " selected to be called. Function caller being added soon, please wait!")
1502 --CallFunction()
1503 DestroyRightClick()
1504 end
1505 )
1506 if currentRightClickMenu and CurrentFunctionCallerWindow then
1507 CurrentFunctionCallerWindow.Position = UDim2.new(0,currentRightClickMenu.Position.X.Offset-currentRightClickMenu.Size.X.Offset*1.5-2,0,0)
1508 end
1509 if CurrentFunctionCallerWindow then
1510 CurrentFunctionCallerWindow.Parent = explorerPanel.Parent
1511 end
1512end
1513
1514function CreateRightClickMenuItem(text, onClick, insObj)
1515 local button = Instance.new("TextButton")
1516 button.Font = DropDown.Font
1517 button.FontSize = DropDown.FontSize
1518 button.TextColor3 = DropDown.TextColor
1519 button.TextXAlignment = DropDown.TextXAlignment
1520 button.BackgroundColor3 = DropDown.BackColor
1521 button.AutoButtonColor = false
1522 button.BorderSizePixel = 0
1523 button.Active = true
1524 button.Text = text
1525
1526 if insObj == 1 then
1527 local newIcon = Icon(nil,ExplorerIndex[text] or 0)
1528 newIcon.Position = UDim2.new(0,0,0,2)
1529 newIcon.Size = UDim2.new(0,16,0,16)
1530 newIcon.IconMap.ZIndex = 5
1531 newIcon.Parent = button
1532 button.Text = "\t\t"..button.Text
1533 elseif insObj == 2 then
1534 button.FontSize = Enum.FontSize.Size11
1535 end
1536
1537 button.MouseEnter:connect(function()
1538 button.TextColor3 = DropDown.TextColorOver
1539 button.BackgroundColor3 = DropDown.BackColorOver
1540 if not insObj and CurrentInsertObjectWindow then
1541 if CurrentInsertObjectWindow.Visible == false and button.Text == "Insert Object" then
1542 CreateInsertObject()
1543 elseif CurrentInsertObjectWindow.Visible and button.Text ~= "Insert Object" then
1544 CurrentInsertObjectWindow.Visible = false
1545 end
1546 end
1547 if not insObj then
1548 if CurrentFunctionCallerWindow and button.Text ~= "Call Function" then
1549 CurrentFunctionCallerWindow:Destroy()
1550 CurrentFunctionCallerWindow = nil
1551 elseif button.Text == "Call Function" then
1552 CreateFunctionCaller()
1553 end
1554 end
1555 end)
1556 button.MouseLeave:connect(function()
1557 button.TextColor3 = DropDown.TextColor
1558 button.BackgroundColor3 = DropDown.BackColor
1559 end)
1560 button.MouseButton1Click:connect(function()
1561 button.TextColor3 = DropDown.TextColor
1562 button.BackgroundColor3 = DropDown.BackColor
1563 onClick(text)
1564 end)
1565 return button
1566end
1567
1568function CreateRightClickMenu(choices, currentChoice, readOnly, onClick)
1569 local mouse = game.Players.LocalPlayer:GetMouse()
1570
1571 local frame = Instance.new("Frame")
1572 frame.Name = "DropDown"
1573 frame.Size = UDim2.new(0, 200, 1, 0)
1574 frame.BackgroundTransparency = 1
1575 frame.Active = true
1576
1577 local menu = nil
1578 local arrow = nil
1579 local expanded = false
1580 local margin = DropDown.BorderSizePixel;
1581
1582 --[[
1583 local button = Instance.new("TextButton")
1584 button.Font = Row.Font
1585 button.FontSize = Row.FontSize
1586 button.TextXAlignment = Row.TextXAlignment
1587 button.BackgroundTransparency = 1
1588 button.TextColor3 = Row.TextColor
1589 if readOnly then
1590 button.TextColor3 = Row.TextLockedColor
1591 end
1592 button.Text = currentChoice
1593 button.Size = UDim2.new(1, -2 * Styles.Margin, 1, 0)
1594 button.Position = UDim2.new(0, Styles.Margin, 0, 0)
1595 button.Parent = frame
1596 --]]
1597
1598 local function hideMenu()
1599 expanded = false
1600 --showArrow(DropDown.ArrowColor)
1601 if frame then
1602 frame:Destroy()
1603 DestroyRightClick()
1604 end
1605 end
1606
1607 local function showMenu()
1608 expanded = true
1609 menu = Instance.new("Frame")
1610 menu.Size = UDim2.new(0, 200, 0, #choices * DropDown.Height)
1611 menu.Position = UDim2.new(0, margin, 0, 5)
1612 menu.BackgroundTransparency = 0
1613 menu.BackgroundColor3 = DropDown.BackColor
1614 menu.BorderColor3 = DropDown.BorderColor
1615 menu.BorderSizePixel = DropDown.BorderSizePixel
1616 menu.Active = true
1617 menu.ZIndex = 5
1618 menu.Parent = frame
1619
1620 --local parentFrameHeight = script.Parent.List.Size.Y.Offset
1621 --local rowHeight = mouse.Y
1622 --if (rowHeight + menu.Size.Y.Offset) > parentFrameHeight then
1623 -- menu.Position = UDim2.new(0, margin, 0, -1 * (#choices * DropDown.Height) - margin)
1624 --end
1625
1626 local function choice(name)
1627 onClick(name)
1628 hideMenu()
1629 end
1630
1631 for i,name in pairs(choices) do
1632 local option = CreateRightClickMenuItem(name, function()
1633 choice(name)
1634 end)
1635 option.Size = UDim2.new(1, 0, 0, 20)
1636 option.Position = UDim2.new(0, 0, 0, (i - 1) * DropDown.Height)
1637 option.ZIndex = menu.ZIndex
1638 option.Parent = menu
1639 end
1640 end
1641
1642
1643 showMenu()
1644
1645
1646 return frame
1647end
1648
1649function checkMouseInGui(gui)
1650 if gui == nil then return false end
1651 local plrMouse = game.Players.LocalPlayer:GetMouse()
1652 local guiPosition = gui.AbsolutePosition
1653 local guiSize = gui.AbsoluteSize
1654
1655 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
1656 return true
1657 else
1658 return false
1659 end
1660end
1661
1662local clipboard = {}
1663local function delete(o)
1664 o.Parent = nil
1665end
1666
1667local getTextWidth do
1668 local text = Create('TextLabel',{
1669 Name = "TextWidth";
1670 TextXAlignment = 'Left';
1671 TextYAlignment = 'Center';
1672 Font = FONT;
1673 FontSize = FONT_SIZE;
1674 Text = "";
1675 Position = UDim2.new(0,0,0,0);
1676 Size = UDim2.new(1,0,1,0);
1677 Visible = false;
1678 Parent = explorerPanel;
1679 })
1680 function getTextWidth(s)
1681 text.Text = s
1682 return text.TextBounds.x
1683 end
1684end
1685
1686local nameScanned = false
1687-- Holds the game tree converted to a list.
1688local TreeList = {}
1689-- Matches objects to their tree node representation.
1690local NodeLookup = {}
1691
1692local nodeWidth = 0
1693
1694local QuickButtons = {}
1695
1696function filteringWorkspace()
1697 if explorerFilter.Text ~= "" and explorerFilter.Text ~= "Filter Workspace" then
1698 return true
1699 end
1700 return false
1701end
1702
1703function lookForAName(obj,name)
1704 for i,v in pairs(obj:GetChildren()) do
1705 if string.find(string.lower(v.Name),string.lower(name)) then nameScanned = true end
1706 lookForAName(v,name)
1707 end
1708end
1709
1710function scanName(obj)
1711 nameScanned = false
1712 if string.find(string.lower(obj.Name),string.lower(explorerFilter.Text)) then
1713 nameScanned = true
1714 else
1715 lookForAName(obj,explorerFilter.Text)
1716 end
1717 return nameScanned
1718end
1719
1720function updateActions()
1721 for i,v in pairs(QuickButtons) do
1722 if v.Cond() then
1723 v.Toggle(true)
1724 else
1725 v.Toggle(false)
1726 end
1727 end
1728end
1729
1730local updateList,rawUpdateList,updateScroll,rawUpdateSize do
1731 local function r(t)
1732 for i = 1,#t do
1733 if not filteringWorkspace() or scanName(t[i].Object) then
1734 TreeList[#TreeList+1] = t[i]
1735
1736 local w = (t[i].Depth)*(2+ENTRY_PADDING+GUI_SIZE) + 2 + ENTRY_SIZE + 4 + getTextWidth(t[i].Object.Name) + 4
1737 if w > nodeWidth then
1738 nodeWidth = w
1739 end
1740 if t[i].Expanded or filteringWorkspace() then
1741 r(t[i])
1742 end
1743 end
1744 end
1745 end
1746
1747 function rawUpdateSize()
1748 scrollBarH.TotalSpace = nodeWidth
1749 scrollBarH.VisibleSpace = listFrame.AbsoluteSize.x
1750 scrollBarH:Update()
1751 local visible = scrollBarH:CanScrollDown() or scrollBarH:CanScrollUp()
1752 scrollBarH.GUI.Visible = visible
1753
1754 listFrame.Size = UDim2.new(1,-GUI_SIZE,1,-GUI_SIZE*(visible and 1 or 0) - HEADER_SIZE)
1755
1756 scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
1757 scrollBar.GUI.Size = UDim2.new(0,GUI_SIZE,1,-GUI_SIZE*(visible and 1 or 0) - HEADER_SIZE)
1758
1759 scrollBar.TotalSpace = #TreeList+1
1760 scrollBar:Update()
1761 end
1762
1763 function rawUpdateList()
1764 -- Clear then repopulate the entire list. It appears to be fast enough.
1765 TreeList = {}
1766 nodeWidth = 0
1767 r(NodeLookup[workspace.Parent])
1768 if DexStorageEnabled then
1769 r(NodeLookup[DexStorage])
1770 end
1771 if NilStorageEnabled then
1772 r(NodeLookup[NilStorage])
1773 end
1774 rawUpdateSize()
1775 updateActions()
1776 end
1777
1778 -- Adding or removing large models will cause many updates to occur. We
1779 -- can reduce the number of updates by creating a delay, then dropping any
1780 -- updates that occur during the delay.
1781 local updatingList = false
1782 function updateList()
1783 if updatingList then return end
1784 updatingList = true
1785 wait(0.25)
1786 updatingList = false
1787 rawUpdateList()
1788 end
1789
1790 local updatingScroll = false
1791 function updateScroll()
1792 if updatingScroll then return end
1793 updatingScroll = true
1794 wait(0.25)
1795 updatingScroll = false
1796 scrollBar:Update()
1797 end
1798end
1799
1800local Selection do
1801 local bindGetSelection = explorerPanel:FindFirstChild("GetSelection")
1802 if not bindGetSelection then
1803 bindGetSelection = Create('BindableFunction',{Name = "GetSelection"})
1804 bindGetSelection.Parent = explorerPanel
1805 end
1806
1807 local bindSetSelection = explorerPanel:FindFirstChild("SetSelection")
1808 if not bindSetSelection then
1809 bindSetSelection = Create('BindableFunction',{Name = "SetSelection"})
1810 bindSetSelection.Parent = explorerPanel
1811 end
1812
1813 local bindSelectionChanged = explorerPanel:FindFirstChild("SelectionChanged")
1814 if not bindSelectionChanged then
1815 bindSelectionChanged = Create('BindableEvent',{Name = "SelectionChanged"})
1816 bindSelectionChanged.Parent = explorerPanel
1817 end
1818
1819 local SelectionList = {}
1820 local SelectionSet = {}
1821 local Updates = true
1822 Selection = {
1823 Selected = SelectionSet;
1824 List = SelectionList;
1825 }
1826
1827 local function addObject(object)
1828 -- list update
1829 local lupdate = false
1830 -- scroll update
1831 local supdate = false
1832
1833 if not SelectionSet[object] then
1834 local node = NodeLookup[object]
1835 if node then
1836 table.insert(SelectionList,object)
1837 SelectionSet[object] = true
1838 node.Selected = true
1839
1840 -- expand all ancestors so that selected node becomes visible
1841 node = node.Parent
1842 while node do
1843 if not node.Expanded then
1844 node.Expanded = true
1845 lupdate = true
1846 end
1847 node = node.Parent
1848 end
1849 supdate = true
1850 end
1851 end
1852 return lupdate,supdate
1853 end
1854
1855 function Selection:Set(objects)
1856 local lupdate = false
1857 local supdate = false
1858
1859 if #SelectionList > 0 then
1860 for i = 1,#SelectionList do
1861 local object = SelectionList[i]
1862 local node = NodeLookup[object]
1863 if node then
1864 node.Selected = false
1865 SelectionSet[object] = nil
1866 end
1867 end
1868
1869 SelectionList = {}
1870 Selection.List = SelectionList
1871 supdate = true
1872 end
1873
1874 for i = 1,#objects do
1875 local l,s = addObject(objects[i])
1876 lupdate = l or lupdate
1877 supdate = s or supdate
1878 end
1879
1880 if lupdate then
1881 rawUpdateList()
1882 supdate = true
1883 elseif supdate then
1884 scrollBar:Update()
1885 end
1886
1887 if supdate then
1888 bindSelectionChanged:Fire()
1889 updateActions()
1890 end
1891 end
1892
1893 function Selection:Add(object)
1894 local l,s = addObject(object)
1895 if l then
1896 rawUpdateList()
1897 if Updates then
1898 bindSelectionChanged:Fire()
1899 updateActions()
1900 end
1901 elseif s then
1902 scrollBar:Update()
1903 if Updates then
1904 bindSelectionChanged:Fire()
1905 updateActions()
1906 end
1907 end
1908 end
1909
1910 function Selection:StopUpdates()
1911 Updates = false
1912 end
1913
1914 function Selection:ResumeUpdates()
1915 Updates = true
1916 bindSelectionChanged:Fire()
1917 updateActions()
1918 end
1919
1920 function Selection:Remove(object,noupdate)
1921 if SelectionSet[object] then
1922 local node = NodeLookup[object]
1923 if node then
1924 node.Selected = false
1925 SelectionSet[object] = nil
1926 for i = 1,#SelectionList do
1927 if SelectionList[i] == object then
1928 table.remove(SelectionList,i)
1929 break
1930 end
1931 end
1932
1933 if not noupdate then
1934 scrollBar:Update()
1935 end
1936 bindSelectionChanged:Fire()
1937 updateActions()
1938 end
1939 end
1940 end
1941
1942 function Selection:Get()
1943 local list = {}
1944 for i = 1,#SelectionList do
1945 list[i] = SelectionList[i]
1946 end
1947 return list
1948 end
1949
1950 bindSetSelection.OnInvoke = function(...)
1951 Selection:Set(...)
1952 end
1953
1954 bindGetSelection.OnInvoke = function()
1955 return Selection:Get()
1956 end
1957end
1958
1959function CreateCaution(title,msg)
1960 local newCaution = CautionWindow:Clone()
1961 newCaution.Title.Text = title
1962 newCaution.MainWindow.Desc.Text = msg
1963 newCaution.Parent = explorerPanel.Parent
1964 newCaution.Visible = true
1965 newCaution.MainWindow.Ok.MouseButton1Up:connect(function()
1966 newCaution:Destroy()
1967 end)
1968end
1969
1970function CreateTableCaution(title,msg)
1971 if type(msg) ~= "table" then return CreateCaution(title,tostring(msg)) end
1972 local newCaution = TableCautionWindow:Clone()
1973 newCaution.Title.Text = title
1974
1975 local TableList = newCaution.MainWindow.TableResults
1976 local TableTemplate = newCaution.MainWindow.TableTemplate
1977
1978 for i,v in pairs(msg) do
1979 local newResult = TableTemplate:Clone()
1980 newResult.Type.Text = type(v)
1981 newResult.Value.Text = tostring(v)
1982 newResult.Position = UDim2.new(0,0,0,#TableList:GetChildren() * 20)
1983 newResult.Parent = TableList
1984 TableList.CanvasSize = UDim2.new(0,0,0,#TableList:GetChildren() * 20)
1985 newResult.Visible = true
1986 end
1987 newCaution.Parent = explorerPanel.Parent
1988 newCaution.Visible = true
1989 newCaution.MainWindow.Ok.MouseButton1Up:connect(function()
1990 newCaution:Destroy()
1991 end)
1992end
1993
1994local function Split(str, delimiter)
1995 local start = 1
1996 local t = {}
1997 while true do
1998 local pos = string.find (str, delimiter, start, true)
1999 if not pos then
2000 break
2001 end
2002 table.insert (t, string.sub (str, start, pos - 1))
2003 start = pos + string.len (delimiter)
2004 end
2005 table.insert (t, string.sub (str, start))
2006 return t
2007end
2008
2009local function ToValue(value,type)
2010 if type == "Vector2" then
2011 local list = Split(value,",")
2012 if #list < 2 then return nil end
2013 local x = tonumber(list[1]) or 0
2014 local y = tonumber(list[2]) or 0
2015 return Vector2.new(x,y)
2016 elseif type == "Vector3" then
2017 local list = Split(value,",")
2018 if #list < 3 then return nil end
2019 local x = tonumber(list[1]) or 0
2020 local y = tonumber(list[2]) or 0
2021 local z = tonumber(list[3]) or 0
2022 return Vector3.new(x,y,z)
2023 elseif type == "Color3" then
2024 local list = Split(value,",")
2025 if #list < 3 then return nil end
2026 local r = tonumber(list[1]) or 0
2027 local g = tonumber(list[2]) or 0
2028 local b = tonumber(list[3]) or 0
2029 return Color3.new(r/255,g/255, b/255)
2030 elseif type == "UDim2" then
2031 local list = Split(string.gsub(string.gsub(value, "{", ""),"}",""),",")
2032 if #list < 4 then return nil end
2033 local xScale = tonumber(list[1]) or 0
2034 local xOffset = tonumber(list[2]) or 0
2035 local yScale = tonumber(list[3]) or 0
2036 local yOffset = tonumber(list[4]) or 0
2037 return UDim2.new(xScale, xOffset, yScale, yOffset)
2038 elseif type == "Number" then
2039 return tonumber(value)
2040 elseif type == "String" then
2041 return value
2042 elseif type == "NumberRange" then
2043 local list = Split(value,",")
2044 if #list == 1 then
2045 if tonumber(list[1]) == nil then return nil end
2046 local newVal = tonumber(list[1]) or 0
2047 return NumberRange.new(newVal)
2048 end
2049 if #list < 2 then return nil end
2050 local x = tonumber(list[1]) or 0
2051 local y = tonumber(list[2]) or 0
2052 return NumberRange.new(x,y)
2053 elseif type == "Script" then
2054 local success,err = ypcall(function()
2055 _G.D_E_X_DONOTUSETHISPLEASE = nil
2056 loadstring(
2057 "_G.D_E_X_DONOTUSETHISPLEASE = "..value
2058 )()
2059 return _G.D_E_X_DONOTUSETHISPLEASE
2060 end)
2061 if err then
2062 return nil
2063 end
2064 else
2065 return nil
2066 end
2067end
2068
2069local function ToPropValue(value,type)
2070 if type == "Vector2" then
2071 local list = Split(value,",")
2072 if #list < 2 then return nil end
2073 local x = tonumber(list[1]) or 0
2074 local y = tonumber(list[2]) or 0
2075 return Vector2.new(x,y)
2076 elseif type == "Vector3" then
2077 local list = Split(value,",")
2078 if #list < 3 then return nil end
2079 local x = tonumber(list[1]) or 0
2080 local y = tonumber(list[2]) or 0
2081 local z = tonumber(list[3]) or 0
2082 return Vector3.new(x,y,z)
2083 elseif type == "Color3" then
2084 local list = Split(value,",")
2085 if #list < 3 then return nil end
2086 local r = tonumber(list[1]) or 0
2087 local g = tonumber(list[2]) or 0
2088 local b = tonumber(list[3]) or 0
2089 return Color3.new(r/255,g/255, b/255)
2090 elseif type == "UDim2" then
2091 local list = Split(string.gsub(string.gsub(value, "{", ""),"}",""),",")
2092 if #list < 4 then return nil end
2093 local xScale = tonumber(list[1]) or 0
2094 local xOffset = tonumber(list[2]) or 0
2095 local yScale = tonumber(list[3]) or 0
2096 local yOffset = tonumber(list[4]) or 0
2097 return UDim2.new(xScale, xOffset, yScale, yOffset)
2098 elseif type == "Content" then
2099 return value
2100 elseif type == "float" or type == "int" or type == "double" then
2101 return tonumber(value)
2102 elseif type == "string" then
2103 return value
2104 elseif type == "NumberRange" then
2105 local list = Split(value,",")
2106 if #list == 1 then
2107 if tonumber(list[1]) == nil then return nil end
2108 local newVal = tonumber(list[1]) or 0
2109 return NumberRange.new(newVal)
2110 end
2111 if #list < 2 then return nil end
2112 local x = tonumber(list[1]) or 0
2113 local y = tonumber(list[2]) or 0
2114 return NumberRange.new(x,y)
2115 elseif string.sub(value,1,4) == "Enum" then
2116 local getEnum = value
2117 while true do
2118 local x,y = string.find(getEnum,".")
2119 if y then
2120 getEnum = string.sub(getEnum,y+1)
2121 else
2122 break
2123 end
2124 end
2125 print(getEnum)
2126 return getEnum
2127 else
2128 return nil
2129 end
2130end
2131
2132function PromptRemoteCaller(inst)
2133 if CurrentRemoteWindow then
2134 CurrentRemoteWindow:Destroy()
2135 CurrentRemoteWindow = nil
2136 end
2137 CurrentRemoteWindow = RemoteWindow:Clone()
2138 CurrentRemoteWindow.Parent = explorerPanel.Parent
2139 CurrentRemoteWindow.Visible = true
2140
2141 local displayValues = false
2142
2143 local ArgumentList = CurrentRemoteWindow.MainWindow.Arguments
2144 local ArgumentTemplate = CurrentRemoteWindow.MainWindow.ArgumentTemplate
2145
2146 if inst:IsA("RemoteEvent") then
2147 CurrentRemoteWindow.Title.Text = "Fire Event"
2148 CurrentRemoteWindow.MainWindow.Ok.Text = "Fire"
2149 CurrentRemoteWindow.MainWindow.DisplayReturned.Visible = false
2150 CurrentRemoteWindow.MainWindow.Desc2.Visible = false
2151 end
2152
2153 local newArgument = ArgumentTemplate:Clone()
2154 newArgument.Parent = ArgumentList
2155 newArgument.Visible = true
2156 newArgument.Type.MouseButton1Down:connect(function()
2157 createDDown(newArgument.Type,function(choice)
2158 newArgument.Type.Text = choice
2159 end,"Script","Number","String","Color3","Vector3","Vector2","UDim2","NumberRange")
2160 end)
2161
2162 CurrentRemoteWindow.MainWindow.Ok.MouseButton1Up:connect(function()
2163 if CurrentRemoteWindow and inst.Parent ~= nil then
2164 local MyArguments = {}
2165 for i,v in pairs(ArgumentList:GetChildren()) do
2166 table.insert(MyArguments,ToValue(v.Value.Text,v.Type.Text))
2167 end
2168 if inst:IsA("RemoteFunction") then
2169 if displayValues then
2170 spawn(function()
2171 local myResults = inst:InvokeServer(unpack(MyArguments))
2172 if myResults then
2173 CreateTableCaution("Remote Caller",myResults)
2174 else
2175 CreateCaution("Remote Caller","This remote did not return anything.")
2176 end
2177 end)
2178 else
2179 spawn(function()
2180 inst:InvokeServer(unpack(MyArguments))
2181 end)
2182 end
2183 else
2184 inst:FireServer(unpack(MyArguments))
2185 end
2186 CurrentRemoteWindow:Destroy()
2187 CurrentRemoteWindow = nil
2188 end
2189 end)
2190
2191 CurrentRemoteWindow.MainWindow.Add.MouseButton1Up:connect(function()
2192 if CurrentRemoteWindow then
2193 local newArgument = ArgumentTemplate:Clone()
2194 newArgument.Position = UDim2.new(0,0,0,#ArgumentList:GetChildren() * 20)
2195 newArgument.Parent = ArgumentList
2196 ArgumentList.CanvasSize = UDim2.new(0,0,0,#ArgumentList:GetChildren() * 20)
2197 newArgument.Visible = true
2198 newArgument.Type.MouseButton1Down:connect(function()
2199 createDDown(newArgument.Type,function(choice)
2200 newArgument.Type.Text = choice
2201 end,"Script","Number","String","Color3","Vector3","Vector2","UDim2","NumberRange")
2202 end)
2203 end
2204 end)
2205
2206 CurrentRemoteWindow.MainWindow.Subtract.MouseButton1Up:connect(function()
2207 if CurrentRemoteWindow then
2208 if #ArgumentList:GetChildren() > 1 then
2209 ArgumentList:GetChildren()[#ArgumentList:GetChildren()]:Destroy()
2210 ArgumentList.CanvasSize = UDim2.new(0,0,0,#ArgumentList:GetChildren() * 20)
2211 end
2212 end
2213 end)
2214
2215 CurrentRemoteWindow.MainWindow.Cancel.MouseButton1Up:connect(function()
2216 if CurrentRemoteWindow then
2217 CurrentRemoteWindow:Destroy()
2218 CurrentRemoteWindow = nil
2219 end
2220 end)
2221
2222 CurrentRemoteWindow.MainWindow.DisplayReturned.MouseButton1Up:connect(function()
2223 if displayValues then
2224 displayValues = false
2225 CurrentRemoteWindow.MainWindow.DisplayReturned.enabled.Visible = false
2226 else
2227 displayValues = true
2228 CurrentRemoteWindow.MainWindow.DisplayReturned.enabled.Visible = true
2229 end
2230 end)
2231end
2232
2233function PromptSaveInstance(inst)
2234 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
2235 if CurrentSaveInstanceWindow then
2236 CurrentSaveInstanceWindow:Destroy()
2237 CurrentSaveInstanceWindow = nil
2238 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2239 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2240 end
2241 end
2242 CurrentSaveInstanceWindow = SaveInstanceWindow:Clone()
2243 CurrentSaveInstanceWindow.Parent = explorerPanel.Parent
2244 CurrentSaveInstanceWindow.Visible = true
2245
2246 local filename = CurrentSaveInstanceWindow.MainWindow.FileName
2247 local saveObjects = true
2248 local overwriteCaution = false
2249
2250 CurrentSaveInstanceWindow.MainWindow.Save.MouseButton1Up:connect(function()
2251 if readfile and getelysianpath then
2252 if readfile(getelysianpath()..filename.Text..".rbxmx") then
2253 if not overwriteCaution then
2254 overwriteCaution = true
2255 local newCaution = ConfirmationWindow:Clone()
2256 newCaution.Name = "SaveInstanceOverwriteCaution"
2257 newCaution.MainWindow.Desc.Text = "The file, "..filename.Text..".rbxmx, already exists. Overwrite?"
2258 newCaution.Parent = explorerPanel.Parent
2259 newCaution.Visible = true
2260 newCaution.MainWindow.Yes.MouseButton1Up:connect(function()
2261 ypcall(function()
2262 SaveInstance(inst,filename.Text..".rbxmx",not saveObjects)
2263 end)
2264 overwriteCaution = false
2265 newCaution:Destroy()
2266 if CurrentSaveInstanceWindow then
2267 CurrentSaveInstanceWindow:Destroy()
2268 CurrentSaveInstanceWindow = nil
2269 end
2270 end)
2271 newCaution.MainWindow.No.MouseButton1Up:connect(function()
2272 overwriteCaution = false
2273 newCaution:Destroy()
2274 end)
2275 end
2276 else
2277 ypcall(function()
2278 SaveInstance(inst,filename.Text..".rbxmx",not saveObjects)
2279 end)
2280 if CurrentSaveInstanceWindow then
2281 CurrentSaveInstanceWindow:Destroy()
2282 CurrentSaveInstanceWindow = nil
2283 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2284 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2285 end
2286 end
2287 end
2288 else
2289 ypcall(function()
2290 if SaveInstance then
2291 SaveInstance(inst,filename.Text..".rbxmx",not saveObjects)
2292 else
2293 _G.SaveInstance(inst,filename.Text,not saveObjects)
2294 end
2295 end)
2296 if CurrentSaveInstanceWindow then
2297 CurrentSaveInstanceWindow:Destroy()
2298 CurrentSaveInstanceWindow = nil
2299 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2300 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2301 end
2302 end
2303 end
2304 end)
2305 CurrentSaveInstanceWindow.MainWindow.Cancel.MouseButton1Up:connect(function()
2306 if CurrentSaveInstanceWindow then
2307 CurrentSaveInstanceWindow:Destroy()
2308 CurrentSaveInstanceWindow = nil
2309 if explorerPanel.Parent:FindFirstChild("SaveInstanceOverwriteCaution") then
2310 explorerPanel.Parent.SaveInstanceOverwriteCaution:Destroy()
2311 end
2312 end
2313 end)
2314 CurrentSaveInstanceWindow.MainWindow.SaveObjects.MouseButton1Up:connect(function()
2315 if saveObjects then
2316 saveObjects = false
2317 CurrentSaveInstanceWindow.MainWindow.SaveObjects.enabled.Visible = false
2318 else
2319 saveObjects = true
2320 CurrentSaveInstanceWindow.MainWindow.SaveObjects.enabled.Visible = true
2321 end
2322 end)
2323end
2324
2325function DestroyRightClick()
2326 if currentRightClickMenu then
2327 currentRightClickMenu:Destroy()
2328 currentRightClickMenu = nil
2329 end
2330 if CurrentInsertObjectWindow and CurrentInsertObjectWindow.Visible then
2331 CurrentInsertObjectWindow.Visible = false
2332 end
2333end
2334
2335function rightClickMenu(sObj)
2336 local mouse = game.Players.LocalPlayer:GetMouse()
2337
2338 currentRightClickMenu = CreateRightClickMenu(
2339 {"Cut","Copy","Paste Into","Duplicate","Delete","Group","Ungroup","Select Children","Teleport To","Insert Part","Insert Object","View Script","Save Instance","Call Function","Call Remote"},
2340 "",
2341 false,
2342 function(option)
2343 if option == "Cut" then
2344 if not Option.Modifiable then return end
2345 clipboard = {}
2346 local list = Selection.List
2347 local cut = {}
2348 for i = 1,#list do
2349 local obj = list[i]:Clone()
2350 if obj then
2351 table.insert(clipboard,obj)
2352 table.insert(cut,list[i])
2353 end
2354 end
2355 for i = 1,#cut do
2356 pcall(delete,cut[i])
2357 end
2358 updateActions()
2359 elseif option == "Copy" then
2360 if not Option.Modifiable then return end
2361 clipboard = {}
2362 local list = Selection.List
2363 for i = 1,#list do
2364 table.insert(clipboard,list[i]:Clone())
2365 end
2366 updateActions()
2367 elseif option == "Paste Into" then
2368 if not Option.Modifiable then return end
2369 local parent = Selection.List[1] or workspace
2370 for i = 1,#clipboard do
2371 clipboard[i]:Clone().Parent = parent
2372 end
2373 elseif option == "Duplicate" then
2374 if not Option.Modifiable then return end
2375 local list = Selection:Get()
2376 for i = 1,#list do
2377 list[i]:Clone().Parent = Selection.List[1].Parent or workspace
2378 end
2379 elseif option == "Delete" then
2380 if not Option.Modifiable then return end
2381 local list = Selection:Get()
2382 for i = 1,#list do
2383 pcall(delete,list[i])
2384 end
2385 Selection:Set({})
2386 elseif option == "Group" then
2387 if not Option.Modifiable then return end
2388 local newModel = Instance.new("Model")
2389 local list = Selection:Get()
2390 newModel.Parent = Selection.List[1].Parent or workspace
2391 for i = 1,#list do
2392 list[i].Parent = newModel
2393 end
2394 Selection:Set({})
2395 elseif option == "Ungroup" then
2396 if not Option.Modifiable then return end
2397 local ungrouped = {}
2398 local list = Selection:Get()
2399 for i = 1,#list do
2400 if list[i]:IsA("Model") then
2401 for i2,v2 in pairs(list[i]:GetChildren()) do
2402 v2.Parent = list[i].Parent or workspace
2403 table.insert(ungrouped,v2)
2404 end
2405 pcall(delete,list[i])
2406 end
2407 end
2408 Selection:Set({})
2409 if SettingsRemote:Invoke("SelectUngrouped") then
2410 for i,v in pairs(ungrouped) do
2411 Selection:Add(v)
2412 end
2413 end
2414 elseif option == "Select Children" then
2415 if not Option.Modifiable then return end
2416 local list = Selection:Get()
2417 Selection:Set({})
2418 Selection:StopUpdates()
2419 for i = 1,#list do
2420 for i2,v2 in pairs(list[i]:GetChildren()) do
2421 Selection:Add(v2)
2422 end
2423 end
2424 Selection:ResumeUpdates()
2425 elseif option == "Teleport To" then
2426 if not Option.Modifiable then return end
2427 local list = Selection:Get()
2428 for i = 1,#list do
2429 if list[i]:IsA("BasePart") then
2430 pcall(function()
2431 game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame = list[i].CFrame
2432 end)
2433 break
2434 end
2435 end
2436 elseif option == "Insert Part" then
2437 if not Option.Modifiable then return end
2438 local insertedParts = {}
2439 local list = Selection:Get()
2440 for i = 1,#list do
2441 pcall(function()
2442 local newPart = Instance.new("Part")
2443 newPart.Parent = list[i]
2444 newPart.CFrame = CFrame.new(game.Players.LocalPlayer.Character.Head.Position) + Vector3.new(0,3,0)
2445 table.insert(insertedParts,newPart)
2446 end)
2447 end
2448 elseif option == "Save Instance" then
2449 if not Option.Modifiable then return end
2450 local list = Selection:Get()
2451 if #list == 1 then
2452 list[1].Archivable = true
2453 ypcall(function()PromptSaveInstance(list[1]:Clone())end)
2454 elseif #list > 1 then
2455 local newModel = Instance.new("Model")
2456 newModel.Name = "SavedInstances"
2457 for i = 1,#list do
2458 ypcall(function()
2459 list[i].Archivable = true
2460 list[i]:Clone().Parent = newModel
2461 end)
2462 end
2463 PromptSaveInstance(newModel)
2464 end
2465 elseif option == "Call Remote" then
2466 if not Option.Modifiable then return end
2467 local list = Selection:Get()
2468 for i = 1,#list do
2469 if list[i]:IsA("RemoteFunction") or list[i]:IsA("RemoteEvent") then
2470 PromptRemoteCaller(list[i])
2471 break
2472 end
2473 end
2474 elseif option == "View Script" then
2475 if not Option.Modifiable then return end
2476 local list = Selection:Get()
2477 for i = 1,#list do
2478 if list[i]:IsA("LocalScript") or list[i]:IsA("ModuleScript") then
2479 ScriptEditorEvent:Fire(list[i])
2480 end
2481 end
2482 end
2483 end)
2484 currentRightClickMenu.Parent = explorerPanel.Parent
2485 currentRightClickMenu.Position = UDim2.new(0,mouse.X,0,mouse.Y)
2486 if currentRightClickMenu.AbsolutePosition.X + currentRightClickMenu.AbsoluteSize.X > explorerPanel.AbsolutePosition.X + explorerPanel.AbsoluteSize.X then
2487 currentRightClickMenu.Position = UDim2.new(0, explorerPanel.AbsolutePosition.X + explorerPanel.AbsoluteSize.X - currentRightClickMenu.AbsoluteSize.X, 0, mouse.Y)
2488 end
2489end
2490
2491local function cancelReparentDrag()end
2492local function cancelSelectDrag()end
2493do
2494 local listEntries = {}
2495 local nameConnLookup = {}
2496
2497 local mouseDrag = Create('ImageButton',{
2498 Name = "MouseDrag";
2499 Position = UDim2.new(-0.25,0,-0.25,0);
2500 Size = UDim2.new(1.5,0,1.5,0);
2501 Transparency = 1;
2502 AutoButtonColor = false;
2503 Active = true;
2504 ZIndex = 10;
2505 })
2506 local function dragSelect(last,add,button)
2507 local connDrag
2508 local conUp
2509
2510 conDrag = mouseDrag.MouseMoved:connect(function(x,y)
2511 local pos = Vector2.new(x,y) - listFrame.AbsolutePosition
2512 local size = listFrame.AbsoluteSize
2513 if pos.x < 0 or pos.x > size.x or pos.y < 0 or pos.y > size.y then return end
2514
2515 local i = math.ceil(pos.y/ENTRY_BOUND) + scrollBar.ScrollIndex
2516 -- Mouse may have made a large step, so interpolate between the
2517 -- last index and the current.
2518 for n = i<last and i or last, i>last and i or last do
2519 local node = TreeList[n]
2520 if node then
2521 if add then
2522 Selection:Add(node.Object)
2523 else
2524 Selection:Remove(node.Object)
2525 end
2526 end
2527 end
2528 last = i
2529 end)
2530
2531 function cancelSelectDrag()
2532 mouseDrag.Parent = nil
2533 conDrag:disconnect()
2534 conUp:disconnect()
2535 function cancelSelectDrag()end
2536 end
2537
2538 conUp = mouseDrag[button]:connect(cancelSelectDrag)
2539
2540 mouseDrag.Parent = GetScreen(listFrame)
2541 end
2542
2543 local function dragReparent(object,dragGhost,clickPos,ghostOffset)
2544 local connDrag
2545 local conUp
2546 local conUp2
2547
2548 local parentIndex = nil
2549 local dragged = false
2550
2551 local parentHighlight = Create('Frame',{
2552 Transparency = 1;
2553 Visible = false;
2554 Create('Frame',{
2555 BorderSizePixel = 0;
2556 BackgroundColor3 = Color3.new(0,0,0);
2557 BackgroundTransparency = 0.1;
2558 Position = UDim2.new(0,0,0,0);
2559 Size = UDim2.new(1,0,0,1);
2560 });
2561 Create('Frame',{
2562 BorderSizePixel = 0;
2563 BackgroundColor3 = Color3.new(0,0,0);
2564 BackgroundTransparency = 0.1;
2565 Position = UDim2.new(1,0,0,0);
2566 Size = UDim2.new(0,1,1,0);
2567 });
2568 Create('Frame',{
2569 BorderSizePixel = 0;
2570 BackgroundColor3 = Color3.new(0,0,0);
2571 BackgroundTransparency = 0.1;
2572 Position = UDim2.new(0,0,1,0);
2573 Size = UDim2.new(1,0,0,1);
2574 });
2575 Create('Frame',{
2576 BorderSizePixel = 0;
2577 BackgroundColor3 = Color3.new(0,0,0);
2578 BackgroundTransparency = 0.1;
2579 Position = UDim2.new(0,0,0,0);
2580 Size = UDim2.new(0,1,1,0);
2581 });
2582 })
2583 SetZIndex(parentHighlight,9)
2584
2585 conDrag = mouseDrag.MouseMoved:connect(function(x,y)
2586 local dragPos = Vector2.new(x,y)
2587 if dragged then
2588 local pos = dragPos - listFrame.AbsolutePosition
2589 local size = listFrame.AbsoluteSize
2590
2591 parentIndex = nil
2592 parentHighlight.Visible = false
2593 if pos.x >= 0 and pos.x <= size.x and pos.y >= 0 and pos.y <= size.y + ENTRY_SIZE*2 then
2594 local i = math.ceil(pos.y/ENTRY_BOUND-2)
2595 local node = TreeList[i + scrollBar.ScrollIndex]
2596 if node and node.Object ~= object and not object:IsAncestorOf(node.Object) then
2597 parentIndex = i
2598 local entry = listEntries[i]
2599 if entry then
2600 parentHighlight.Visible = true
2601 parentHighlight.Position = UDim2.new(0,1,0,entry.AbsolutePosition.y-listFrame.AbsolutePosition.y)
2602 parentHighlight.Size = UDim2.new(0,size.x-4,0,entry.AbsoluteSize.y)
2603 end
2604 end
2605 end
2606
2607 dragGhost.Position = UDim2.new(0,dragPos.x+ghostOffset.x,0,dragPos.y+ghostOffset.y)
2608 elseif (clickPos-dragPos).magnitude > 8 then
2609 dragged = true
2610 SetZIndex(dragGhost,9)
2611 dragGhost.IndentFrame.Transparency = 0.25
2612 dragGhost.IndentFrame.EntryText.TextColor3 = GuiColor.TextSelected
2613 dragGhost.Position = UDim2.new(0,dragPos.x+ghostOffset.x,0,dragPos.y+ghostOffset.y)
2614 dragGhost.Parent = GetScreen(listFrame)
2615 parentHighlight.Parent = listFrame
2616 end
2617 end)
2618
2619 function cancelReparentDrag()
2620 mouseDrag.Parent = nil
2621 conDrag:disconnect()
2622 conUp:disconnect()
2623 conUp2:disconnect()
2624 dragGhost:Destroy()
2625 parentHighlight:Destroy()
2626 function cancelReparentDrag()end
2627 end
2628
2629 local wasSelected = Selection.Selected[object]
2630 if not wasSelected and Option.Selectable then
2631 Selection:Set({object})
2632 end
2633
2634 conUp = mouseDrag.MouseButton1Up:connect(function()
2635 cancelReparentDrag()
2636 if dragged then
2637 if parentIndex then
2638 local parentNode = TreeList[parentIndex + scrollBar.ScrollIndex]
2639 if parentNode then
2640 parentNode.Expanded = true
2641
2642 local parentObj = parentNode.Object
2643 local function parent(a,b)
2644 a.Parent = b
2645 end
2646 if Option.Selectable then
2647 local list = Selection.List
2648 for i = 1,#list do
2649 pcall(parent,list[i],parentObj)
2650 end
2651 else
2652 pcall(parent,object,parentObj)
2653 end
2654 end
2655 end
2656 else
2657 -- do selection click
2658 if wasSelected and Option.Selectable then
2659 Selection:Set({})
2660 end
2661 end
2662 end)
2663 conUp2 = mouseDrag.MouseButton2Down:connect(function()
2664 cancelReparentDrag()
2665 end)
2666
2667 mouseDrag.Parent = GetScreen(listFrame)
2668 end
2669
2670 local entryTemplate = Create('ImageButton',{
2671 Name = "Entry";
2672 Transparency = 1;
2673 AutoButtonColor = false;
2674 Position = UDim2.new(0,0,0,0);
2675 Size = UDim2.new(1,0,0,ENTRY_SIZE);
2676 Create('Frame',{
2677 Name = "IndentFrame";
2678 BackgroundTransparency = 1;
2679 BackgroundColor3 = GuiColor.Selected;
2680 BorderColor3 = GuiColor.BorderSelected;
2681 Position = UDim2.new(0,0,0,0);
2682 Size = UDim2.new(1,0,1,0);
2683 Create(Icon('ImageButton',0),{
2684 Name = "Expand";
2685 AutoButtonColor = false;
2686 Position = UDim2.new(0,-GUI_SIZE,0.5,-GUI_SIZE/2);
2687 Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
2688 });
2689 Create(Icon(nil,0),{
2690 Name = "ExplorerIcon";
2691 Position = UDim2.new(0,2+ENTRY_PADDING,0.5,-GUI_SIZE/2);
2692 Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
2693 });
2694 Create('TextLabel',{
2695 Name = "EntryText";
2696 BackgroundTransparency = 1;
2697 TextColor3 = GuiColor.Text;
2698 TextXAlignment = 'Left';
2699 TextYAlignment = 'Center';
2700 Font = FONT;
2701 FontSize = FONT_SIZE;
2702 Text = "";
2703 Position = UDim2.new(0,2+ENTRY_SIZE+4,0,0);
2704 Size = UDim2.new(1,-2,1,0);
2705 });
2706 });
2707 })
2708
2709 function scrollBar.UpdateCallback(self)
2710 for i = 1,self.VisibleSpace do
2711 local node = TreeList[i + self.ScrollIndex]
2712 if node then
2713 local entry = listEntries[i]
2714 if not entry then
2715 entry = Create(entryTemplate:Clone(),{
2716 Position = UDim2.new(0,2,0,ENTRY_BOUND*(i-1)+2);
2717 Size = UDim2.new(0,nodeWidth,0,ENTRY_SIZE);
2718 ZIndex = listFrame.ZIndex;
2719 })
2720 listEntries[i] = entry
2721
2722 local expand = entry.IndentFrame.Expand
2723 expand.MouseEnter:connect(function()
2724 local node = TreeList[i + self.ScrollIndex]
2725 if #node > 0 then
2726 if node.Expanded then
2727 Icon(expand,NODE_EXPANDED_OVER)
2728 else
2729 Icon(expand,NODE_COLLAPSED_OVER)
2730 end
2731 end
2732 end)
2733 expand.MouseLeave:connect(function()
2734 local node = TreeList[i + self.ScrollIndex]
2735 if #node > 0 then
2736 if node.Expanded then
2737 Icon(expand,NODE_EXPANDED)
2738 else
2739 Icon(expand,NODE_COLLAPSED)
2740 end
2741 end
2742 end)
2743 expand.MouseButton1Down:connect(function()
2744 local node = TreeList[i + self.ScrollIndex]
2745 if #node > 0 then
2746 node.Expanded = not node.Expanded
2747 if node.Object == explorerPanel.Parent and node.Expanded then
2748 CreateCaution("Warning","Please be careful when editing instances inside here, this is like the System32 of Dex and modifying objects here can break Dex.")
2749 end
2750 -- use raw update so the list updates instantly
2751 rawUpdateList()
2752 end
2753 end)
2754
2755 entry.MouseButton1Down:connect(function(x,y)
2756 local node = TreeList[i + self.ScrollIndex]
2757 DestroyRightClick()
2758 if GetAwaitRemote:Invoke() then
2759 bindSetAwaiting:Fire(node.Object)
2760 return
2761 end
2762
2763 if not HoldingShift then
2764 lastSelectedNode = i + self.ScrollIndex
2765 end
2766
2767 if HoldingShift and not filteringWorkspace() then
2768 if lastSelectedNode then
2769 if i + self.ScrollIndex - lastSelectedNode > 0 then
2770 Selection:StopUpdates()
2771 for i2 = 1, i + self.ScrollIndex - lastSelectedNode do
2772 local newNode = TreeList[lastSelectedNode + i2]
2773 if newNode then
2774 Selection:Add(newNode.Object)
2775 end
2776 end
2777 Selection:ResumeUpdates()
2778 else
2779 Selection:StopUpdates()
2780 for i2 = i + self.ScrollIndex - lastSelectedNode, 1 do
2781 local newNode = TreeList[lastSelectedNode + i2]
2782 if newNode then
2783 Selection:Add(newNode.Object)
2784 end
2785 end
2786 Selection:ResumeUpdates()
2787 end
2788 end
2789 return
2790 end
2791
2792 if HoldingCtrl then
2793 if Selection.Selected[node.Object] then
2794 Selection:Remove(node.Object)
2795 else
2796 Selection:Add(node.Object)
2797 end
2798 return
2799 end
2800 if Option.Modifiable then
2801 local pos = Vector2.new(x,y)
2802 dragReparent(node.Object,entry:Clone(),pos,entry.AbsolutePosition-pos)
2803 elseif Option.Selectable then
2804 if Selection.Selected[node.Object] then
2805 Selection:Set({})
2806 else
2807 Selection:Set({node.Object})
2808 end
2809 dragSelect(i+self.ScrollIndex,true,'MouseButton1Up')
2810 end
2811 end)
2812
2813 entry.MouseButton2Down:connect(function()
2814 if not Option.Selectable then return end
2815
2816 DestroyRightClick()
2817
2818 curSelect = entry
2819
2820 local node = TreeList[i + self.ScrollIndex]
2821
2822 if GetAwaitRemote:Invoke() then
2823 bindSetAwaiting:Fire(node.Object)
2824 return
2825 end
2826
2827 if not Selection.Selected[node.Object] then
2828 Selection:Set({node.Object})
2829 end
2830 end)
2831
2832
2833 entry.MouseButton2Up:connect(function()
2834 if not Option.Selectable then return end
2835
2836 local node = TreeList[i + self.ScrollIndex]
2837
2838 if checkMouseInGui(curSelect) then
2839 rightClickMenu(node.Object)
2840 end
2841 end)
2842
2843 entry.Parent = listFrame
2844 end
2845
2846 entry.Visible = true
2847
2848 local object = node.Object
2849
2850 -- update expand icon
2851 if #node == 0 then
2852 entry.IndentFrame.Expand.Visible = false
2853 elseif node.Expanded then
2854 Icon(entry.IndentFrame.Expand,NODE_EXPANDED)
2855 entry.IndentFrame.Expand.Visible = true
2856 else
2857 Icon(entry.IndentFrame.Expand,NODE_COLLAPSED)
2858 entry.IndentFrame.Expand.Visible = true
2859 end
2860
2861 -- update explorer icon
2862 Icon(entry.IndentFrame.ExplorerIcon,ExplorerIndex[object.ClassName] or 0)
2863
2864 -- update indentation
2865 local w = (node.Depth)*(2+ENTRY_PADDING+GUI_SIZE)
2866 entry.IndentFrame.Position = UDim2.new(0,w,0,0)
2867 entry.IndentFrame.Size = UDim2.new(1,-w,1,0)
2868
2869 -- update name change detection
2870 if nameConnLookup[entry] then
2871 nameConnLookup[entry]:disconnect()
2872 end
2873 local text = entry.IndentFrame.EntryText
2874 text.Text = object.Name
2875 nameConnLookup[entry] = node.Object.Changed:connect(function(p)
2876 if p == 'Name' then
2877 text.Text = object.Name
2878 end
2879 end)
2880
2881 -- update selection
2882 entry.IndentFrame.Transparency = node.Selected and 0 or 1
2883 text.TextColor3 = GuiColor[node.Selected and 'TextSelected' or 'Text']
2884
2885 entry.Size = UDim2.new(0,nodeWidth,0,ENTRY_SIZE)
2886 elseif listEntries[i] then
2887 listEntries[i].Visible = false
2888 end
2889 end
2890 for i = self.VisibleSpace+1,self.TotalSpace do
2891 local entry = listEntries[i]
2892 if entry then
2893 listEntries[i] = nil
2894 entry:Destroy()
2895 end
2896 end
2897 end
2898
2899 function scrollBarH.UpdateCallback(self)
2900 for i = 1,scrollBar.VisibleSpace do
2901 local node = TreeList[i + scrollBar.ScrollIndex]
2902 if node then
2903 local entry = listEntries[i]
2904 if entry then
2905 entry.Position = UDim2.new(0,2 - scrollBarH.ScrollIndex,0,ENTRY_BOUND*(i-1)+2)
2906 end
2907 end
2908 end
2909 end
2910
2911 Connect(listFrame.Changed,function(p)
2912 if p == 'AbsoluteSize' then
2913 rawUpdateSize()
2914 end
2915 end)
2916
2917 local wheelAmount = 6
2918 explorerPanel.MouseWheelForward:connect(function()
2919 if scrollBar.VisibleSpace - 1 > wheelAmount then
2920 scrollBar:ScrollTo(scrollBar.ScrollIndex - wheelAmount)
2921 else
2922 scrollBar:ScrollTo(scrollBar.ScrollIndex - scrollBar.VisibleSpace)
2923 end
2924 end)
2925 explorerPanel.MouseWheelBackward:connect(function()
2926 if scrollBar.VisibleSpace - 1 > wheelAmount then
2927 scrollBar:ScrollTo(scrollBar.ScrollIndex + wheelAmount)
2928 else
2929 scrollBar:ScrollTo(scrollBar.ScrollIndex + scrollBar.VisibleSpace)
2930 end
2931 end)
2932end
2933
2934----------------------------------------------------------------
2935----------------------------------------------------------------
2936----------------------------------------------------------------
2937----------------------------------------------------------------
2938---- Object detection
2939
2940-- Inserts `v` into `t` at `i`. Also sets `Index` field in `v`.
2941local function insert(t,i,v)
2942 for n = #t,i,-1 do
2943 local v = t[n]
2944 v.Index = n+1
2945 t[n+1] = v
2946 end
2947 v.Index = i
2948 t[i] = v
2949end
2950
2951-- Removes `i` from `t`. Also sets `Index` field in removed value.
2952local function remove(t,i)
2953 local v = t[i]
2954 for n = i+1,#t do
2955 local v = t[n]
2956 v.Index = n-1
2957 t[n-1] = v
2958 end
2959 t[#t] = nil
2960 v.Index = 0
2961 return v
2962end
2963
2964-- Returns how deep `o` is in the tree.
2965local function depth(o)
2966 local d = -1
2967 while o do
2968 o = o.Parent
2969 d = d + 1
2970 end
2971 return d
2972end
2973
2974
2975local connLookup = {}
2976
2977-- Returns whether a node would be present in the tree list
2978local function nodeIsVisible(node)
2979 local visible = true
2980 node = node.Parent
2981 while node and visible do
2982 visible = visible and node.Expanded
2983 node = node.Parent
2984 end
2985 return visible
2986end
2987
2988-- Removes an object's tree node. Called when the object stops existing in the
2989-- game tree.
2990local function removeObject(object)
2991 local objectNode = NodeLookup[object]
2992 if not objectNode then
2993 return
2994 end
2995
2996 local visible = nodeIsVisible(objectNode)
2997
2998 Selection:Remove(object,true)
2999
3000 local parent = objectNode.Parent
3001 remove(parent,objectNode.Index)
3002 NodeLookup[object] = nil
3003 connLookup[object]:disconnect()
3004 connLookup[object] = nil
3005
3006 if visible then
3007 updateList()
3008 elseif nodeIsVisible(parent) then
3009 updateScroll()
3010 end
3011end
3012
3013-- Moves a tree node to a new parent. Called when an existing object's parent
3014-- changes.
3015local function moveObject(object,parent)
3016 local objectNode = NodeLookup[object]
3017 if not objectNode then
3018 return
3019 end
3020
3021 local parentNode = NodeLookup[parent]
3022 if not parentNode then
3023 return
3024 end
3025
3026 local visible = nodeIsVisible(objectNode)
3027
3028 remove(objectNode.Parent,objectNode.Index)
3029 objectNode.Parent = parentNode
3030
3031 objectNode.Depth = depth(object)
3032 local function r(node,d)
3033 for i = 1,#node do
3034 node[i].Depth = d
3035 r(node[i],d+1)
3036 end
3037 end
3038 r(objectNode,objectNode.Depth+1)
3039
3040 insert(parentNode,#parentNode+1,objectNode)
3041
3042 if visible or nodeIsVisible(objectNode) then
3043 updateList()
3044 elseif nodeIsVisible(objectNode.Parent) then
3045 updateScroll()
3046 end
3047end
3048
3049-- ScriptContext['/Libraries/LibraryRegistration/LibraryRegistration']
3050-- This RobloxLocked object lets me index its properties for some reason
3051
3052local function check(object)
3053 return object.AncestryChanged
3054end
3055
3056-- Creates a new tree node from an object. Called when an object starts
3057-- existing in the game tree.
3058local function addObject(object,noupdate)
3059 if script then
3060 -- protect against naughty RobloxLocked objects
3061 local s = pcall(check,object)
3062 if not s then
3063 return
3064 end
3065 end
3066
3067 local parentNode = NodeLookup[object.Parent]
3068 if not parentNode then
3069 return
3070 end
3071
3072 local objectNode = {
3073 Object = object;
3074 Parent = parentNode;
3075 Index = 0;
3076 Expanded = false;
3077 Selected = false;
3078 Depth = depth(object);
3079 }
3080
3081 connLookup[object] = Connect(object.AncestryChanged,function(c,p)
3082 if c == object then
3083 if p == nil then
3084 removeObject(c)
3085 else
3086 moveObject(c,p)
3087 end
3088 end
3089 end)
3090
3091 NodeLookup[object] = objectNode
3092 insert(parentNode,#parentNode+1,objectNode)
3093
3094 if not noupdate then
3095 if nodeIsVisible(objectNode) then
3096 updateList()
3097 elseif nodeIsVisible(objectNode.Parent) then
3098 updateScroll()
3099 end
3100 end
3101end
3102
3103local function makeObject(obj,par)
3104 local newObject = Instance.new(obj.ClassName)
3105 for i,v in pairs(obj.Properties) do
3106 ypcall(function()
3107 local newProp
3108 newProp = ToPropValue(v.Value,v.Type)
3109 newObject[v.Name] = newProp
3110 end)
3111 end
3112 newObject.Parent = par
3113end
3114
3115local function writeObject(obj)
3116 local newObject = {ClassName = obj.ClassName, Properties = {}}
3117 for i,v in pairs(RbxApi.GetProperties(obj.className)) do
3118 if v["Name"] ~= "Parent" then
3119 print("thispassed")
3120 table.insert(newObject.Properties,{Name = v["Name"], Type = v["ValueType"], Value = tostring(obj[v["Name"]])})
3121 end
3122 end
3123 return newObject
3124end
3125
3126local function buildDexStorage()
3127 local localDexStorage
3128
3129 local success,err = ypcall(function()
3130 localDexStorage = game:GetObjects("rbxasset://DexStorage.rbxm")[1]
3131 end)
3132
3133 if success and localDexStorage then
3134 for i,v in pairs(localDexStorage:GetChildren()) do
3135 ypcall(function()
3136 v.Parent = DexStorageMain
3137 end)
3138 end
3139 end
3140
3141 updateDexStorageListeners()
3142 --[[
3143 local localDexStorage = readfile(getelysianpath().."DexStorage.txt")--game:GetService("CookiesService"):GetCookieValue("DexStorage")
3144 --local success,err = pcall(function()
3145 if localDexStorage then
3146 local objTable = game:GetService("HttpService"):JSONDecode(localDexStorage)
3147 for i,v in pairs(objTable) do
3148 makeObject(v,DexStorageMain)
3149 end
3150 end
3151 --end)
3152 --]]
3153end
3154
3155local dexStorageDebounce = false
3156local dexStorageListeners = {}
3157
3158local function updateDexStorage()
3159 if dexStorageDebounce then return end
3160 dexStorageDebounce = true
3161
3162 wait()
3163
3164 pcall(function()
3165 saveinstance("content//DexStorage.rbxm",DexStorageMain)
3166 end)
3167
3168 updateDexStorageListeners()
3169
3170 dexStorageDebounce = false
3171 --[[
3172 local success,err = ypcall(function()
3173 local objs = {}
3174 for i,v in pairs(DexStorageMain:GetChildren()) do
3175 table.insert(objs,writeObject(v))
3176 end
3177 writefile(getelysianpath().."DexStorage.txt",game:GetService("HttpService"):JSONEncode(objs))
3178 --game:GetService("CookiesService"):SetCookieValue("DexStorage",game:GetService("HttpService"):JSONEncode(objs))
3179 end)
3180 if err then
3181 CreateCaution("DexStorage Save Fail!","DexStorage broke! If you see this message, report to Raspberry Pi!")
3182 end
3183 print("hi")
3184 --]]
3185end
3186
3187function updateDexStorageListeners()
3188 for i,v in pairs(dexStorageListeners) do
3189 v:Disconnect()
3190 end
3191 dexStorageListeners = {}
3192 for i,v in pairs(DexStorageMain:GetChildren()) do
3193 pcall(function()
3194 local ev = v.Changed:connect(updateDexStorage)
3195 table.insert(dexStorageListeners,ev)
3196 end)
3197 end
3198end
3199
3200do
3201 NodeLookup[workspace.Parent] = {
3202 Object = workspace.Parent;
3203 Parent = nil;
3204 Index = 0;
3205 Expanded = true;
3206 }
3207
3208 if DexStorageEnabled then
3209 NodeLookup[DexStorage] = {
3210 Object = DexStorage;
3211 Parent = nil;
3212 Index = 0;
3213 Expanded = true;
3214 }
3215 end
3216
3217 if NilStorageEnabled then
3218 NodeLookup[NilStorage] = {
3219 Object = NilStorage;
3220 Parent = nil;
3221 Index = 0;
3222 Expanded = true;
3223 }
3224 end
3225
3226 Connect(game.DescendantAdded,addObject)
3227 Connect(game.DescendantRemoving,removeObject)
3228
3229 if DexStorageEnabled then
3230 --[[
3231 if readfile(getelysianpath().."DexStorage.txt") == nil then
3232 writefile(getelysianpath().."DexStorage.txt","")
3233 end
3234 --]]
3235
3236 buildDexStorage()
3237
3238 Connect(DexStorage.DescendantAdded,addObject)
3239 Connect(DexStorage.DescendantRemoving,removeObject)
3240
3241 Connect(DexStorage.DescendantAdded,updateDexStorage)
3242 Connect(DexStorage.DescendantRemoving,updateDexStorage)
3243 end
3244
3245 if NilStorageEnabled then
3246 Connect(NilStorage.DescendantAdded,addObject)
3247 Connect(NilStorage.DescendantRemoving,removeObject)
3248
3249 local currentTable = get_nil_instances()
3250
3251 spawn(function()
3252 while wait() do
3253 if #currentTable ~= #get_nil_instances() then
3254 currentTable = get_nil_instances()
3255 --NilStorageMain:ClearAllChildren()
3256 for i,v in pairs(get_nil_instances()) do
3257 if v ~= NilStorage and v ~= DexStorage then
3258 pcall(function()
3259 v.Parent = NilStorageMain
3260 end)
3261 --[[
3262 local newNil = v
3263 newNil.Archivable = true
3264 newNil:Clone().Parent = NilStorageMain
3265 --]]
3266 end
3267 end
3268 end
3269 end
3270 end)
3271 end
3272
3273 local function get(o)
3274 return o:GetChildren()
3275 end
3276
3277 local function r(o)
3278 local s,children = pcall(get,o)
3279 if s then
3280 for i = 1,#children do
3281 addObject(children[i],true)
3282 r(children[i])
3283 end
3284 end
3285 end
3286
3287 r(workspace.Parent)
3288 if DexStorageEnabled then
3289 r(DexStorage)
3290 end
3291 if NilStorageEnabled then
3292 r(NilStorage)
3293 end
3294
3295 scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
3296 updateList()
3297end
3298
3299----------------------------------------------------------------
3300----------------------------------------------------------------
3301----------------------------------------------------------------
3302----------------------------------------------------------------
3303---- Actions
3304
3305local actionButtons do
3306 actionButtons = {}
3307
3308 local totalActions = 1
3309 local currentActions = totalActions
3310 local function makeButton(icon,over,name,vis,cond)
3311 local buttonEnabled = false
3312
3313 local button = Create(Icon('ImageButton',icon),{
3314 Name = name .. "Button";
3315 Visible = Option.Modifiable and Option.Selectable;
3316 Position = UDim2.new(1,-(GUI_SIZE+2)*currentActions+2,0.25,-GUI_SIZE/2);
3317 Size = UDim2.new(0,GUI_SIZE,0,GUI_SIZE);
3318 Parent = headerFrame;
3319 })
3320
3321 local tipText = Create('TextLabel',{
3322 Name = name .. "Text";
3323 Text = name;
3324 Visible = false;
3325 BackgroundTransparency = 1;
3326 TextXAlignment = 'Right';
3327 Font = FONT;
3328 FontSize = FONT_SIZE;
3329 Position = UDim2.new(0,0,0,0);
3330 Size = UDim2.new(1,-(GUI_SIZE+2)*totalActions,1,0);
3331 Parent = headerFrame;
3332 })
3333
3334
3335 button.MouseEnter:connect(function()
3336 if buttonEnabled then
3337 button.BackgroundTransparency = 0.9
3338 end
3339 --Icon(button,over)
3340 --tipText.Visible = true
3341 end)
3342 button.MouseLeave:connect(function()
3343 button.BackgroundTransparency = 1
3344 --Icon(button,icon)
3345 --tipText.Visible = false
3346 end)
3347
3348 currentActions = currentActions + 1
3349 actionButtons[#actionButtons+1] = {Obj = button,Cond = cond}
3350 QuickButtons[#actionButtons+1] = {Obj = button,Cond = cond, Toggle = function(on)
3351 if on then
3352 buttonEnabled = true
3353 Icon(button,over)
3354 else
3355 buttonEnabled = false
3356 Icon(button,icon)
3357 end
3358 end}
3359 return button
3360 end
3361
3362 --local clipboard = {}
3363 local function delete(o)
3364 o.Parent = nil
3365 end
3366
3367 makeButton(ACTION_EDITQUICKACCESS,ACTION_EDITQUICKACCESS,"Options",true,function()return true end).MouseButton1Click:connect(function()
3368
3369 end)
3370
3371
3372 -- DELETE
3373 makeButton(ACTION_DELETE,ACTION_DELETE_OVER,"Delete",true,function() return #Selection:Get() > 0 end).MouseButton1Click:connect(function()
3374 if not Option.Modifiable then return end
3375 local list = Selection:Get()
3376 for i = 1,#list do
3377 pcall(delete,list[i])
3378 end
3379 Selection:Set({})
3380 end)
3381
3382 -- PASTE
3383 makeButton(ACTION_PASTE,ACTION_PASTE_OVER,"Paste",true,function() return #Selection:Get() > 0 and #clipboard > 0 end).MouseButton1Click:connect(function()
3384 if not Option.Modifiable then return end
3385 local parent = Selection.List[1] or workspace
3386 for i = 1,#clipboard do
3387 clipboard[i]:Clone().Parent = parent
3388 end
3389 end)
3390
3391 -- COPY
3392 makeButton(ACTION_COPY,ACTION_COPY_OVER,"Copy",true,function() return #Selection:Get() > 0 end).MouseButton1Click:connect(function()
3393 if not Option.Modifiable then return end
3394 clipboard = {}
3395 local list = Selection.List
3396 for i = 1,#list do
3397 table.insert(clipboard,list[i]:Clone())
3398 end
3399 updateActions()
3400 end)
3401
3402 -- CUT
3403 makeButton(ACTION_CUT,ACTION_CUT_OVER,"Cut",true,function() return #Selection:Get() > 0 end).MouseButton1Click:connect(function()
3404 if not Option.Modifiable then return end
3405 clipboard = {}
3406 local list = Selection.List
3407 local cut = {}
3408 for i = 1,#list do
3409 local obj = list[i]:Clone()
3410 if obj then
3411 table.insert(clipboard,obj)
3412 table.insert(cut,list[i])
3413 end
3414 end
3415 for i = 1,#cut do
3416 pcall(delete,cut[i])
3417 end
3418 updateActions()
3419 end)
3420
3421 -- FREEZE
3422 makeButton(ACTION_FREEZE,ACTION_FREEZE,"Freeze",true,function() return true end)
3423
3424 -- ADD/REMOVE STARRED
3425 makeButton(ACTION_ADDSTAR,ACTION_ADDSTAR_OVER,"Star",true,function() return #Selection:Get() > 0 end)
3426
3427 -- STARRED
3428 makeButton(ACTION_STARRED,ACTION_STARRED,"Starred",true,function() return true end)
3429
3430
3431 -- SORT
3432 -- local actionSort = makeButton(ACTION_SORT,ACTION_SORT_OVER,"Sort")
3433end
3434
3435----------------------------------------------------------------
3436----------------------------------------------------------------
3437----------------------------------------------------------------
3438----------------------------------------------------------------
3439---- Option Bindables
3440
3441do
3442 local optionCallback = {
3443 Modifiable = function(value)
3444 for i = 1,#actionButtons do
3445 actionButtons[i].Obj.Visible = value and Option.Selectable
3446 end
3447 cancelReparentDrag()
3448 end;
3449 Selectable = function(value)
3450 for i = 1,#actionButtons do
3451 actionButtons[i].Obj.Visible = value and Option.Modifiable
3452 end
3453 cancelSelectDrag()
3454 Selection:Set({})
3455 end;
3456 }
3457
3458 local bindSetOption = explorerPanel:FindFirstChild("SetOption")
3459 if not bindSetOption then
3460 bindSetOption = Create('BindableFunction',{Name = "SetOption"})
3461 bindSetOption.Parent = explorerPanel
3462 end
3463
3464 bindSetOption.OnInvoke = function(optionName,value)
3465 if optionCallback[optionName] then
3466 Option[optionName] = value
3467 optionCallback[optionName](value)
3468 end
3469 end
3470
3471 local bindGetOption = explorerPanel:FindFirstChild("GetOption")
3472 if not bindGetOption then
3473 bindGetOption = Create('BindableFunction',{Name = "GetOption"})
3474 bindGetOption.Parent = explorerPanel
3475 end
3476
3477 bindGetOption.OnInvoke = function(optionName)
3478 if optionName then
3479 return Option[optionName]
3480 else
3481 local options = {}
3482 for k,v in pairs(Option) do
3483 options[k] = v
3484 end
3485 return options
3486 end
3487 end
3488end
3489
3490function SelectionVar()
3491 return Selection
3492end
3493
3494Input.InputBegan:connect(function(key)
3495 if key.KeyCode == Enum.KeyCode.LeftControl then
3496 HoldingCtrl = true
3497 end
3498 if key.KeyCode == Enum.KeyCode.LeftShift then
3499 HoldingShift = true
3500 end
3501end)
3502
3503Input.InputEnded:connect(function(key)
3504 if key.KeyCode == Enum.KeyCode.LeftControl then
3505 HoldingCtrl = false
3506 end
3507 if key.KeyCode == Enum.KeyCode.LeftShift then
3508 HoldingShift = false
3509 end
3510end)
3511
3512while RbxApi == nil do
3513 RbxApi = GetApiRemote:Invoke()
3514 wait()
3515end
3516
3517explorerFilter.Changed:connect(function(prop)
3518 if prop == "Text" then
3519 rawUpdateList()
3520 end
3521end)
3522
3523CurrentInsertObjectWindow = CreateInsertObjectMenu(
3524 GetClasses(),
3525 "",
3526 false,
3527 function(option)
3528 CurrentInsertObjectWindow.Visible = false
3529 local list = SelectionVar():Get()
3530 for i = 1,#list do
3531 pcall(function() Instance.new(option,list[i]) end)
3532 end
3533 DestroyRightClick()
3534 end
3535)