azul-sync 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/README.md +142 -0
- package/dist/build.d.ts +19 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +92 -0
- package/dist/build.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +397 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +105 -0
- package/dist/config.js.map +1 -0
- package/dist/fs/fileWriter.d.ts +100 -0
- package/dist/fs/fileWriter.d.ts.map +1 -0
- package/dist/fs/fileWriter.js +342 -0
- package/dist/fs/fileWriter.js.map +1 -0
- package/dist/fs/treeManager.d.ts +84 -0
- package/dist/fs/treeManager.d.ts.map +1 -0
- package/dist/fs/treeManager.js +365 -0
- package/dist/fs/treeManager.js.map +1 -0
- package/dist/fs/watcher.d.ts +39 -0
- package/dist/fs/watcher.d.ts.map +1 -0
- package/dist/fs/watcher.js +120 -0
- package/dist/fs/watcher.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +349 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/httpPolling.d.ts +56 -0
- package/dist/ipc/httpPolling.d.ts.map +1 -0
- package/dist/ipc/httpPolling.js +171 -0
- package/dist/ipc/httpPolling.js.map +1 -0
- package/dist/ipc/messages.d.ts +112 -0
- package/dist/ipc/messages.d.ts.map +1 -0
- package/dist/ipc/messages.js +5 -0
- package/dist/ipc/messages.js.map +1 -0
- package/dist/ipc/server.d.ts +50 -0
- package/dist/ipc/server.d.ts.map +1 -0
- package/dist/ipc/server.js +168 -0
- package/dist/ipc/server.js.map +1 -0
- package/dist/pack.d.ts +19 -0
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +225 -0
- package/dist/pack.js.map +1 -0
- package/dist/push.d.ts +43 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +532 -0
- package/dist/push.js.map +1 -0
- package/dist/rojo.d.ts +9 -0
- package/dist/rojo.d.ts.map +1 -0
- package/dist/rojo.js +114 -0
- package/dist/rojo.js.map +1 -0
- package/dist/snapshot/rojo.d.ts +39 -0
- package/dist/snapshot/rojo.d.ts.map +1 -0
- package/dist/snapshot/rojo.js +364 -0
- package/dist/snapshot/rojo.js.map +1 -0
- package/dist/snapshot.d.ts +23 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +132 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/sourcemap/generator.d.ts +78 -0
- package/dist/sourcemap/generator.d.ts.map +1 -0
- package/dist/sourcemap/generator.js +351 -0
- package/dist/sourcemap/generator.js.map +1 -0
- package/dist/sourcemap/propertyLoader.d.ts +19 -0
- package/dist/sourcemap/propertyLoader.d.ts.map +1 -0
- package/dist/sourcemap/propertyLoader.js +131 -0
- package/dist/sourcemap/propertyLoader.js.map +1 -0
- package/dist/util/id.d.ts +9 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +14 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/log.d.ts +13 -0
- package/dist/util/log.d.ts.map +1 -0
- package/dist/util/log.js +51 -0
- package/dist/util/log.js.map +1 -0
- package/docs/assets/azul-logo.pdn +0 -0
- package/docs/assets/logo-200px.png +0 -0
- package/docs/assets/logo.png +0 -0
- package/docs/assets/plugin/toolbox.png +0 -0
- package/docs/assets/synced.png +0 -0
- package/package.json +41 -0
- package/plugin/README.md +54 -0
- package/plugin/sourcemap.json +264 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Actor/AzulSync.server.luau +905 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/AzulService.luau +1010 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Config.luau +29 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Enums.luau +11 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/CollapsibleTitledSection.luau +214 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ColorPicker.luau +360 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/CustomTextButton.luau +170 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/DropdownMenu.luau +363 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/HorizontalLine.luau +43 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ImageButtonWithText.luau +181 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledCheckbox.luau +295 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledColorInputPicker.luau +294 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledMultiChoice.luau +163 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledNumberInput.luau +312 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledRadioButton.luau +55 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledSlider.luau +151 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledTextInput.luau +222 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledToggleButton.luau +73 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/StatefulImageButton.luau +125 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticalScrollingFrame.luau +100 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticalSpacer.luau +35 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticallyScalingListFrame.luau +107 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/GuiUtilities.luau +429 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/RbxGui.luau +4363 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/UI.luau +425 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/WebSocketClient.luau +161 -0
- package/src/build.ts +120 -0
- package/src/cli.ts +496 -0
- package/src/config.ts +170 -0
- package/src/fs/fileWriter.ts +414 -0
- package/src/fs/treeManager.ts +458 -0
- package/src/fs/watcher.ts +142 -0
- package/src/index.ts +450 -0
- package/src/ipc/httpPolling.ts +214 -0
- package/src/ipc/messages.ts +159 -0
- package/src/ipc/server.ts +196 -0
- package/src/pack.ts +309 -0
- package/src/push.ts +726 -0
- package/src/snapshot/rojo.ts +467 -0
- package/src/snapshot.ts +161 -0
- package/src/sourcemap/generator.ts +504 -0
- package/src/sourcemap/propertyLoader.ts +195 -0
- package/src/util/id.ts +15 -0
- package/src/util/log.ts +94 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
local Enums = require(script.Parent.Enums)
|
|
2
|
+
|
|
3
|
+
configTable = {
|
|
4
|
+
WS_URL = "ws://localhost:8080",
|
|
5
|
+
HEARTBEAT_INTERVAL = 30,
|
|
6
|
+
LIST_TYPE = Enums.listType.WHITELIST, -- or BLACKLIST
|
|
7
|
+
SERVICE_LIST = {
|
|
8
|
+
"Workspace",
|
|
9
|
+
"Lighting",
|
|
10
|
+
"ReplicatedFirst",
|
|
11
|
+
"ReplicatedStorage",
|
|
12
|
+
"ServerScriptService",
|
|
13
|
+
"ServerStorage",
|
|
14
|
+
"StarterGui",
|
|
15
|
+
"StarterPack",
|
|
16
|
+
"StarterPlayer",
|
|
17
|
+
"SoundService",
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
EXCLUDED_PARENTS = {
|
|
21
|
+
"ServerStorage.RecPlugins", -- Folder managed by "Eye" plugin. It updates the sourcemap thousands of times. We don't need to track this.
|
|
22
|
+
"Workspace.Surface Converter Storage", -- Folder managed by "Surface Converter" plugin. We don't need to track it.
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
DEBUG_MODE = false,
|
|
26
|
+
SILENT_MODE = false,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return configTable
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
----------------------------------------
|
|
2
|
+
--
|
|
3
|
+
-- CollapsibleTitledSectionClass
|
|
4
|
+
--
|
|
5
|
+
-- Creates a section with a title label:
|
|
6
|
+
--
|
|
7
|
+
-- "SectionXXX"
|
|
8
|
+
-- "TitleBarVisual"
|
|
9
|
+
-- "Contents"
|
|
10
|
+
--
|
|
11
|
+
-- Requires "parent" and "sectionName" parameters and returns the section and its contentsFrame
|
|
12
|
+
-- The entire frame will resize dynamically as contents frame changes size.
|
|
13
|
+
--
|
|
14
|
+
-- "autoScalingList" is a boolean that defines wheter or not the content frame automatically resizes when children are added.
|
|
15
|
+
-- This is important for cases when you want minimize button to push or contract what is below it.
|
|
16
|
+
--
|
|
17
|
+
-- Both "minimizeable" and "minimizedByDefault" are false by default
|
|
18
|
+
-- These parameters define if the section will have an arrow button infront of the title label,
|
|
19
|
+
-- which the user may use to hide the section's contents
|
|
20
|
+
--
|
|
21
|
+
----------------------------------------
|
|
22
|
+
GuiUtilities = require("../GuiUtilities")
|
|
23
|
+
|
|
24
|
+
local kArrowSpriteSheet = "rbxasset://textures/StudioSharedUI/arrowSpritesheet.png"
|
|
25
|
+
local kRightButtonRectSize = Vector2.new(12, 12)
|
|
26
|
+
local kRightButtonRectOffset = Vector2.new(12, 0)
|
|
27
|
+
local kDownButtonRectSize = Vector2.new(12, 12)
|
|
28
|
+
local kDownButtonRectOffset = Vector2.new(24, 0)
|
|
29
|
+
|
|
30
|
+
local kArrowSize = 9
|
|
31
|
+
local kDoubleClickTimeSec = 0.5
|
|
32
|
+
|
|
33
|
+
CollapsibleTitledSectionClass = {}
|
|
34
|
+
CollapsibleTitledSectionClass.__index = CollapsibleTitledSectionClass
|
|
35
|
+
|
|
36
|
+
--- CollapsibleTitledSectionClass constructor.
|
|
37
|
+
--- @param nameSuffix string -- The name suffix of the text input.
|
|
38
|
+
--- @param titleText string -- The title text.
|
|
39
|
+
--- @param autoScalingList boolean? -- Should it automatically update its size based on the content? Defaults to true.
|
|
40
|
+
--- @param minimizable boolean? -- Should it be minimizable? Defaults to true.
|
|
41
|
+
--- @param minimizedByDefault boolean? -- Should it start minimized? Defaults to true.
|
|
42
|
+
--- @paramm createTitleBar boolean? -- Should it create a title bar? Defaults to true.
|
|
43
|
+
--- @return CollapsibleTitledSectionClass -- The CollapsibleTitledSection class object.
|
|
44
|
+
function CollapsibleTitledSectionClass.new(
|
|
45
|
+
nameSuffix: string,
|
|
46
|
+
titleText: string,
|
|
47
|
+
autoScalingList: boolean?,
|
|
48
|
+
minimizable: boolean?,
|
|
49
|
+
minimizedByDefault: boolean?,
|
|
50
|
+
createTitleBar: boolean?
|
|
51
|
+
)
|
|
52
|
+
local self = {}
|
|
53
|
+
setmetatable(self, CollapsibleTitledSectionClass)
|
|
54
|
+
|
|
55
|
+
self._minimized = minimizedByDefault == true
|
|
56
|
+
self._minimizable = minimizable == true
|
|
57
|
+
self._createTitleBar = createTitleBar == nil or createTitleBar == true
|
|
58
|
+
|
|
59
|
+
self._titleBarHeight = GuiUtilities.kTitleBarHeight
|
|
60
|
+
|
|
61
|
+
local frame = Instance.new("Frame")
|
|
62
|
+
frame.Name = "CTSection" .. nameSuffix
|
|
63
|
+
frame.BackgroundTransparency = 1
|
|
64
|
+
self._frame = frame
|
|
65
|
+
|
|
66
|
+
local uiListLayout = Instance.new("UIListLayout")
|
|
67
|
+
uiListLayout.SortOrder = Enum.SortOrder.LayoutOrder
|
|
68
|
+
uiListLayout.Parent = frame
|
|
69
|
+
self._uiListLayout = uiListLayout
|
|
70
|
+
|
|
71
|
+
local contentsFrame = Instance.new("Frame")
|
|
72
|
+
contentsFrame.Name = "Contents"
|
|
73
|
+
contentsFrame.BackgroundTransparency = 1
|
|
74
|
+
contentsFrame.Size = UDim2.new(1, 0, 0, 1)
|
|
75
|
+
contentsFrame.Position = UDim2.new(0, 0, 0, 0)
|
|
76
|
+
contentsFrame.Parent = frame
|
|
77
|
+
contentsFrame.LayoutOrder = 2
|
|
78
|
+
GuiUtilities.syncGuiElementBackgroundColor(contentsFrame)
|
|
79
|
+
|
|
80
|
+
self._contentsFrame = contentsFrame
|
|
81
|
+
|
|
82
|
+
uiListLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
|
|
83
|
+
self:_UpdateSize()
|
|
84
|
+
end)
|
|
85
|
+
self:_UpdateSize()
|
|
86
|
+
|
|
87
|
+
if self._createTitleBar then self:_CreateTitleBar(titleText) end
|
|
88
|
+
self:SetCollapsedState(self._minimized)
|
|
89
|
+
|
|
90
|
+
self._autoScalingList = autoScalingList == true
|
|
91
|
+
if self._autoScalingList then GuiUtilities.MakeFrameAutoScalingList(self:GetContentsFrame()) end
|
|
92
|
+
|
|
93
|
+
return self
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
--- Gets the frame of this Collapsible Section itself.
|
|
97
|
+
--- @return Frame This Collapsible Section frame.
|
|
98
|
+
function CollapsibleTitledSectionClass:GetSectionFrame(): Frame
|
|
99
|
+
return self._frame
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
--- Gets the frame that contains everything that is inside this Collapsible Section.
|
|
103
|
+
--- @return Frame The frame that contains everything inside this Collapsible Section.
|
|
104
|
+
function CollapsibleTitledSectionClass:GetContentsFrame(): Frame
|
|
105
|
+
return self._contentsFrame
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
function CollapsibleTitledSectionClass:_UpdateSize()
|
|
109
|
+
local totalSize = self._uiListLayout.AbsoluteContentSize.Y
|
|
110
|
+
self._frame.Size = UDim2.new(1, 0, 0, totalSize)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
function CollapsibleTitledSectionClass:_UpdateMinimizeButton()
|
|
114
|
+
-- We can't rotate it because rotated images don't get clipped by parents.
|
|
115
|
+
-- This is all in a scroll widget.
|
|
116
|
+
-- :(
|
|
117
|
+
if self._minimized then
|
|
118
|
+
self._minimizeButton.Image = kArrowSpriteSheet
|
|
119
|
+
self._minimizeButton.ImageRectSize = kRightButtonRectSize
|
|
120
|
+
self._minimizeButton.ImageRectOffset = kRightButtonRectOffset
|
|
121
|
+
else
|
|
122
|
+
self._minimizeButton.Image = kArrowSpriteSheet
|
|
123
|
+
self._minimizeButton.ImageRectSize = kDownButtonRectSize
|
|
124
|
+
self._minimizeButton.ImageRectOffset = kDownButtonRectOffset
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
--- Sets the collapsed state. Whether or not its open and showing its contents.
|
|
129
|
+
--- @param state boolean -- A boolean representing the state to set.
|
|
130
|
+
function CollapsibleTitledSectionClass:SetCollapsedState(state: boolean)
|
|
131
|
+
if not self._minimizable then return end
|
|
132
|
+
self._minimized = state
|
|
133
|
+
self._contentsFrame.Visible = not state
|
|
134
|
+
self:_UpdateMinimizeButton()
|
|
135
|
+
self:_UpdateSize()
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
function CollapsibleTitledSectionClass:_ToggleCollapsedState()
|
|
139
|
+
if not self._minimizable then return end
|
|
140
|
+
self:SetCollapsedState(not self._minimized)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
function CollapsibleTitledSectionClass:_CreateTitleBar(titleText)
|
|
144
|
+
local titleTextOffset = self._titleBarHeight
|
|
145
|
+
|
|
146
|
+
local titleBar = Instance.new("ImageButton")
|
|
147
|
+
titleBar.AutoButtonColor = false
|
|
148
|
+
titleBar.Name = "TitleBarVisual"
|
|
149
|
+
titleBar.BorderSizePixel = 0
|
|
150
|
+
titleBar.Position = UDim2.new(0, 0, 0, 0)
|
|
151
|
+
titleBar.Size = UDim2.new(1, 0, 0, self._titleBarHeight)
|
|
152
|
+
titleBar.Parent = self._frame
|
|
153
|
+
titleBar.LayoutOrder = 1
|
|
154
|
+
titleBar.BorderMode = Enum.BorderMode.Middle
|
|
155
|
+
titleBar.BorderSizePixel = 1
|
|
156
|
+
GuiUtilities.syncGuiElementTitleColor(titleBar)
|
|
157
|
+
GuiUtilities.syncGuiElementBorderColor(titleBar)
|
|
158
|
+
|
|
159
|
+
local titleLabel = Instance.new("TextLabel")
|
|
160
|
+
titleLabel.Name = "TitleLabel"
|
|
161
|
+
titleLabel.BackgroundTransparency = 1
|
|
162
|
+
titleLabel.Font = Enum.Font.SourceSansBold --todo: input spec font
|
|
163
|
+
titleLabel.TextSize = 15 --todo: input spec font size
|
|
164
|
+
titleLabel.TextXAlignment = Enum.TextXAlignment.Left
|
|
165
|
+
titleLabel.Text = titleText
|
|
166
|
+
titleLabel.Position = UDim2.new(0, titleTextOffset, 0, 0)
|
|
167
|
+
titleLabel.Size = UDim2.new(1, -titleTextOffset, 1, GuiUtilities.kTextVerticalFudge)
|
|
168
|
+
titleLabel.Parent = titleBar
|
|
169
|
+
GuiUtilities.syncGuiElementFontColor(titleLabel)
|
|
170
|
+
|
|
171
|
+
self._minimizeButton = Instance.new("ImageButton")
|
|
172
|
+
self._minimizeButton.Name = "MinimizeSectionButton"
|
|
173
|
+
self._minimizeButton.Image = kArrowSpriteSheet
|
|
174
|
+
self._minimizeButton.ImageRectSize = kRightButtonRectSize
|
|
175
|
+
self._minimizeButton.ImageRectOffset = kRightButtonRectOffset
|
|
176
|
+
self._minimizeButton.Size = UDim2.new(0, kArrowSize, 0, kArrowSize)
|
|
177
|
+
self._minimizeButton.AnchorPoint = Vector2.new(0.5, 0.5)
|
|
178
|
+
self._minimizeButton.Position = UDim2.new(0, self._titleBarHeight * 0.5, 0, self._titleBarHeight * 0.5)
|
|
179
|
+
self._minimizeButton.BackgroundTransparency = 1
|
|
180
|
+
self._minimizeButton.Visible = self._minimizable -- only show when minimizable
|
|
181
|
+
GuiUtilities.syncGuiElementColorCustom(
|
|
182
|
+
self._minimizeButton,
|
|
183
|
+
"ImageColor3",
|
|
184
|
+
Enum.StudioStyleGuideColor.ScriptText,
|
|
185
|
+
Enum.StudioStyleGuideModifier.Default
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
self._minimizeButton.MouseButton1Down:Connect(function()
|
|
189
|
+
self:_ToggleCollapsedState()
|
|
190
|
+
end)
|
|
191
|
+
self:_UpdateMinimizeButton()
|
|
192
|
+
self._minimizeButton.Parent = titleBar
|
|
193
|
+
|
|
194
|
+
self._latestClickTime = 0
|
|
195
|
+
titleBar.MouseButton1Down:Connect(function()
|
|
196
|
+
local now = tick()
|
|
197
|
+
if now - self._latestClickTime < kDoubleClickTimeSec then
|
|
198
|
+
self:_ToggleCollapsedState()
|
|
199
|
+
self._latestClickTime = 0
|
|
200
|
+
else
|
|
201
|
+
self._latestClickTime = now
|
|
202
|
+
end
|
|
203
|
+
end)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
--- Adds a child frame to the contents section of the collapsible titled section.
|
|
207
|
+
--- @param childFrame GuiObject -- The GUI object to add to the contents frame.
|
|
208
|
+
--- @param layoutOrder number? -- Optional layout order to assign to the child frame.
|
|
209
|
+
function CollapsibleTitledSectionClass:AddChild(childFrame: GuiObject, layoutOrder: number?)
|
|
210
|
+
if layoutOrder then childFrame.LayoutOrder = layoutOrder end
|
|
211
|
+
childFrame.Parent = self._contentsFrame
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
return CollapsibleTitledSectionClass
|
package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ColorPicker.luau
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
----------------------------------------
|
|
2
|
+
--
|
|
3
|
+
-- ColorPicker.lua
|
|
4
|
+
--
|
|
5
|
+
-- Creates a frame containing a color picker.
|
|
6
|
+
--
|
|
7
|
+
----------------------------------------
|
|
8
|
+
GuiUtilities = require("../GuiUtilities")
|
|
9
|
+
|
|
10
|
+
local CustomTextButton = require("./CustomTextButton")
|
|
11
|
+
local VerticallyScalingListFrame = require("./VerticallyScalingListFrame")
|
|
12
|
+
|
|
13
|
+
local kColorPickedLabelHeight = 20
|
|
14
|
+
|
|
15
|
+
local ColorPickerClass = {}
|
|
16
|
+
ColorPickerClass.__index = ColorPickerClass
|
|
17
|
+
|
|
18
|
+
--- ColorPickerClass constructor.
|
|
19
|
+
--- @param nameSuffix string -- Suffix to append to the color picker's name.
|
|
20
|
+
--- @return ColorPickerClass -- A new instance of the color picker class.
|
|
21
|
+
function ColorPickerClass.new(nameSuffix: string)
|
|
22
|
+
local self = setmetatable({}, ColorPickerClass)
|
|
23
|
+
|
|
24
|
+
self._cancelFunction = nil
|
|
25
|
+
self._confirmFunction = nil
|
|
26
|
+
self._valueChangedFunction = nil
|
|
27
|
+
|
|
28
|
+
local frame = Instance.new("Frame")
|
|
29
|
+
frame.Name = "ClPck " .. nameSuffix
|
|
30
|
+
frame.BackgroundColor3 = Color3.fromRGB(53, 53, 53)
|
|
31
|
+
frame.BorderSizePixel = 0
|
|
32
|
+
frame.Size = UDim2.fromOffset(170, 186)
|
|
33
|
+
GuiUtilities.syncGuiElementBackgroundColor(frame)
|
|
34
|
+
|
|
35
|
+
local colorSpectrum = Instance.new("ImageButton")
|
|
36
|
+
colorSpectrum.Name = "ColorSpectrum"
|
|
37
|
+
colorSpectrum.AutoButtonColor = false
|
|
38
|
+
colorSpectrum.BackgroundColor3 = Color3.new(1, 1, 1)
|
|
39
|
+
colorSpectrum.Image = "rbxassetid://18967417547"
|
|
40
|
+
colorSpectrum.Position = UDim2.new(0, 15, 0, 7)
|
|
41
|
+
colorSpectrum.Size = UDim2.new(0, 111, 0, 111)
|
|
42
|
+
colorSpectrum.BorderSizePixel = 1
|
|
43
|
+
colorSpectrum.Parent = frame
|
|
44
|
+
GuiUtilities.syncGuiElementBorderColor(colorSpectrum)
|
|
45
|
+
|
|
46
|
+
local colorBrightness = Instance.new("ImageButton")
|
|
47
|
+
colorBrightness.Name = "ColorBrightness"
|
|
48
|
+
colorBrightness.AnchorPoint = Vector2.new(0.5, 0)
|
|
49
|
+
colorBrightness.AutoButtonColor = false
|
|
50
|
+
colorBrightness.BackgroundColor3 = Color3.new(1, 1, 1)
|
|
51
|
+
colorBrightness.Image = ""
|
|
52
|
+
colorBrightness.Position = UDim2.new(1, -20, 0, 7)
|
|
53
|
+
colorBrightness.Size = UDim2.new(0, 16, 0, 107)
|
|
54
|
+
colorBrightness.BorderSizePixel = 1
|
|
55
|
+
colorBrightness.Parent = frame
|
|
56
|
+
GuiUtilities.syncGuiElementBorderColor(colorBrightness)
|
|
57
|
+
|
|
58
|
+
local colorBrightnessKnob = Instance.new("Frame")
|
|
59
|
+
colorBrightnessKnob.Name = "Knob"
|
|
60
|
+
colorBrightnessKnob.AnchorPoint = Vector2.new(0.5, 0)
|
|
61
|
+
colorBrightnessKnob.BackgroundColor3 = Color3.new(1, 1, 1)
|
|
62
|
+
colorBrightnessKnob.BorderColor3 = Color3.new()
|
|
63
|
+
colorBrightnessKnob.BorderSizePixel = 0
|
|
64
|
+
colorBrightnessKnob.Position = UDim2.fromScale(0.5, 0)
|
|
65
|
+
colorBrightnessKnob.Size = UDim2.fromOffset(25, 10)
|
|
66
|
+
colorBrightnessKnob.Parent = colorBrightness
|
|
67
|
+
|
|
68
|
+
local uIGradient = Instance.new("UIGradient")
|
|
69
|
+
uIGradient.Name = "UIGradient"
|
|
70
|
+
uIGradient.Rotation = -90
|
|
71
|
+
uIGradient.Color = ColorSequence.new({
|
|
72
|
+
ColorSequenceKeypoint.new(0, Color3.new(0, 0, 0)),
|
|
73
|
+
ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1)),
|
|
74
|
+
})
|
|
75
|
+
uIGradient.Parent = colorBrightness
|
|
76
|
+
|
|
77
|
+
local uiStroke = Instance.new("UIStroke")
|
|
78
|
+
uiStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Border
|
|
79
|
+
uiStroke.Parent = colorBrightnessKnob
|
|
80
|
+
|
|
81
|
+
local uiCorner = Instance.new("UICorner")
|
|
82
|
+
uiCorner.CornerRadius = UDim.new(0, 4)
|
|
83
|
+
uiCorner.Parent = colorBrightnessKnob
|
|
84
|
+
|
|
85
|
+
local cross = Instance.new("ImageLabel")
|
|
86
|
+
cross.Name = "CrossIcon"
|
|
87
|
+
cross.AnchorPoint = Vector2.new(0.5, 0.5)
|
|
88
|
+
cross.BackgroundTransparency = 1
|
|
89
|
+
cross.Image = "rbxassetid://15929013661"
|
|
90
|
+
cross.Position = UDim2.fromScale(0, 0)
|
|
91
|
+
cross.Size = UDim2.fromOffset(20, 20)
|
|
92
|
+
cross.Parent = colorSpectrum
|
|
93
|
+
|
|
94
|
+
local buttonsContainer = Instance.new("Frame")
|
|
95
|
+
buttonsContainer.Name = "ButtonsContainer"
|
|
96
|
+
buttonsContainer.AnchorPoint = Vector2.new(0.5, 1)
|
|
97
|
+
buttonsContainer.BackgroundColor3 = Color3.fromRGB(169, 255, 129)
|
|
98
|
+
buttonsContainer.BackgroundTransparency = 1
|
|
99
|
+
buttonsContainer.BorderSizePixel = 0
|
|
100
|
+
buttonsContainer.Position = UDim2.fromScale(0.5, 1)
|
|
101
|
+
buttonsContainer.Size = UDim2.fromOffset(170, 36)
|
|
102
|
+
buttonsContainer.Parent = frame
|
|
103
|
+
|
|
104
|
+
local outputContainer = Instance.new("Frame")
|
|
105
|
+
outputContainer.Name = "OutputContainer"
|
|
106
|
+
outputContainer.AnchorPoint = Vector2.new(0.5, 1)
|
|
107
|
+
outputContainer.BackgroundTransparency = 1
|
|
108
|
+
outputContainer.BackgroundColor3 = Color3.fromRGB(40, 132, 181)
|
|
109
|
+
outputContainer.BorderSizePixel = 0
|
|
110
|
+
outputContainer.Position = UDim2.fromScale(0.5, 0.8)
|
|
111
|
+
outputContainer.Size = UDim2.fromOffset(170, 24)
|
|
112
|
+
outputContainer.Parent = frame
|
|
113
|
+
|
|
114
|
+
local colorPreviewBox = Instance.new("Frame")
|
|
115
|
+
colorPreviewBox.Name = "ColorPreview"
|
|
116
|
+
colorPreviewBox.AnchorPoint = Vector2.new(0, 0.5)
|
|
117
|
+
colorPreviewBox.BackgroundColor3 = Color3.new(1, 1, 1)
|
|
118
|
+
colorPreviewBox.Position = UDim2.new(0, 15, 0.5, 0)
|
|
119
|
+
colorPreviewBox.Size = UDim2.new(0, 18, 0, 18)
|
|
120
|
+
colorPreviewBox.Parent = outputContainer
|
|
121
|
+
GuiUtilities.syncGuiElementBorderColor(colorPreviewBox)
|
|
122
|
+
|
|
123
|
+
local colorRGBCode = Instance.new("TextBox")
|
|
124
|
+
colorRGBCode.Name = "ColorRGBCode"
|
|
125
|
+
colorRGBCode.AnchorPoint = Vector2.new(0, 0.5)
|
|
126
|
+
colorRGBCode.BackgroundColor3 = Color3.fromRGB(61, 255, 232)
|
|
127
|
+
colorRGBCode.BorderColor3 = Color3.fromRGB(34, 34, 34)
|
|
128
|
+
colorRGBCode.BorderSizePixel = 1
|
|
129
|
+
colorRGBCode.ClearTextOnFocus = false
|
|
130
|
+
colorRGBCode.Font = Enum.Font.SourceSans
|
|
131
|
+
colorRGBCode.Position = UDim2.new(0, 36, 0.5, 0)
|
|
132
|
+
colorRGBCode.Size = UDim2.fromOffset(62, 20)
|
|
133
|
+
colorRGBCode.Text = "255,255,255"
|
|
134
|
+
colorRGBCode.TextColor3 = Color3.fromRGB(204, 204, 204)
|
|
135
|
+
colorRGBCode.TextEditable = false
|
|
136
|
+
colorRGBCode.TextSize = 15
|
|
137
|
+
colorRGBCode.Parent = outputContainer
|
|
138
|
+
GuiUtilities.syncGuiElementFontColor(colorRGBCode)
|
|
139
|
+
GuiUtilities.syncGuiElementInputFieldColor(colorRGBCode)
|
|
140
|
+
GuiUtilities.syncGuiElementBorderColor(colorRGBCode)
|
|
141
|
+
|
|
142
|
+
local colorHexCode = Instance.new("TextBox")
|
|
143
|
+
colorHexCode.Name = "ColorHexCode"
|
|
144
|
+
colorHexCode.AnchorPoint = Vector2.new(0, 0.5)
|
|
145
|
+
colorHexCode.BackgroundColor3 = Color3.fromRGB(61, 255, 232)
|
|
146
|
+
colorHexCode.BorderColor3 = Color3.fromRGB(34, 34, 34)
|
|
147
|
+
colorHexCode.BorderSizePixel = 1
|
|
148
|
+
colorHexCode.ClearTextOnFocus = false
|
|
149
|
+
colorHexCode.Font = Enum.Font.SourceSans
|
|
150
|
+
colorHexCode.Position = UDim2.new(0, 101, 0.5, 0)
|
|
151
|
+
colorHexCode.Size = UDim2.fromOffset(55, 20)
|
|
152
|
+
colorHexCode.Text = "#FFFFFF"
|
|
153
|
+
colorHexCode.TextColor3 = Color3.fromRGB(204, 204, 204)
|
|
154
|
+
colorHexCode.TextEditable = false
|
|
155
|
+
colorHexCode.TextSize = 15
|
|
156
|
+
colorHexCode.Parent = outputContainer
|
|
157
|
+
GuiUtilities.syncGuiElementFontColor(colorHexCode)
|
|
158
|
+
GuiUtilities.syncGuiElementInputFieldColor(colorHexCode)
|
|
159
|
+
GuiUtilities.syncGuiElementBorderColor(colorHexCode)
|
|
160
|
+
|
|
161
|
+
colorSpectrum.InputBegan:Connect(function (inputObject: InputObject)
|
|
162
|
+
if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
|
|
163
|
+
self._dragging = true
|
|
164
|
+
self:_OnColorSpectrumClick(inputObject)
|
|
165
|
+
end)
|
|
166
|
+
|
|
167
|
+
colorSpectrum.InputChanged:Connect(function (inputObject: InputObject)
|
|
168
|
+
if not self._dragging then return end
|
|
169
|
+
self:_OnColorSpectrumClick(inputObject)
|
|
170
|
+
end)
|
|
171
|
+
|
|
172
|
+
colorSpectrum.InputEnded:Connect(function (inputObject: InputObject)
|
|
173
|
+
if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
|
|
174
|
+
self._dragging = false
|
|
175
|
+
end)
|
|
176
|
+
|
|
177
|
+
colorBrightness.InputBegan:Connect(function (inputObject: InputObject)
|
|
178
|
+
if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
|
|
179
|
+
self._draggingBrightness = true
|
|
180
|
+
self:_OnBrightnessSliderClick(inputObject)
|
|
181
|
+
end)
|
|
182
|
+
|
|
183
|
+
colorBrightness.InputChanged:Connect(function (inputObject: InputObject)
|
|
184
|
+
if not self._draggingBrightness then return end
|
|
185
|
+
self:_OnBrightnessSliderClick(inputObject)
|
|
186
|
+
end)
|
|
187
|
+
|
|
188
|
+
colorBrightness.InputEnded:Connect(function (inputObject: InputObject)
|
|
189
|
+
if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
|
|
190
|
+
self._draggingBrightness = false
|
|
191
|
+
end)
|
|
192
|
+
|
|
193
|
+
local verticallyScalingFrame = VerticallyScalingListFrame.new("suffix")
|
|
194
|
+
verticallyScalingFrame:GetFrame().Parent = buttonsContainer
|
|
195
|
+
verticallyScalingFrame:GetFrame().AnchorPoint = Vector2.new(0, 0.5)
|
|
196
|
+
verticallyScalingFrame:GetFrame().Position = UDim2.fromScale(0, 0.5)
|
|
197
|
+
verticallyScalingFrame:SetHorizontalAlignment(Enum.HorizontalAlignment.Center)
|
|
198
|
+
verticallyScalingFrame:SetVerticalAlignment(Enum.VerticalAlignment.Center)
|
|
199
|
+
verticallyScalingFrame:SetFillDirection(Enum.FillDirection.Horizontal)
|
|
200
|
+
verticallyScalingFrame:SetLayoutPadding(UDim.new(0, 5))
|
|
201
|
+
|
|
202
|
+
local buttonConfirm = CustomTextButton.new("confirm", "Confirm", true)
|
|
203
|
+
local buttonCancel = CustomTextButton.new("cancel", "Cancel", true)
|
|
204
|
+
|
|
205
|
+
verticallyScalingFrame:AddChild(buttonConfirm:GetFrame())
|
|
206
|
+
verticallyScalingFrame:AddChild(buttonCancel:GetFrame())
|
|
207
|
+
|
|
208
|
+
self._frame = frame
|
|
209
|
+
self._colorSpectrum = colorSpectrum
|
|
210
|
+
self._colorPreviewBox = colorPreviewBox
|
|
211
|
+
self._colorCodeBoxRGB = colorRGBCode
|
|
212
|
+
self._colorCodeBoxHex = colorHexCode
|
|
213
|
+
self._colorBrightnessSlider = colorBrightness
|
|
214
|
+
self._colorBrightnessKnob = colorBrightnessKnob
|
|
215
|
+
self._colorCross = cross
|
|
216
|
+
self._buttonCancel = buttonCancel
|
|
217
|
+
self._buttonConfirm = buttonConfirm
|
|
218
|
+
|
|
219
|
+
self._colorPicked = Color3.new(1,1,1) :: Color3
|
|
220
|
+
self._colorPickedRGBCode = "255,255,255"
|
|
221
|
+
self._colorPickedHexCode = "#FFFFFF"
|
|
222
|
+
|
|
223
|
+
self._dragging = false
|
|
224
|
+
self._draggingBrightness = false
|
|
225
|
+
|
|
226
|
+
self._hsvHue = 1
|
|
227
|
+
self._hsvSat = 1
|
|
228
|
+
self._hsvVal = 1
|
|
229
|
+
|
|
230
|
+
return self
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
function ColorPickerClass:_OnColorSpectrumClick(inputObject: InputObject)
|
|
234
|
+
-- detect clicked color code based on the click position in the color spectrum image
|
|
235
|
+
local relX: number, relY:number = GuiUtilities.GetClickOffsetFromObject(inputObject, self._colorSpectrum)
|
|
236
|
+
if relX >= 0 and relX <= 1 and relY >= 0 and relY <= 1 then
|
|
237
|
+
self._hsvHue = relX
|
|
238
|
+
self._hsvSat = 1 - relY
|
|
239
|
+
self:_CommitColorChange()
|
|
240
|
+
self:_UpdateBrightnessSlider()
|
|
241
|
+
self:_UpdateColorCross()
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
function ColorPickerClass:_OnBrightnessSliderClick(inputObject: InputObject)
|
|
246
|
+
local _, relY = GuiUtilities.GetClickOffsetFromObject(inputObject, self._colorBrightnessSlider)
|
|
247
|
+
self._hsvVal = 1 - relY
|
|
248
|
+
self:_UpdateBrightnessSlider()
|
|
249
|
+
self:_CommitColorChange()
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
function ColorPickerClass:_CommitColorChange(color: Color3?)
|
|
253
|
+
-- Applies and commits a new color to the picker.
|
|
254
|
+
-- If a Color3 parameter is provided, updates internal HSV values accordingly. Used by manually setting the value.
|
|
255
|
+
-- Otherwise, generates a color from current HSV state. Used by interacting with the picker.
|
|
256
|
+
-- Also updates UI elements and triggers the value changed callback if set.
|
|
257
|
+
if color then
|
|
258
|
+
self._colorPicked = color
|
|
259
|
+
local h, s, v = color:ToHSV()
|
|
260
|
+
self._hsvHue = h
|
|
261
|
+
self._hsvSat = s
|
|
262
|
+
self._hsvVal = v
|
|
263
|
+
else
|
|
264
|
+
self._colorPicked = Color3.fromHSV(self._hsvHue, self._hsvSat, self._hsvVal)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
self:_UpdateColorCodeLabel()
|
|
268
|
+
self:_UpdateColorPreviewBox()
|
|
269
|
+
if self._valueChangedFunction then -- fire value changed function
|
|
270
|
+
self._valueChangedFunction(self._colorPicked)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
function ColorPickerClass:_UpdateColorCross()
|
|
275
|
+
-- positions and paint the color cross
|
|
276
|
+
self._colorCross.Position = UDim2.fromScale(self._hsvHue, 1 - self._hsvSat)
|
|
277
|
+
self._colorCross.ImageColor3 = if 1 - self._hsvSat < 0.4 then Color3.new(1,1,1) else Color3.new(0,0,0)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
function ColorPickerClass:_UpdateBrightnessSlider()
|
|
281
|
+
self._colorBrightnessKnob.Position = UDim2.new(0.5, 0, 1 - self._hsvVal, 0)
|
|
282
|
+
self._colorBrightnessSlider.UIGradient.Color = ColorSequence.new({
|
|
283
|
+
ColorSequenceKeypoint.new(0, Color3.new(0, 0, 0)),
|
|
284
|
+
ColorSequenceKeypoint.new(1, Color3.fromHSV(self._hsvHue, self._hsvSat, 1)),
|
|
285
|
+
})
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
function ColorPickerClass:_UpdateColorCodeLabel()
|
|
289
|
+
-- generate a color code string like this: R,G,B #HEX
|
|
290
|
+
local R = math.clamp(math.round(self._colorPicked.R * 255), 0, 255)
|
|
291
|
+
local G = math.clamp(math.round(self._colorPicked.G * 255), 0, 255)
|
|
292
|
+
local B = math.clamp(math.round(self._colorPicked.B * 255), 0, 255)
|
|
293
|
+
self._colorPickedHexCode = "#" .. string.upper(self._colorPicked:ToHex())
|
|
294
|
+
self._colorPickedRGBCode = ("%d,%d,%d"):format(R, G, B)
|
|
295
|
+
self._colorCodeBoxRGB.Text = self._colorPickedRGBCode
|
|
296
|
+
self._colorCodeBoxHex.Text = self._colorPickedHexCode
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
function ColorPickerClass:_UpdateColorPreviewBox()
|
|
300
|
+
self._colorPreviewBox.BackgroundColor3 = self._colorPicked
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
--- Sets the function to be called when the cancel button is clicked.
|
|
304
|
+
--- @param cf function -- A function to execute when cancel is pressed.
|
|
305
|
+
function ColorPickerClass:SetCancelFunction(cf: () -> ())
|
|
306
|
+
self._buttonCancel:SetClickedFunction(cf)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
--- Sets the function to be called when the confirm button is clicked.
|
|
310
|
+
--- Passes the currently selected color to the callback.
|
|
311
|
+
--- @param cf function -- A function that takes the selected Color3 as a parameter.
|
|
312
|
+
function ColorPickerClass:SetConfirmFunction(cf: (chosenColor: Color3) -> ())
|
|
313
|
+
self._buttonConfirm:SetClickedFunction(function (...)
|
|
314
|
+
cf(self._colorPicked)
|
|
315
|
+
end)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
--- Sets a callback function to be called when the color value changes.
|
|
319
|
+
--- Passing nil will remove the existing callback.
|
|
320
|
+
--- @param vcf (newValue: Color3) -> () | nil -- Function to call on color change, or nil to unbind.
|
|
321
|
+
function ColorPickerClass:SetValueChangedFunction(vcf: (newValue: Color3) -> () | nil)
|
|
322
|
+
self._valueChangedFunction = vcf
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
--- Returns the main UI frame of the color picker.
|
|
326
|
+
--- @return Frame -- The root frame containing the color picker UI.
|
|
327
|
+
function ColorPickerClass:GetFrame(): Frame
|
|
328
|
+
return self._frame
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
--- Gets the currently selected color in the color picker.
|
|
332
|
+
--- @return Color3 -- The current color selection.
|
|
333
|
+
function ColorPickerClass:GetValue(): Color3
|
|
334
|
+
return self._colorPicked
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
--- Sets the currently selected color in the color picker.
|
|
338
|
+
--- @param newValue Color3 -- The color to set.
|
|
339
|
+
function ColorPickerClass:SetValue(newValue: Color3)
|
|
340
|
+
self:_CommitColorChange(newValue)
|
|
341
|
+
self:_UpdateColorCross()
|
|
342
|
+
self:_UpdateBrightnessSlider()
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
--- Returns the currently picked color as a hex code string.
|
|
346
|
+
--- Example: "#FFFFFF" for white.
|
|
347
|
+
--- @return string -- The hex code representation of the picked color.
|
|
348
|
+
function ColorPickerClass:GetHexCode(): string
|
|
349
|
+
return self._colorPickedHexCode
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
--- Returns the currently picked color as an RGB string.
|
|
354
|
+
--- Example: "255,255,255" for white.
|
|
355
|
+
--- @return string -- The RGB string representation of the picked color.
|
|
356
|
+
function ColorPickerClass:GetRGBCode(): string
|
|
357
|
+
return self._colorPickedRGBCode
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
return ColorPickerClass
|