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,294 @@
|
|
|
1
|
+
----------------------------------------
|
|
2
|
+
--
|
|
3
|
+
-- LabeledColorInput.lua
|
|
4
|
+
--
|
|
5
|
+
-- Creates a frame containing a label and a text input control.
|
|
6
|
+
--
|
|
7
|
+
----------------------------------------
|
|
8
|
+
GuiUtilities = require("../GuiUtilities")
|
|
9
|
+
|
|
10
|
+
local ColorPicker = require("./ColorPicker")
|
|
11
|
+
|
|
12
|
+
local kTextInputWidth = 100
|
|
13
|
+
local kTextBoxInternalPadding = 4
|
|
14
|
+
|
|
15
|
+
LabeledColorInputPickerClass = {}
|
|
16
|
+
LabeledColorInputPickerClass.__index = LabeledColorInputPickerClass
|
|
17
|
+
|
|
18
|
+
function round(x)
|
|
19
|
+
return x + 0.5 - (x + 0.5) % 1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
--- LabeledColorInputPickerClass constructor.
|
|
23
|
+
--- @param nameSuffix string -- Suffix to append to the element's name for uniqueness.
|
|
24
|
+
--- @param labelText string -- Text label displayed alongside the color input.
|
|
25
|
+
--- @param defaultValue Color3 -- The default color value to initialize the input with.
|
|
26
|
+
--- @return LabeledColorInputPickerClass -- A new instance of the labeled color input class.
|
|
27
|
+
function LabeledColorInputPickerClass.new(nameSuffix: string, labelText: string, defaultValue: Color3)
|
|
28
|
+
local self = {}
|
|
29
|
+
setmetatable(self, LabeledColorInputPickerClass)
|
|
30
|
+
|
|
31
|
+
-- Note: we are using "graphemes" instead of characters.
|
|
32
|
+
-- In modern text-manipulation-fu, what with internationalization,
|
|
33
|
+
-- emojis, etc, it's not enough to count characters, particularly when
|
|
34
|
+
-- concerned with "how many <things> am I rendering?".
|
|
35
|
+
-- We are using the
|
|
36
|
+
self._MaxGraphemes = 20
|
|
37
|
+
|
|
38
|
+
self._valueChangedFunction = nil
|
|
39
|
+
self._focusLostFunction = nil
|
|
40
|
+
|
|
41
|
+
defaultValue = defaultValue or Color3.new(1,1,1)
|
|
42
|
+
|
|
43
|
+
local frame = Instance.new("Frame")
|
|
44
|
+
frame.Name = "CTIF" .. nameSuffix
|
|
45
|
+
frame.Position = UDim2.new(0, 0, 1, 0)
|
|
46
|
+
frame.Size = UDim2.new(1, 0, 0, 0)
|
|
47
|
+
frame.BorderSizePixel = 0
|
|
48
|
+
frame.AutomaticSize = Enum.AutomaticSize.Y
|
|
49
|
+
GuiUtilities.syncGuiElementBackgroundColor(frame)
|
|
50
|
+
|
|
51
|
+
local inputFrame = GuiUtilities.MakeStandardFixedHeightFrame("InputFrame")
|
|
52
|
+
inputFrame.Parent = frame
|
|
53
|
+
|
|
54
|
+
local label = GuiUtilities.MakeStandardPropertyLabel(labelText)
|
|
55
|
+
label.Parent = inputFrame
|
|
56
|
+
self._label = label
|
|
57
|
+
|
|
58
|
+
-- Dumb hack to add padding to text box,
|
|
59
|
+
local colorFrame = Instance.new("ImageButton")
|
|
60
|
+
colorFrame.Name = "Color"
|
|
61
|
+
colorFrame.AutoButtonColor = true
|
|
62
|
+
colorFrame.Size = UDim2.new(0, 12, 0, 12)
|
|
63
|
+
colorFrame.Position = UDim2.new(0, GuiUtilities.StandardLineElementLeftMargin, .5, 0)
|
|
64
|
+
colorFrame.AnchorPoint = Vector2.new(0, .5)
|
|
65
|
+
colorFrame.Parent = inputFrame
|
|
66
|
+
colorFrame.BackgroundColor3 = defaultValue
|
|
67
|
+
colorFrame.Image = ""
|
|
68
|
+
GuiUtilities.syncGuiElementBorderColor(colorFrame)
|
|
69
|
+
|
|
70
|
+
local textBoxWrapperFrame = Instance.new("Frame")
|
|
71
|
+
textBoxWrapperFrame.Name = "Wrapper"
|
|
72
|
+
textBoxWrapperFrame.Size = UDim2.new(0, kTextInputWidth - 20, 0.6, 0)
|
|
73
|
+
textBoxWrapperFrame.Position = UDim2.new(0, GuiUtilities.StandardLineElementLeftMargin + 20, .5, 0)
|
|
74
|
+
textBoxWrapperFrame.AnchorPoint = Vector2.new(0, .5)
|
|
75
|
+
textBoxWrapperFrame.Parent = inputFrame
|
|
76
|
+
GuiUtilities.syncGuiElementInputFieldColor(textBoxWrapperFrame)
|
|
77
|
+
GuiUtilities.syncGuiElementBorderColor(textBoxWrapperFrame)
|
|
78
|
+
|
|
79
|
+
local textBox = Instance.new("TextBox")
|
|
80
|
+
textBox.Parent = textBoxWrapperFrame
|
|
81
|
+
textBox.Name = "TextBox"
|
|
82
|
+
textBox.Text = string.format("[%s, %s, %s]", tostring(round(defaultValue.R * 255)), tostring(round(defaultValue.G * 255)), tostring(round(defaultValue.B * 255)))
|
|
83
|
+
textBox.Font = Enum.Font.SourceSans
|
|
84
|
+
textBox.TextSize = 15
|
|
85
|
+
textBox.BackgroundTransparency = 1
|
|
86
|
+
textBox.TextXAlignment = Enum.TextXAlignment.Left
|
|
87
|
+
textBox.Size = UDim2.new(1, -kTextBoxInternalPadding, 1, GuiUtilities.kTextVerticalFudge)
|
|
88
|
+
textBox.Position = UDim2.new(0, kTextBoxInternalPadding, 0, 0)
|
|
89
|
+
textBox.ClipsDescendants = true
|
|
90
|
+
textBox.ClearTextOnFocus = false
|
|
91
|
+
GuiUtilities.syncGuiElementFontColor(textBox)
|
|
92
|
+
|
|
93
|
+
textBox:GetPropertyChangedSignal("Text"):Connect(function()
|
|
94
|
+
-- Never let the text be too long.
|
|
95
|
+
-- Careful here: we want to measure number of graphemes, not characters,
|
|
96
|
+
-- in the text, and we want to clamp on graphemes as well.
|
|
97
|
+
if (utf8.len(self._textBox.Text) > self._MaxGraphemes) then
|
|
98
|
+
local count = 0
|
|
99
|
+
for start, stop in utf8.graphemes(self._textBox.Text) do
|
|
100
|
+
count = count + 1
|
|
101
|
+
if (count > self._MaxGraphemes) then
|
|
102
|
+
-- We have gone one too far.
|
|
103
|
+
-- clamp just before the beginning of this grapheme.
|
|
104
|
+
self._textBox.Text = string.sub(self._textBox.Text, 1, start-1)
|
|
105
|
+
break
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
-- Don't continue with rest of function: the resetting of "Text" field
|
|
109
|
+
-- above will trigger re-entry. We don't need to trigger value
|
|
110
|
+
-- changed function twice.
|
|
111
|
+
return
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
self._value = self._textBox.Text
|
|
115
|
+
if (self._valueChangedFunction) then
|
|
116
|
+
self._valueChangedFunction(self._value)
|
|
117
|
+
end
|
|
118
|
+
end)
|
|
119
|
+
|
|
120
|
+
textBox.FocusLost:Connect(function (enterPressed: boolean)
|
|
121
|
+
self:_GuessColorFromInputValue()
|
|
122
|
+
if self._focusLostFunction then
|
|
123
|
+
self._focusLostFunction(enterPressed)
|
|
124
|
+
end
|
|
125
|
+
end)
|
|
126
|
+
|
|
127
|
+
local colorPickerComponent = ColorPicker.new("Picker")
|
|
128
|
+
colorPickerComponent:SetValue(defaultValue)
|
|
129
|
+
colorPickerComponent:GetFrame().Parent = frame
|
|
130
|
+
colorPickerComponent:GetFrame().Position = UDim2.new(0, 43, 0, 30)
|
|
131
|
+
colorPickerComponent:GetFrame().Visible = false
|
|
132
|
+
colorPickerComponent._buttonConfirm:GetFrame().Visible = false
|
|
133
|
+
colorPickerComponent._buttonCancel:GetButton().Text = "Close"
|
|
134
|
+
colorPickerComponent._colorPreviewBox.Visible = false
|
|
135
|
+
colorPickerComponent._colorCodeBoxRGB.Position = UDim2.new(0, 26, 0.5, 0)
|
|
136
|
+
colorPickerComponent._colorCodeBoxHex.Position = UDim2.new(0, 92, 0.5, 0)
|
|
137
|
+
|
|
138
|
+
colorPickerComponent:SetCancelFunction(function ()
|
|
139
|
+
colorPickerComponent:GetFrame().Visible = false
|
|
140
|
+
end)
|
|
141
|
+
|
|
142
|
+
colorPickerComponent:SetValueChangedFunction(function (newValue: Color3)
|
|
143
|
+
self._colorValue = newValue
|
|
144
|
+
self:_UpdateColorFrame()
|
|
145
|
+
self:_UpdateInputValue()
|
|
146
|
+
end)
|
|
147
|
+
|
|
148
|
+
colorFrame.MouseButton1Click:Connect(function ()
|
|
149
|
+
if not self._colorPickerEnabled then return end
|
|
150
|
+
colorPickerComponent:GetFrame().Visible = not colorPickerComponent:GetFrame().Visible
|
|
151
|
+
end)
|
|
152
|
+
|
|
153
|
+
self._frame = frame
|
|
154
|
+
self._textBox = textBox
|
|
155
|
+
self._colorFrame = colorFrame
|
|
156
|
+
self._value = self._textBox.Text
|
|
157
|
+
self._colorValue = defaultValue
|
|
158
|
+
self._colorPickerComponent = colorPickerComponent
|
|
159
|
+
self._colorPickerFrame = colorPickerComponent:GetFrame()
|
|
160
|
+
self._colorPickerEnabled = true
|
|
161
|
+
|
|
162
|
+
return self
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
function LabeledColorInputPickerClass:_UpdateColorFrame()
|
|
166
|
+
self._colorFrame.BackgroundColor3 = self._colorValue
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
function LabeledColorInputPickerClass:_UpdateInputValue()
|
|
170
|
+
self._value = if self._colorPickerEnabled then
|
|
171
|
+
`[{self._colorPickerComponent:GetRGBCode()}]`
|
|
172
|
+
else
|
|
173
|
+
string.format(
|
|
174
|
+
"[%s, %s, %s]",
|
|
175
|
+
tostring(round(self._colorValue.R * 255)),
|
|
176
|
+
tostring(round(self._colorValue.G * 255)),
|
|
177
|
+
tostring(round(self._colorValue.B * 255))
|
|
178
|
+
)
|
|
179
|
+
self._textBox.Text = self._value
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
function LabeledColorInputPickerClass:_GuessColorFromInputValue()
|
|
183
|
+
--- Attempts to parse a color value from the text input.
|
|
184
|
+
--- Supports two formats: `R, G, B` (e.g., "255, 128, 0") and hex code (e.g., "#FFA500").
|
|
185
|
+
--- If a valid color is found, it updates the current color value accordingly.
|
|
186
|
+
local text = self._textBox.Text
|
|
187
|
+
|
|
188
|
+
-- Try matching RGB format first
|
|
189
|
+
local R, G, B = string.match(text, "(%d+)%s*,%s*(%d+)%s*,%s*(%d+)")
|
|
190
|
+
R = tonumber(R)
|
|
191
|
+
G = tonumber(G)
|
|
192
|
+
B = tonumber(B)
|
|
193
|
+
if R and G and B then
|
|
194
|
+
self:SetColorValue(Color3.fromRGB(
|
|
195
|
+
math.clamp(R, 0, 255),
|
|
196
|
+
math.clamp(G, 0, 255),
|
|
197
|
+
math.clamp(B, 0, 255)
|
|
198
|
+
))
|
|
199
|
+
return
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
-- Try matching HEX format like #2e2e2e or #ABCDEF
|
|
203
|
+
local hex = string.match(text, "#(%x%x%x%x%x%x)")
|
|
204
|
+
if hex then
|
|
205
|
+
local r = tonumber(string.sub(hex, 1, 2), 16)
|
|
206
|
+
local g = tonumber(string.sub(hex, 3, 4), 16)
|
|
207
|
+
local b = tonumber(string.sub(hex, 5, 6), 16)
|
|
208
|
+
if r and g and b then
|
|
209
|
+
self:SetColorValue(Color3.fromRGB(r, g, b))
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
--- Sets the function to be called when the input value changes.
|
|
215
|
+
--- @param vcf function -- The function to call when the value changes.
|
|
216
|
+
function LabeledColorInputPickerClass:SetValueChangedFunction(vcf)
|
|
217
|
+
self._valueChangedFunction = vcf
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
--- Sets the function to be called when the input loses focus.
|
|
221
|
+
--- @param flf function -- A function with signature (enterPressed: boolean) -> ().
|
|
222
|
+
function LabeledColorInputPickerClass:SetFocusLostFunction(flf: (enterPressed: boolean) -> ())
|
|
223
|
+
self._focusLostFunction = flf
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
--- Returns the main frame of the labeled color input component.
|
|
227
|
+
--- @return Frame -- The UI frame for the component.
|
|
228
|
+
function LabeledColorInputPickerClass:GetFrame()
|
|
229
|
+
return self._frame
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
--- Returns the current text value from the input field.
|
|
233
|
+
--- @return string -- The string entered in the input box.
|
|
234
|
+
function LabeledColorInputPickerClass:GetValue(): string
|
|
235
|
+
return self._textBox.Text
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
--- Returns the current color value.
|
|
239
|
+
--- @return Color3 -- The selected color value.
|
|
240
|
+
function LabeledColorInputPickerClass:GetColorValue(): Color3
|
|
241
|
+
return self._value
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
--- Returns the maximum number of graphemes allowed in the input field.
|
|
245
|
+
--- @return number -- The maximum graphemes setting.
|
|
246
|
+
function LabeledColorInputPickerClass:GetMaxGraphemes()
|
|
247
|
+
return self._MaxGraphemes
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
--- Sets the maximum number of graphemes allowed in the input field.
|
|
251
|
+
--- @param newValue number -- The maximum number of graphemes.
|
|
252
|
+
function LabeledColorInputPickerClass:SetMaxGraphemes(newValue)
|
|
253
|
+
self._MaxGraphemes = newValue
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
--- Sets the text value of the input field.
|
|
257
|
+
--- @param newValue string -- The new value to assign to the input.
|
|
258
|
+
function LabeledColorInputPickerClass:SetValue(newValue)
|
|
259
|
+
if self._value ~= newValue then
|
|
260
|
+
self._textBox.Text = newValue
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
--- Sets the color value for the color input and updates the display.
|
|
265
|
+
--- @param newValue Color3 -- The new color to assign.
|
|
266
|
+
function LabeledColorInputPickerClass:SetColorValue(newValue: Color3)
|
|
267
|
+
assert(typeof(newValue) == "Color3", "First parameter must be a Color3. Received " .. typeof(newValue))
|
|
268
|
+
self._colorValue = newValue
|
|
269
|
+
self:_UpdateColorFrame()
|
|
270
|
+
self:_UpdateInputValue()
|
|
271
|
+
if self._colorPickerEnabled then
|
|
272
|
+
self._colorPickerComponent:SetValue(newValue)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
--- Enables or disables the color picker UI.
|
|
277
|
+
--- If disabled, the user can only manually input a RGB or a Hex color value.
|
|
278
|
+
---
|
|
279
|
+
--- If enabled, the user can also open a color picker UI to choose a color.
|
|
280
|
+
--- @param state boolean -- Whether to enable (true) or disable (false) the color picker.
|
|
281
|
+
function LabeledColorInputPickerClass:SetPickerEnabled(state: boolean)
|
|
282
|
+
self._colorPickerEnabled = state
|
|
283
|
+
if not state then
|
|
284
|
+
self._colorPickerFrame.Visible = false
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
--- Returns whether the color picker is currently enabled.
|
|
289
|
+
--- @return boolean -- True if the color picker is enabled, false otherwise.
|
|
290
|
+
function LabeledColorInputPickerClass:GetPickerEnabled(state: boolean)
|
|
291
|
+
return self._colorPickerEnabled
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
return LabeledColorInputPickerClass
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
----------------------------------------
|
|
2
|
+
--
|
|
3
|
+
-- LabeledMultiChoice.lua
|
|
4
|
+
--
|
|
5
|
+
-- Creates a frame containing a label and list of choices, of which exactly one
|
|
6
|
+
-- is always selected.
|
|
7
|
+
--
|
|
8
|
+
----------------------------------------
|
|
9
|
+
GuiUtilities = require("../GuiUtilities")
|
|
10
|
+
LabeledRadioButton = require("./LabeledRadioButton")
|
|
11
|
+
LabeledCheckbox = require("./LabeledCheckbox")
|
|
12
|
+
VerticallyScalingListFrame = require("./VerticallyScalingListFrame")
|
|
13
|
+
|
|
14
|
+
local kRadioButtonsHPadding = GuiUtilities.kRadioButtonsHPadding
|
|
15
|
+
|
|
16
|
+
LabeledMultiChoiceClass = {}
|
|
17
|
+
LabeledMultiChoiceClass.__index = LabeledMultiChoiceClass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
--- LabeledMultiChoiceClass constructor.
|
|
21
|
+
--- @param nameSuffix string -- Suffix to append to the name of the UI elements.
|
|
22
|
+
--- @param labelText string -- The label displayed next to the multi-choice selector.
|
|
23
|
+
--- @param choices {{Id: number | string, Text: string}} -- An array of choice entries. Each entry must include a .Id field and .Text field.
|
|
24
|
+
--- @param initChoiceIndex number? -- Optional index of the initially selected choice. Defaults to the first if not provided.
|
|
25
|
+
--- @return LabeledMultiChoiceClass -- A new instance of the labeled multi-choice selector.
|
|
26
|
+
function LabeledMultiChoiceClass.new(nameSuffix: string, labelText: string, choices: {{Id: number | string, Text: string}}, initChoiceIndex: number?)
|
|
27
|
+
local self = {}
|
|
28
|
+
setmetatable(self, LabeledMultiChoiceClass)
|
|
29
|
+
|
|
30
|
+
self._buttonObjsByIndex = {}
|
|
31
|
+
|
|
32
|
+
self._choices = choices
|
|
33
|
+
|
|
34
|
+
if (not initChoiceIndex ) then
|
|
35
|
+
initChoiceIndex = 1
|
|
36
|
+
end
|
|
37
|
+
if (initChoiceIndex > #choices) then
|
|
38
|
+
initChoiceIndex = #choices
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
local vsl = VerticallyScalingListFrame.new("MCC_" .. nameSuffix)
|
|
43
|
+
vsl:AddBottomPadding()
|
|
44
|
+
|
|
45
|
+
local titleLabel = GuiUtilities.MakeFrameWithSubSectionLabel("Title", labelText)
|
|
46
|
+
vsl:AddChild(titleLabel)
|
|
47
|
+
|
|
48
|
+
-- Container for cells.
|
|
49
|
+
local cellFrame = self:_MakeRadioButtons(choices)
|
|
50
|
+
vsl:AddChild(cellFrame)
|
|
51
|
+
|
|
52
|
+
self._vsl = vsl
|
|
53
|
+
|
|
54
|
+
self:SetSelectedIndex(initChoiceIndex)
|
|
55
|
+
|
|
56
|
+
return self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
-- Small checkboxes are a different entity.
|
|
60
|
+
-- All the bits are smaller.
|
|
61
|
+
-- Fixed width instead of flood-fill.
|
|
62
|
+
-- Box comes first, then label.
|
|
63
|
+
function LabeledMultiChoiceClass:_MakeRadioButtons(choices)
|
|
64
|
+
local frame = GuiUtilities.MakeFrame("RadioButtons")
|
|
65
|
+
frame.BackgroundTransparency = 1
|
|
66
|
+
|
|
67
|
+
local padding = Instance.new("UIPadding")
|
|
68
|
+
padding.PaddingLeft = UDim.new(0, GuiUtilities.StandardLineLabelLeftMargin)
|
|
69
|
+
padding.PaddingRight = UDim.new(0, GuiUtilities.StandardLineLabelLeftMargin)
|
|
70
|
+
padding.Parent = frame
|
|
71
|
+
|
|
72
|
+
-- Make a grid to put checkboxes in.
|
|
73
|
+
local uiGridLayout = Instance.new("UIGridLayout")
|
|
74
|
+
uiGridLayout.CellSize = LabeledCheckbox.kMinFrameSize
|
|
75
|
+
uiGridLayout.CellPadding = UDim2.new(0,
|
|
76
|
+
kRadioButtonsHPadding,
|
|
77
|
+
0,
|
|
78
|
+
GuiUtilities.kStandardVMargin)
|
|
79
|
+
uiGridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Left
|
|
80
|
+
uiGridLayout.VerticalAlignment = Enum.VerticalAlignment.Top
|
|
81
|
+
uiGridLayout.Parent = frame
|
|
82
|
+
uiGridLayout.SortOrder = Enum.SortOrder.LayoutOrder
|
|
83
|
+
self._uiGridLayout = uiGridLayout
|
|
84
|
+
|
|
85
|
+
for i, choiceData in ipairs(choices) do
|
|
86
|
+
self:_AddRadioButton(frame, i, choiceData)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
-- Sync size with content size.
|
|
90
|
+
GuiUtilities.AdjustHeightDynamicallyToLayout(frame, uiGridLayout)
|
|
91
|
+
|
|
92
|
+
return frame
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
function LabeledMultiChoiceClass:_AddRadioButton(parentFrame, index, choiceData)
|
|
96
|
+
local radioButtonObj = LabeledRadioButton.new(choiceData.Id, choiceData.Text)
|
|
97
|
+
self._buttonObjsByIndex[index] = radioButtonObj
|
|
98
|
+
|
|
99
|
+
radioButtonObj:SetValueChangedFunction(function(value)
|
|
100
|
+
-- If we notice the button going from off to on, and it disagrees with
|
|
101
|
+
-- our current notion of selection, update selection.
|
|
102
|
+
if (value and self._selectedIndex ~= index) then
|
|
103
|
+
self:SetSelectedIndex(index)
|
|
104
|
+
end
|
|
105
|
+
end)
|
|
106
|
+
|
|
107
|
+
radioButtonObj:GetFrame().LayoutOrder = index
|
|
108
|
+
radioButtonObj:GetFrame().Parent = parentFrame
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
--- Sets the selected index in the multi-choice UI and updates the button states accordingly.
|
|
112
|
+
--- @param selectedIndex number -- The index of the choice to be selected.
|
|
113
|
+
function LabeledMultiChoiceClass:SetSelectedIndex(selectedIndex)
|
|
114
|
+
self._selectedIndex = selectedIndex
|
|
115
|
+
for i = 1, #self._buttonObjsByIndex do
|
|
116
|
+
self._buttonObjsByIndex[i]:SetValue(i == selectedIndex)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
if (self._valueChangedFunction) then
|
|
120
|
+
self._valueChangedFunction(self._selectedIndex)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
--- Gets the currently selected index in the multi-choice UI.
|
|
125
|
+
--- @return number -- The index of the selected choice.
|
|
126
|
+
function LabeledMultiChoiceClass:GetSelectedIndex()
|
|
127
|
+
return self._selectedIndex
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
--- Gets the ID value of the currently selected choice.
|
|
131
|
+
--- @return number | string -- The "Id" field of the selected choice.
|
|
132
|
+
function LabeledMultiChoiceClass:GetSelectedValue(): number | string
|
|
133
|
+
return self._choices[self._selectedIndex].Id
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
--- Sets a callback function to be invoked whenever the selected value changes.
|
|
137
|
+
--- @param vcf (newValue: number | string) -> () -- A function that receives the new selected index as a parameter.
|
|
138
|
+
function LabeledMultiChoiceClass:SetValueChangedFunction(vcf: (newValue: number | string) -> ())
|
|
139
|
+
self._valueChangedFunction = vcf
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
--- Retrieves the main frame containing the multi-choice UI elements.
|
|
143
|
+
--- @return Frame -- The UI frame of the multi-choice component.
|
|
144
|
+
function LabeledMultiChoiceClass:GetFrame(): Frame
|
|
145
|
+
return self._vsl:GetFrame()
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
--- Sets the horizontal size of each cell (button) in the multi-choice grid layout.
|
|
149
|
+
--- @param cellSize number -- The desired horizontal size in pixels.
|
|
150
|
+
function LabeledMultiChoiceClass:SetCellHorizontalSize(cellSize: number)
|
|
151
|
+
local size = self._uiGridLayout.CellSize :: UDim2
|
|
152
|
+
self._uiGridLayout.CellSize = UDim2.new(size.X.Scale, cellSize, size.Y.Scale, size.Y.Offset)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
--- Sets the vertical size of each cell (button) in the multi-choice grid layout.
|
|
156
|
+
--- @param cellSize number -- The desired vertical size in pixels.
|
|
157
|
+
function LabeledMultiChoiceClass:SetCellVerticalSize(cellSize: number)
|
|
158
|
+
local size = self._uiGridLayout.CellSize :: UDim2
|
|
159
|
+
self._uiGridLayout.CellSize = UDim2.new(size.X.Scale, size.X.Offset, size.Y.Scale, cellSize)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
return LabeledMultiChoiceClass
|