Files
2025-09-18 17:55:52 -04:00

1009 lines
28 KiB
Lua

local on = false
local showingWires = false
local allWires = {}
---------------
--PLUGIN SETUP-
---------------
self = PluginManager():CreatePlugin()
self.Deactivation:connect(function () Off() end)
toolbar = self:CreateToolbar("Wiring")
toolbarbutton = toolbar:CreateButton("", "Hook up CustomEvent and CustomEventReceivers", "wiring.png")
toolbarbutton.Click:connect(function()
if on then
Off()
else
On()
end
end)
allWiresButton = toolbar:CreateButton("", "Show current connections", "showWires.png")
allWiresButton.Click:connect(function()
if showingWires then
hideAllWires()
else
showAllWires()
end
end)
local g = nil
local indicatorArrow = nil
local indicatorBox = nil
local storedTerminal = nil
local wires = {}
local WHITE_COLOR = Color3.new(1, 1, 1)
local BASE_WIRE_COLOR = BrickColor.new("Really black")
local BASE_WIRE_RADIUS = 0.0625
local HOVER_WIRE_COLOR = BrickColor.new("Really red")
local HOVER_WIRE_RADIUS = 0.125
local SOURCE_BUTTON_TEXT_COLOR = Color3.new(1, .5, 0)
local SOURCE_BUTTON_ICON_TEXTURE = "http://www.watrbx.wtf/asset/?id=55130296"
local SOURCE_BUTTON_ICON_HOVER_TEXTURE = "http://www.watrbx.wtf/asset/?id=56953981"
local SINK_BUTTON_TEXT_COLOR = Color3.new(0, 1, 0)
local SINK_BUTTON_ICON_TEXTURE = "http://www.watrbx.wtf/asset/?id=55130274"
local SINK_BUTTON_ICON_HOVER_TEXTURE = "http://www.watrbx.wtf/asset/?id=56953950"
local SELECT_CONNECTION = nil
local DOWN_ARROW_TEXTURE = "http://www.watrbx.wtf/asset/?id=48972653"
local SOURCE_BADGE_TEXTURE = "http://www.watrbx.wtf/asset/?id=60730993"
local SINK_BADGE_TEXTURE = "http://www.watrbx.wtf/asset/?id=61334830"
local PENDING_LEAVE_CALLBACK = nil
local receiverTable = {}
local eventTable = {}
local adornmentTable = {}
local receiverBadgeCount = {}
local eventBadgeCount = {}
self:GetMouse().Button1Down:connect(function ()
local target = self:GetMouse().Target
if target ~= nil then
while target.Parent ~= game.Workspace do
target = target.Parent
end
end
game.Selection:Set({target})
end)
self:GetMouse().KeyDown:connect(function (key)
if string.byte(key) == 27 then
game.Selection:Set({})
end
end)
function getIndicator()
if indicatorArrow == nil then
indicatorArrow = Instance.new("BillboardGui", game:GetService("CoreGui"))
indicatorArrow.Active = true
indicatorArrow.AlwaysOnTop = true
indicatorArrow.Size = UDim2.new(4, 0, 4, 0)
indicatorArrow.StudsOffset = Vector3.new(0, 2, 0)
local frame = Instance.new("Frame", indicatorArrow)
frame.Active = true
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 0, 1, 0)
local arrow = Instance.new("ImageLabel", frame)
arrow.BackgroundTransparency = 1
arrow.Image = DOWN_ARROW_TEXTURE
arrow.Size = UDim2.new(1, 0, 1, 0)
end
return indicatorArrow
end
function getIndicatorBox()
if indicatorBox == nil then
indicatorBox = Instance.new("SelectionBox", game:GetService("CoreGui"))
indicatorBox.Color = BrickColor.new("New Yeller")
indicatorBox.Adornee = nil
end
return indicatorBox
end
function refreshScreenGui()
if g ~= nil then
g:Remove()
end
for idx, wire in ipairs(wires) do
wire:Remove()
end
g = Instance.new("ScreenGui", game:GetService("CoreGui"))
getIndicator().Adornee = nil
getIndicatorBox().Adornee = nil
if storedTerminal ~= nil then
handleStoredTerminal(g)
end
selected = game.Selection:Get()
if #selected == 0 then
return
elseif #selected > 1 then
handleContainer(g, selected)
elseif selected[1]:IsA("CustomEvent") then
handleTerminal(g, selected[1], function(customEvent) return customEvent:GetAttachedReceivers() end)
getIndicatorBox().Adornee = selected.Parent
elseif selected[1]:IsA("CustomEventReceiver") then
handleTerminal(g, selected[1], function(customEventReceiver) return { customEventReceiver.Source } end)
getIndicatorBox().Adornee = selected.Parent
elseif selected[1] ~= game.Workspace then
handleContainer(g, selected)
end
end
function On()
RbxGui = LoadLibrary("RbxGui")
setUpConfigurationService()
self:Activate(true)
SELECT_CONNECTION = game.Selection.SelectionChanged:connect(refreshScreenGui)
refreshScreenGui()
toolbarbutton:SetActive(true)
on = true
end
function Off()
destroyConfigurationService()
storedTerminal = nil
if g ~= nil then
g:Remove()
g = nil
end
for idx, wire in ipairs(wires) do
wire:Remove()
end
wires = {}
SELECT_CONNECTION:disconnect()
getIndicator().Adornee = nil
toolbarbutton:SetActive(false)
on = false
end
function IsChildOfWorkspace(instance)
return instance ~= nil and (instance == game.Workspace or IsChildOfWorkspace(instance.Parent))
end
function findModel(part)
local origPart = part
while part ~= nil do
if part.className == "Model" then
return part
elseif part.Name == "Workspace" or part.Name == "game" then
return origPart
end
part = part.Parent
end
return nil
end
----------------------------------------------------------
-- Left Side Popup when CustomEvent/Receiver is selected
function applyTextSize(label, text)
label.Size = UDim2.new(0, label.TextBounds.x, 0, label.TextBounds.y)
end
function handleConnect(terminal)
if storedTerminal == nil then
storedTerminal = terminal
return
else
local storedIsSource = storedTerminal:IsA("CustomEvent")
local newIsSource = terminal:IsA("CustomEvent")
if storedIsSource and not newIsSource then
terminal.Source = storedTerminal
storedTerminal = nil
game:GetService("ChangeHistoryService"):SetWaypoint("Wiring")
elseif not storedIsSource and newIsSource then
storedTerminal.Source = terminal
storedTerminal = nil
game:GetService("ChangeHistoryService"):SetWaypoint("Wiring")
else
storedTerminal = terminal
end
end
end
function disconnectHelper(terminal1, terminal2)
if terminal1:IsA("CustomEvent") then
terminal2.Source = nil
else
terminal1.Source = nil
end
game:GetService("ChangeHistoryService"):SetWaypoint("Disconnect wiring")
end
function createModelLine(frame, yOffset, terminal)
local model = findParentUnderWorkspace(terminal)
local button = Instance.new("TextButton", frame)
button.Text = "Top parent: " .. model.Name
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.BackgroundTransparency = .5
button.TextColor3 = WHITE_COLOR
button.BorderSizePixel = 0
applyTextSize(button)
button.Position = UDim2.new(0, 0, 0, yOffset)
button.MouseButton1Click:connect(function () game.Selection:Set({model}) end)
return button
end
function createParentLine(frame, yOffset, terminal)
local parent = terminal.Parent
local button = Instance.new("TextButton", frame)
button.Text = "Parent: " .. parent.Name
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.BackgroundTransparency = .5
button.TextColor3 = WHITE_COLOR
button.BorderSizePixel = 0
applyTextSize(button)
button.Position = UDim2.new(0, 0, 0, yOffset)
button.MouseButton1Click:connect(function () game.Selection:Set({parent}) end)
return button
end
function createTerminalElement(type, frame, font, yOffset, terminal, dontShowParent)
local button = Instance.new(type, frame)
local icon = Instance.new("ImageLabel", button)
icon.Position = UDim2.new(0, 0, 0, -8)
icon.Size = UDim2.new(0, 35, 0 , 35)
icon.BackgroundTransparency = 1
if dontShowParent then
button.Text = terminal.Name
else
button.Text = terminal.Name .. " (" .. terminal.Parent.Name .. ")"
end
button.TextXAlignment = 1 -- right
button.Font = font
button.FontSize = Enum.FontSize.Size18
button.BorderSizePixel = 0
button.BackgroundTransparency = .5
applyTextSize(button)
button.Position = UDim2.new(0, 0, 0, yOffset)
if terminal:IsA("CustomEvent") then
button.TextColor3 = SOURCE_BUTTON_TEXT_COLOR
icon.Image = SOURCE_BUTTON_ICON_TEXTURE
else
button.TextColor3 = SINK_BUTTON_TEXT_COLOR
icon.Image = SINK_BUTTON_ICON_TEXTURE
end
button.Size = UDim2.new(0, button.Size.X.Offset + 35 + 10, 0, button.Size.Y.Offset)
return button
end
function createTextLabelHeader(labelParent, yOffset, text)
local label = Instance.new("TextLabel", labelParent)
label.Text = text
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size18
label.TextColor3 = WHITE_COLOR
label.BorderSizePixel = 0
label.BackgroundTransparency = 1
label.Position = UDim2.new(0, 0, 0, yOffset)
applyTextSize(label)
return label
end
function createTextLabel(labelParent, yOffset, childName, parentName)
local label = Instance.new("TextButton", labelParent)
label.Text = childName .. " (" .. parentName .. ")"
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size18
label.TextColor3 = WHITE_COLOR
label.BorderSizePixel = 0
label.BackgroundTransparency = .5
-- label.Position = UDim2.new(0, 0, 0, yOffset)
applyTextSize(label)
return label
end
function createDisconnectButton(frame, xOffset, yOffset, rcb)
local button = Instance.new("TextButton", frame)
button.Text = "Disconnect"
button.Font = Enum.Font.ArialBold
button.FontSize = Enum.FontSize.Size18
button.TextColor3 = WHITE_COLOR
applyTextSize(button)
button.BorderSizePixel = 0
button.BackgroundTransparency = 0.5
button.Position = UDim2.new(1, -button.Size.X.Offset - 2, 0, 0)
button.MouseButton1Click:connect(rcb)
return button
end
function createWire(terminal1, terminal2)
local from = nil
local to = nil
if terminal1:IsA("CustomEvent") then
from = terminal1.Parent
to = terminal2.Parent
else
from = terminal2.Parent
to = terminal1.Parent
end
local wire = Instance.new("FloorWire", game:GetService("CoreGui"))
wire.From = from
wire.To = to
wire.Color = BASE_WIRE_COLOR
wire.WireRadius = BASE_WIRE_RADIUS
table.insert(wires, wire)
if showingWires then
local wireCopy = Instance.new("FloorWire", game:GetService("CoreGui"))
wireCopy.From = wire.From
wireCopy.To = wire.To
wireCopy.Color = wire.Color
wireCopy.WireRadius = wire.WireRadius
table.insert(allWires, wireCopy)
end
return wire
end
function createNoneLabel(frame, yOffset)
local label = Instance.new("TextLabel", frame)
label.Text = "-- none --"
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size18
label.TextColor3 = WHITE_COLOR
label.BorderSizePixel = 0
label.BackgroundTransparency = 1
label.Position = UDim2.new(0, 0, 0, yOffset)
applyTextSize(label)
return label
end
function createConnectButton(frame, yOffset, terminal)
local button = Instance.new("TextButton", frame)
if storedTerminal == nil then
button.Text = "Add Connection"
else
local storedIsSource = storedTerminal:IsA("CustomEvent")
local terminalIsSource = terminal:IsA("CustomEvent")
if storedIsSource ~= terminalIsSource then
button.Text = "Connect to " .. storedTerminal.Name .. " (" .. storedTerminal.Parent.Name .. ")"
else
button.Text = "Add Connection"
end
end
button.Font = Enum.Font.ArialBold
button.FontSize = Enum.FontSize.Size18
button.TextColor3 = WHITE_COLOR
applyTextSize(button)
button.BorderSizePixel = 0
button.BackgroundTransparency = 0.5
button.Position = UDim2.new(0, 0, 0, yOffset)
return button
end
function handleTerminal(screenGui, terminal, getAttached)
local frame = Instance.new("Frame", screenGui)
frame.Style = Enum.FrameStyle.RobloxRound
frame.Visible = true
local yOffset = 0
local maxX = 0
local title = createTerminalElement("TextLabel", frame, Enum.Font.ArialBold, yOffset, terminal, true)
title.BackgroundTransparency = 1
yOffset = yOffset + title.Size.Y.Offset + 2
maxX = math.max(maxX, title.Size.X.Offset)
local modelLine = createModelLine(frame, yOffset, terminal)
yOffset = yOffset + modelLine.Size.Y.Offset + 2
maxX = math.max(maxX, modelLine.Size.X.Offset)
local parentLine = createParentLine(frame, yOffset, terminal)
yOffset = yOffset + parentLine.Size.Y.Offset + 12.5
maxX = math.max(maxX, parentLine.Size.X.Offset)
local header = createTextLabelHeader(frame, yOffset, "Connections")
yOffset = yOffset + header.Size.Y.Offset + 3
maxX = math.max(maxX, header.Size.X.Offset)
local attached = getAttached(terminal)
local scrollHolder = Instance.new("Frame", frame)
local scrollYOffset = 0
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame()
scrollFrame.Parent = scrollHolder
scrollUp.Parent = scrollHolder
scrollDown.Parent = scrollHolder
for idx, other in ipairs(attached) do
if IsChildOfWorkspace(other) then
local rowFrame = Instance.new("Frame", scrollFrame)
rowFrame.BackgroundTransparency = 1
rowFrame.BorderSizePixel = 0
local label = createTextLabel(rowFrame, scrollYOffset, other.Name, other.Parent.Name)
label.MouseButton1Click:connect(function () game.Selection:Set({other}) end)
label.MouseEnter:connect(function() getIndicator().Adornee = other.Parent end)
label.MouseLeave:connect(function() getIndicator().Adornee = nil end)
local button = createDisconnectButton(rowFrame, label.Size.X.Offset, scrollYOffset,
function()
disconnectHelper(terminal, other)
refreshScreenGui()
end)
local wire = createWire(terminal, other)
label.MouseEnter:connect(function() wire.WireRadius = HOVER_WIRE_RADIUS end)
label.MouseLeave:connect(function() wire.WireRadius = BASE_WIRE_RADIUS end)
button.MouseEnter:connect(function()
wire.Color = HOVER_WIRE_COLOR
wire.WireRadius = HOVER_WIRE_RADIUS
end)
button.MouseLeave:connect(function()
wire.Color = BASE_WIRE_COLOR
wire.WireRadius = BASE_WIRE_RADIUS
end)
rowFrame.Size = UDim2.new(1, 0, 0, label.Size.Y.Offset + 5)
scrollYOffset = scrollYOffset + rowFrame.Size.Y.Offset
maxX = math.max(maxX, label.Size.X.Offset + 3 + button.Size.X.Offset)
end
end
if #attached == 0 then
local label = createNoneLabel(frame, yOffset)
scrollYOffset = scrollYOffset + label.Size.Y.Offset + 3
maxX = math.max(maxX, label.Size.X.Offset)
end
if #attached < 4 then
scrollUp.Visible = false
scrollDown.Visible = false
end
scrollFrame.Size = UDim2.new(1, -scrollUp.Size.X.Offset, 1, 0)
scrollUp.Position = UDim2.new(1, -scrollUp.Size.X.Offset, 0, 0)
scrollDown.Position = UDim2.new(1, -scrollDown.Size.X.Offset, 1, -scrollDown.Size.Y.Offset)
scrollHolder.Position = UDim2.new(0, 0, 0, yOffset)
scrollHolder.Size = UDim2.new(1, 0, 0, math.min(70, scrollYOffset))
scrollHolder.BackgroundTransparency = 1
scrollHolder.BorderSizePixel = 0
scrollFrame.BackgroundTransparency = 1
scrollFrame.BorderSizePixel = 0
-- give room for scroll bars
maxX = maxX + scrollUp.Size.X.Offset + 3
yOffset = yOffset + scrollHolder.Size.Y.Offset
-- add another gap before the connect button
yOffset = yOffset + 12.5
local connect = createConnectButton(frame, yOffset, terminal)
connect.MouseButton1Click:connect(function ()
handleConnect(terminal)
refreshScreenGui()
end)
maxX = math.max(maxX, connect.Size.X.Offset)
frame.Size = UDim2.new(0, maxX + 17.5, 0, yOffset + connect.Size.Y.Offset + 17.5)
recalculateScroll()
frame.BackgroundTransparency = 0.5
delay(0, function()
local etime = time() + 10
while time() < etime do
recalculateScroll()
wait(.5)
end
end)
end
--------------------------------------------------
-- Left Side Popup when non-terminal is selected
function collectTerminalsHelper(root, terminals)
if root:IsA("CustomEvent") or root:IsA("CustomEventReceiver") then
table.insert(terminals, root)
end
for idx, child in ipairs(root:GetChildren()) do
collectTerminals(child, terminals)
end
end
function collectTerminals(root, terminals)
collectTerminalsHelper(root, terminals)
table.sort(terminals, function (item1, item2)
local item1IsSource = item1:IsA("CustomEvent")
local item2IsSource = item2:IsA("CustomEvent")
if item1IsSource and not item2IsSource then
return true
elseif item2IsSource and not item1IsSource then
return false
else
return item1.Name < item2.Name
end
end)
end
function handleContainer(screenGui, root)
local frame = Instance.new("Frame", screenGui)
frame.Style = Enum.FrameStyle.RobloxRound
frame.Visible = true
local yOffset = 0
local maxX = 0
local header = createTextLabelHeader(frame, yOffset, "Custom Events and Receivers")
yOffset = yOffset + header.Size.Y.Offset + 3
maxX = header.Size.X.Offset
local terminals = {}
for idx, sel in ipairs(root) do
if sel ~= game.Workspace then
collectTerminals(sel, terminals)
end
end
local scrollHolder = Instance.new("Frame", frame)
scrollHolder.BackgroundTransparency = 1
scrollHolder.BorderSizePixel = 0
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame()
scrollFrame.BackgroundTransparency = 1
scrollFrame.BorderSizePixel = 0
scrollFrame.Parent = scrollHolder
scrollUp.Parent = scrollHolder
scrollDown.Parent = scrollHolder
scrollHolder.Position = UDim2.new(0, 0, 0, yOffset)
for idx, terminal in ipairs(terminals) do
local button = createTerminalElement("TextButton", frame, Enum.Font.Arial, yOffset, terminal)
button.MouseButton1Click:connect(function ()
game.Selection:Set({terminal})
end)
button.MouseEnter:connect(function () getIndicator().Adornee = terminal.Parent end)
button.MouseLeave:connect(function () getIndicator().Adornee = nil end)
yOffset = yOffset + button.Size.Y.Offset + 3
maxX = math.max(maxX, button.Size.X.Offset)
end
if #terminals == 0 then
local label = createNoneLabel(frame, yOffset)
yOffset = yOffset + label.Size.Y.Offset + 3
maxX = math.max(maxX, label.Size.X.Offset)
end
if #terminals < 2 then
scrollUp.Visible = false
scrollDown.Visible = false
end
scrollFrame.Size = UDim2.new(1, -scrollUp.Size.X.Offset, 1, 0)
scrollUp.Position = UDim2.new(1, -scrollUp.Size.X.Offset, 0, 0)
scrollDown.Position = UDim2.new(1, -scrollDown.Size.X.Offset, 1, -scrollDown.Size.Y.Offset)
scrollHolder.Size = UDim2.new(1, 0, 0, yOffset - (header.Size.Y.Offset + 3))
recalculateScroll()
maxX = maxX + scrollUp.Size.X.Offset
frame.Size = UDim2.new(0, maxX + 17.5, 0, yOffset + 17.5)
frame.BackgroundTransparency = 0.5
end
----------------------------------------------------------
-- Right side gui when connecting a CustomEvent/Receiver
function findParentUnderWorkspace(instance)
while instance.Parent ~= game.Workspace and instance.Parent ~= nil do
instance = instance.Parent
end
return instance
end
function createCancelButton(frame, yOffset)
local button = Instance.new("TextButton", frame)
button.Text = "Cancel"
button.Font = Enum.Font.ArialBold
button.FontSize = Enum.FontSize.Size18
button.TextColor3 = WHITE_COLOR
applyTextSize(button)
button.BorderSizePixel = 0
button.BackgroundTransparency = 0.5
button.Position = UDim2.new(1, -button.Size.X.Offset, 0, yOffset)
button.MouseButton1Click:connect(function ()
storedTerminal = nil
refreshScreenGui()
end)
return button
end
function handleStoredTerminal(screenGui)
if storedTerminal == nil then return end
local frame = Instance.new("Frame", screenGui)
frame.Style = Enum.FrameStyle.RobloxRound
frame.Visible = true
local yOffset = 0
local maxX = 0
local terminalButton = createTerminalElement("TextButton", frame, Enum.Font.Arial, yOffset, storedTerminal)
terminalButton.MouseButton1Click:connect(function () game.Selection:Set({storedTerminal}) end)
yOffset = yOffset + terminalButton.Size.Y.Offset + 3
maxX = math.max(maxX, terminalButton.Size.X.Offset)
local cancelButton = createCancelButton(frame, yOffset)
yOffset = yOffset + cancelButton.Size.Y.Offset
maxX = math.max(maxX, cancelButton.Size.X.Offset)
frame.Size = UDim2.new(0, maxX + 17.5, 0, yOffset + 17.5)
frame.Position = UDim2.new(1, -frame.Size.X.Offset, 0, 0)
frame.BackgroundTransparency = 0.5
end
------------------------
-- Show/Hide All Wires
function showWiresHelper(terminal, othersFunc, completedTerminals)
local terminalIsSource = terminal:IsA("CustomEvent")
for idx, other in ipairs(othersFunc(terminal)) do
if completedTerminals[other] == nil and IsChildOfWorkspace(other) then
local wire = Instance.new("FloorWire", game:GetService("CoreGui"))
if terminalIsSource then
wire.From = terminal.Parent
wire.To = other.Parent
else
wire.From = other.Parent
wire.To = terminal.Parent
end
wire.Color = BASE_WIRE_COLOR
wire.WireRadius = BASE_WIRE_RADIUS
table.insert(allWires, wire)
end
end
completedTerminals[terminal] = true
end
function showAllWires()
allWiresButton:SetActive(true)
terminals = {}
collectTerminals(game.Workspace, terminals)
local completedTerminals = {}
for idx, terminal in ipairs(terminals) do
local othersFunc = nil
if terminal:IsA("CustomEvent") then
othersFunc = function (source) return source:GetAttachedReceivers() end
elseif terminal:IsA("CustomEventReceiver") then
othersFunc = function (sink) return { sink.Source } end
end
if othersFunc ~= nil then
showWiresHelper(terminal, othersFunc, completedTerminals)
end
end
showingWires = true
end
function hideAllWires()
allWiresButton:SetActive(false)
for idx, wire in ipairs(allWires) do
wire:Remove()
end
allWires = {}
showingWires = false
end
function refreshAllWires()
hideAllWires()
showAllWires()
end
game.DescendantAdded:connect(function (newChild)
if newChild:IsA("CustomEvent") or newChild:IsA("CustomEventReceiver") then
-- refresh screen gui now, because we may be showing the parent dialog
if on then refreshScreenGui() end
-- Attach a listener to the terminal to refresh Guis when properties changed.
-- This will catch re-wiring because connection changes show up as property
-- changes as well.
newChild.Changed:connect(function()
if on then
if showingWires then
hideAllWires()
showAllWires()
end
refreshScreenGui()
end
end)
end
end)
game.DescendantRemoving:connect(function (removed)
-- when a descendant is removed, refresh the screen gui
if on and (removed:IsA("CustomEvent") or removed:IsA("CustomEventReceiver")) then
refreshScreenGui()
end
end)
function findBillboard(guiTable)
if not guiTable then return end
for i = 1, #guiTable do
if guiTable[i] and guiTable[i]:IsA("BillboardGui") then
return guiTable[i]
end
end
end
function getBillboard(adornee)
local guiKey = adornee
local billboard = findBillboard(adornmentTable[guiKey])
if not billboard then
local screen = Instance.new("BillboardGui")
screen.Name = adornee.Name .. "BadgeGUI"
screen.Size = UDim2.new(1.5,0,1.5,0)
screen.Enabled = true
screen.Active = true
screen.AlwaysOnTop = true
screen.ExtentsOffset = Vector3.new(0,0,0)
screen.Adornee = adornee
screen.Parent = game:GetService("CoreGui")
if not adornmentTable[guiKey] then return end
table.insert(adornmentTable[guiKey],screen)
local badgeFrame = Instance.new("Frame")
badgeFrame.Name = "BadgeFrame"
badgeFrame.Size = UDim2.new(2,0,1,0)
badgeFrame.Position = UDim2.new(-0.5,0,0,0)
badgeFrame.BackgroundTransparency = 1
badgeFrame.Parent = screen
return screen
end
return billboard
end
function repositionBadges(badgeFrame)
local badges = badgeFrame:GetChildren()
if #badges == 1 then
badges[1].Position = UDim2.new(0.25,0,0,0)
elseif #badges == 2 then
badges[1].Position = UDim2.new(0,0,0,0)
badges[2].Position = UDim2.new(0.5,0,0)
end
end
function hasBadge(adornee, type)
local screen = getBillboard(adornee)
return screen:FindFirstChild(type .. "Badge",true)
end
function removeBadge(adornee, type)
local screen = getBillboard(adornee)
local badge = screen:FindFirstChild(type .. "Badge",true)
if badge then badge:remove() end
end
function createBadge(adornee,type)
local screen = getBillboard(adornee)
local wiringBadge = Instance.new("ImageLabel")
wiringBadge.Name = type .. "Badge"
wiringBadge.BackgroundTransparency = 1
if type == "Receiver" then
wiringBadge.Image = SOURCE_BADGE_TEXTURE
else
wiringBadge.Image = SINK_BADGE_TEXTURE
end
wiringBadge.Position = UDim2.new(0.25,0,0,0)
wiringBadge.Size = UDim2.new(0.5,0,1,0)
wiringBadge.Parent = screen.BadgeFrame
wiringBadge.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if wiringBadge.AbsoluteSize.X < 10 then
wiringBadge.Visible = false
else
wiringBadge.Visible = true
end
end
end)
repositionBadges(screen.BadgeFrame)
end
function upAdorneeCount(adornee,type)
local typeLower = string.lower(type)
if typeLower == "receiver" then
if not receiverBadgeCount[adornee] then
receiverBadgeCount[adornee] = 1
else
receiverBadgeCount[adornee] = receiverBadgeCount[adornee] + 1
end
elseif typeLower == "event" then
if not eventBadgeCount[adornee] then
eventBadgeCount[adornee] = 1
else
eventBadgeCount[adornee] = eventBadgeCount[adornee] + 1
end
end
end
function downAdorneeCount(adornee,type)
local typeLower = string.lower(type)
if typeLower == "receiver" then
if receiverBadgeCount[adornee] then
receiverBadgeCount[adornee] = receiverBadgeCount[adornee] - 1
if receiverBadgeCount[adornee] < 1 then
receiverBadgeCount[adornee] = nil
end
end
elseif typeLower == "event" then
if eventBadgeCount[adornee] then
eventBadgeCount[adornee] = eventBadgeCount[adornee] - 1
if eventBadgeCount[adornee] < 1 then
eventBadgeCount[adornee] = nil
end
end
end
end
function createAdornment(adornee,adornColor,type)
upAdorneeCount(adornee,type)
if receiverBadgeCount[adornee] == 1 or eventBadgeCount[adornee] == 1 then
local box = Instance.new("SelectionBox")
box.Color = adornColor
box.Name = adornee.Name .. "Selection" .. tostring(type)
box.Adornee = adornee
box.Transparency = 0.5
box.Parent = game:GetService("CoreGui")
if not adornmentTable[adornee] then
adornmentTable[adornee] = {}
end
table.insert(adornmentTable[adornee],box)
if not hasBadge(adornee,type) then
createBadge(adornee,type)
end
end
end
function doRemoveAdornment(adornee, type)
local key = adornee
if not adornmentTable[key] then return end
for i = 1, #adornmentTable[key] do
if adornmentTable[key] and adornmentTable[key][i] then
if string.find(adornmentTable[key][i].Name,type) then
adornmentTable[key][i]:remove()
adornmentTable[key][i] = nil
end
end
end
end
function removeAdornment(adornee, type)
downAdorneeCount(adornee,type)
if type == "Receiver" then
if not receiverBadgeCount[adornee]then
removeBadge(adornee, type)
doRemoveAdornment(adornee, type)
end
elseif type == "Event" then
if not eventBadgeCount[adornee] then
removeBadge(adornee, type)
doRemoveAdornment(adornee, type)
end
end
end
function eventReceiverAdded(receiver,wirePartCount)
if isRestricted then
if not inBaseplate(receiver) then return wirePartCount end
end
receiverTable[receiver] = findModel(receiver.Parent)
createAdornment(receiverTable[receiver], BrickColor.new("Lime green"), "Receiver")
if wirePartCount then
return wirePartCount + 1
else
return 0
end
end
function eventAdded(event,wirePartCount)
if isRestricted then
if not inBaseplate(event) then return wirePartCount end
end
eventTable[event] = findModel(event.Parent)
createAdornment(eventTable[event], BrickColor.new("Bright orange"), "Event")
if wirePartCount then
return wirePartCount + 1
else
return 0
end
end
function eventReceiverRemoved(receiver)
if not receiverTable[receiver] then return end
removeAdornment(receiverTable[receiver],"Receiver")
receiverTable[receiver] = nil
end
function eventRemoved(event)
if not eventTable[event] then return end
removeAdornment(eventTable[event], "Event")
eventTable[event] = nil
end
function setUpConfigurationService()
local wirePartCount = 0
ServiceConnections = {}
local collectionService = game:GetService("CollectionService")
-- first lets check if anything already exists
local receivers = collectionService:GetCollection("CustomEventReceiver")
if receivers then
for pos, receiver in pairs(receivers) do
wirePartCount = eventReceiverAdded(receiver, wirePartCount)
end
end
local events = collectionService:GetCollection("CustomEvent")
if events then
for pos, event in pairs(events) do
wirePartCount = eventAdded(event, wirePartCount)
end
end
-- Now lets listen for any future additions/removals
ServiceConnections[#ServiceConnections+1] = collectionService.ItemAdded:connect(function(instance)
if instance:IsA("CustomEventReceiver") then
eventReceiverAdded(instance)
elseif instance:IsA("CustomEvent") then
eventAdded(instance)
end
end)
ServiceConnections[#ServiceConnections+1] = collectionService.ItemRemoved:connect(function(instance)
if instance:IsA("CustomEventReceiver") then
eventReceiverRemoved(instance)
elseif instance:IsA("CustomEvent") then
eventRemoved(instance)
end
end)
return wirePartCount
end
function destroyConfigurationService()
-- first lets destroy the collection service
for index, connection in pairs(ServiceConnections) do
connection:disconnect()
end
ServiceConnections = {}
-- now lets remove all of our collection service objects that were generated
for event, object in pairs(eventTable) do
eventRemoved(event)
end
for eventReceiver, object in pairs(receiverTable) do
eventReceiverRemoved(eventReceiver)
end
end