@babylonjs/gui 9.15.0 → 9.16.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.
Files changed (64) hide show
  1. package/2D/controls/checkbox.pure.js +164 -153
  2. package/2D/controls/checkbox.pure.js.map +1 -1
  3. package/2D/controls/colorpicker.pure.js +1300 -1289
  4. package/2D/controls/colorpicker.pure.js.map +1 -1
  5. package/2D/controls/container.pure.js +597 -582
  6. package/2D/controls/container.pure.js.map +1 -1
  7. package/2D/controls/control.pure.js +2474 -2434
  8. package/2D/controls/control.pure.js.map +1 -1
  9. package/2D/controls/displayGrid.pure.js +201 -190
  10. package/2D/controls/displayGrid.pure.js.map +1 -1
  11. package/2D/controls/ellipse.pure.js +96 -85
  12. package/2D/controls/ellipse.pure.js.map +1 -1
  13. package/2D/controls/grid.pure.js +511 -500
  14. package/2D/controls/grid.pure.js.map +1 -1
  15. package/2D/controls/image.pure.js +888 -877
  16. package/2D/controls/image.pure.js.map +1 -1
  17. package/2D/controls/inputText.pure.js +988 -973
  18. package/2D/controls/inputText.pure.js.map +1 -1
  19. package/2D/controls/inputTextArea.pure.js +955 -944
  20. package/2D/controls/inputTextArea.pure.js.map +1 -1
  21. package/2D/controls/line.pure.js +237 -226
  22. package/2D/controls/line.pure.js.map +1 -1
  23. package/2D/controls/multiLine.pure.js +233 -222
  24. package/2D/controls/multiLine.pure.js.map +1 -1
  25. package/2D/controls/radioButton.pure.js +182 -169
  26. package/2D/controls/radioButton.pure.js.map +1 -1
  27. package/2D/controls/rectangle.pure.js +211 -200
  28. package/2D/controls/rectangle.pure.js.map +1 -1
  29. package/2D/controls/scrollViewers/scrollViewer.pure.js +579 -567
  30. package/2D/controls/scrollViewers/scrollViewer.pure.js.map +1 -1
  31. package/2D/controls/sliders/baseSlider.js +291 -280
  32. package/2D/controls/sliders/baseSlider.js.map +1 -1
  33. package/2D/controls/sliders/imageBasedSlider.pure.js +158 -147
  34. package/2D/controls/sliders/imageBasedSlider.pure.js.map +1 -1
  35. package/2D/controls/sliders/imageScrollBar.js +237 -223
  36. package/2D/controls/sliders/imageScrollBar.js.map +1 -1
  37. package/2D/controls/sliders/scrollBar.pure.js +169 -158
  38. package/2D/controls/sliders/scrollBar.pure.js.map +1 -1
  39. package/2D/controls/sliders/slider.pure.js +251 -240
  40. package/2D/controls/sliders/slider.pure.js.map +1 -1
  41. package/2D/controls/stackPanel.pure.js +236 -221
  42. package/2D/controls/stackPanel.pure.js.map +1 -1
  43. package/2D/controls/textBlock.pure.js +637 -626
  44. package/2D/controls/textBlock.pure.js.map +1 -1
  45. package/3D/materials/fluent/fluentMaterial.pure.d.ts +4 -4
  46. package/3D/materials/fluent/fluentMaterial.pure.js +322 -273
  47. package/3D/materials/fluent/fluentMaterial.pure.js.map +1 -1
  48. package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js +510 -454
  49. package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js.map +1 -1
  50. package/3D/materials/fluentButton/fluentButtonMaterial.pure.js +612 -529
  51. package/3D/materials/fluentButton/fluentButtonMaterial.pure.js.map +1 -1
  52. package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js +313 -274
  53. package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js.map +1 -1
  54. package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js +462 -405
  55. package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js.map +1 -1
  56. package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js +583 -501
  57. package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js.map +1 -1
  58. package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js +226 -203
  59. package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js.map +1 -1
  60. package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js +961 -825
  61. package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js.map +1 -1
  62. package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js +961 -825
  63. package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js.map +1 -1
  64. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { __decorate } from "@babylonjs/core/tslib.es6.js";
1
+ import { __esDecorate, __runInitializers } from "@babylonjs/core/tslib.es6.js";
2
2
  import { Observable } from "@babylonjs/core/Misc/observable.js";
3
3
  import { Control } from "./control.pure.js";
4
4
  import { InputText } from "./inputText.pure.js";
@@ -11,1386 +11,1397 @@ import { Color3 } from "@babylonjs/core/Maths/math.color.pure.js";
11
11
  import { serialize } from "@babylonjs/core/Misc/decorators.js";
12
12
  import { EngineStore } from "@babylonjs/core/Engines/engineStore.js";
13
13
  /** Class used to create color pickers */
14
- export class ColorPicker extends Control {
15
- /** Gets or sets the color of the color picker */
16
- get value() {
17
- return this._value;
18
- }
19
- set value(value) {
20
- if (this._value.equals(value)) {
21
- return;
22
- }
23
- this._value.copyFrom(value);
24
- this._value.toHSVToRef(this._tmpColor);
25
- this._h = this._tmpColor.r;
26
- this._s = Math.max(this._tmpColor.g, 0.00001);
27
- this._v = Math.max(this._tmpColor.b, 0.00001);
28
- this._markAsDirty();
29
- if (this._value.r <= ColorPicker._Epsilon) {
30
- this._value.r = 0;
31
- }
32
- if (this._value.g <= ColorPicker._Epsilon) {
33
- this._value.g = 0;
34
- }
35
- if (this._value.b <= ColorPicker._Epsilon) {
36
- this._value.b = 0;
37
- }
38
- if (this._value.r >= 1.0 - ColorPicker._Epsilon) {
39
- this._value.r = 1.0;
40
- }
41
- if (this._value.g >= 1.0 - ColorPicker._Epsilon) {
42
- this._value.g = 1.0;
43
- }
44
- if (this._value.b >= 1.0 - ColorPicker._Epsilon) {
45
- this._value.b = 1.0;
46
- }
47
- this.onValueChangedObservable.notifyObservers(this._value, undefined, this, this);
48
- }
49
- /**
50
- * Gets or sets control width
51
- * @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#position-and-size
52
- */
53
- get width() {
54
- return this._width.toString(this._host);
55
- }
56
- set width(value) {
57
- if (this._width.toString(this._host) === value) {
58
- return;
59
- }
60
- if (this._width.fromString(value)) {
61
- if (this._width.getValue(this._host) === 0) {
62
- value = "1px";
63
- this._width.fromString(value);
64
- }
65
- this._height.fromString(value);
66
- this._markAsDirty();
67
- }
68
- }
69
- /**
70
- * Gets or sets control height
71
- * @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#position-and-size
72
- */
73
- get height() {
74
- return this._height.toString(this._host);
75
- }
76
- /** Gets or sets control height */
77
- set height(value) {
78
- if (this._height.toString(this._host) === value) {
79
- return;
80
- }
81
- if (this._height.fromString(value)) {
82
- if (this._height.getValue(this._host) === 0) {
83
- value = "1px";
84
- this._height.fromString(value);
14
+ let ColorPicker = (() => {
15
+ var _a;
16
+ let _classSuper = Control;
17
+ let _instanceExtraInitializers = [];
18
+ let _get_value_decorators;
19
+ let _get_width_decorators;
20
+ let _get_height_decorators;
21
+ let _get_size_decorators;
22
+ return _a = class ColorPicker extends _classSuper {
23
+ /** Gets or sets the color of the color picker */
24
+ get value() {
25
+ return this._value;
85
26
  }
86
- this._width.fromString(value);
87
- this._markAsDirty();
88
- }
89
- }
90
- /** Gets or sets control size */
91
- get size() {
92
- return this.width;
93
- }
94
- set size(value) {
95
- this.width = value;
96
- }
97
- /**
98
- * Creates a new ColorPicker
99
- * @param name defines the control name
100
- */
101
- constructor(name) {
102
- super(name);
103
- this.name = name;
104
- this._value = Color3.Red();
105
- this._tmpColor = new Color3();
106
- this._pointerStartedOnSquare = false;
107
- this._pointerStartedOnWheel = false;
108
- this._squareLeft = 0;
109
- this._squareTop = 0;
110
- this._squareSize = 0;
111
- this._h = 360;
112
- this._s = 1;
113
- this._v = 1;
114
- this._lastPointerDownId = -1;
115
- /**
116
- * Observable raised when the value changes
117
- */
118
- this.onValueChangedObservable = new Observable();
119
- // Events
120
- this._pointerIsDown = false;
121
- this.value = new Color3(0.88, 0.1, 0.1);
122
- this.size = "200px";
123
- this.isPointerBlocker = true;
124
- }
125
- _getTypeName() {
126
- return "ColorPicker";
127
- }
128
- /**
129
- * @internal
130
- */
131
- _preMeasure(parentMeasure) {
132
- if (parentMeasure.width < parentMeasure.height) {
133
- this._currentMeasure.height = parentMeasure.width;
134
- }
135
- else {
136
- this._currentMeasure.width = parentMeasure.height;
137
- }
138
- }
139
- _updateSquareProps() {
140
- const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
141
- const wheelThickness = radius * 0.2;
142
- const innerDiameter = (radius - wheelThickness) * 2;
143
- const squareSize = innerDiameter / Math.sqrt(2);
144
- const offset = radius - squareSize * 0.5;
145
- this._squareLeft = this._currentMeasure.left + offset;
146
- this._squareTop = this._currentMeasure.top + offset;
147
- this._squareSize = squareSize;
148
- }
149
- _drawGradientSquare(hueValue, left, top, width, height, context) {
150
- const lgh = context.createLinearGradient(left, top, width + left, top);
151
- lgh.addColorStop(0, "#fff");
152
- lgh.addColorStop(1, "hsl(" + hueValue + ", 100%, 50%)");
153
- context.fillStyle = lgh;
154
- context.fillRect(left, top, width, height);
155
- const lgv = context.createLinearGradient(left, top, left, height + top);
156
- lgv.addColorStop(0, "rgba(0,0,0,0)");
157
- lgv.addColorStop(1, "#000");
158
- context.fillStyle = lgv;
159
- context.fillRect(left, top, width, height);
160
- }
161
- _drawCircle(centerX, centerY, radius, context) {
162
- context.beginPath();
163
- context.arc(centerX, centerY, radius + 1, 0, 2 * Math.PI, false);
164
- context.lineWidth = 3;
165
- context.strokeStyle = "#333333";
166
- context.stroke();
167
- context.beginPath();
168
- context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
169
- context.lineWidth = 3;
170
- context.strokeStyle = "#ffffff";
171
- context.stroke();
172
- }
173
- _createColorWheelCanvas(radius, thickness) {
174
- // Shoudl abstract platform instead of using LastCreatedEngine
175
- const engine = EngineStore.LastCreatedEngine;
176
- if (!engine) {
177
- throw new Error("Invalid engine. Unable to create a canvas.");
178
- }
179
- const canvas = engine.createCanvas(radius * 2, radius * 2);
180
- const context = canvas.getContext("2d");
181
- const image = context.getImageData(0, 0, radius * 2, radius * 2);
182
- const data = image.data;
183
- const color = this._tmpColor;
184
- const maxDistSq = radius * radius;
185
- const innerRadius = radius - thickness;
186
- const minDistSq = innerRadius * innerRadius;
187
- for (let x = -radius; x < radius; x++) {
188
- for (let y = -radius; y < radius; y++) {
189
- const distSq = x * x + y * y;
190
- if (distSq > maxDistSq || distSq < minDistSq) {
191
- continue;
27
+ set value(value) {
28
+ if (this._value.equals(value)) {
29
+ return;
192
30
  }
193
- const dist = Math.sqrt(distSq);
194
- const ang = Math.atan2(y, x);
195
- Color3.HSVtoRGBToRef((ang * 180) / Math.PI + 180, dist / radius, 1, color);
196
- const index = (x + radius + (y + radius) * 2 * radius) * 4;
197
- data[index] = color.r * 255;
198
- data[index + 1] = color.g * 255;
199
- data[index + 2] = color.b * 255;
200
- //apply less alpha to bigger color pickers
201
- let alphaAmount;
202
- const maxAlpha = 0.2;
203
- const minAlpha = 0.04;
204
- const lowerRadius = 50;
205
- const upperRadius = 150;
206
- if (radius < lowerRadius) {
207
- alphaAmount = maxAlpha;
31
+ this._value.copyFrom(value);
32
+ this._value.toHSVToRef(this._tmpColor);
33
+ this._h = this._tmpColor.r;
34
+ this._s = Math.max(this._tmpColor.g, 0.00001);
35
+ this._v = Math.max(this._tmpColor.b, 0.00001);
36
+ this._markAsDirty();
37
+ if (this._value.r <= _a._Epsilon) {
38
+ this._value.r = 0;
208
39
  }
209
- else if (radius > upperRadius) {
210
- alphaAmount = minAlpha;
40
+ if (this._value.g <= _a._Epsilon) {
41
+ this._value.g = 0;
211
42
  }
212
- else {
213
- alphaAmount = ((minAlpha - maxAlpha) * (radius - lowerRadius)) / (upperRadius - lowerRadius) + maxAlpha;
43
+ if (this._value.b <= _a._Epsilon) {
44
+ this._value.b = 0;
214
45
  }
215
- const alphaRatio = (dist - innerRadius) / (radius - innerRadius);
216
- if (alphaRatio < alphaAmount) {
217
- data[index + 3] = 255 * (alphaRatio / alphaAmount);
46
+ if (this._value.r >= 1.0 - _a._Epsilon) {
47
+ this._value.r = 1.0;
218
48
  }
219
- else if (alphaRatio > 1 - alphaAmount) {
220
- data[index + 3] = 255 * (1.0 - (alphaRatio - (1 - alphaAmount)) / alphaAmount);
49
+ if (this._value.g >= 1.0 - _a._Epsilon) {
50
+ this._value.g = 1.0;
221
51
  }
222
- else {
223
- data[index + 3] = 255;
52
+ if (this._value.b >= 1.0 - _a._Epsilon) {
53
+ this._value.b = 1.0;
224
54
  }
55
+ this.onValueChangedObservable.notifyObservers(this._value, undefined, this, this);
225
56
  }
226
- }
227
- context.putImageData(image, 0, 0);
228
- return canvas;
229
- }
230
- /**
231
- * @internal
232
- */
233
- _draw(context) {
234
- context.save();
235
- this._applyStates(context);
236
- const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
237
- const wheelThickness = radius * 0.2;
238
- const left = this._currentMeasure.left;
239
- const top = this._currentMeasure.top;
240
- if (!this._colorWheelCanvas || this._colorWheelCanvas.width != radius * 2) {
241
- this._colorWheelCanvas = this._createColorWheelCanvas(radius, wheelThickness);
242
- }
243
- this._updateSquareProps();
244
- if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
245
- context.shadowColor = this.shadowColor;
246
- context.shadowBlur = this.shadowBlur;
247
- context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
248
- context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
249
- context.fillRect(this._squareLeft, this._squareTop, this._squareSize, this._squareSize);
250
- }
251
- context.drawImage(this._colorWheelCanvas, left, top);
252
- if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
253
- context.shadowBlur = 0;
254
- context.shadowOffsetX = 0;
255
- context.shadowOffsetY = 0;
256
- }
257
- this._drawGradientSquare(this._h, this._squareLeft, this._squareTop, this._squareSize, this._squareSize, context);
258
- let cx = this._squareLeft + this._squareSize * this._s;
259
- let cy = this._squareTop + this._squareSize * (1 - this._v);
260
- this._drawCircle(cx, cy, radius * 0.04, context);
261
- const dist = radius - wheelThickness * 0.5;
262
- cx = left + radius + Math.cos(((this._h - 180) * Math.PI) / 180) * dist;
263
- cy = top + radius + Math.sin(((this._h - 180) * Math.PI) / 180) * dist;
264
- this._drawCircle(cx, cy, wheelThickness * 0.35, context);
265
- context.restore();
266
- }
267
- _updateValueFromPointer(x, y) {
268
- if (this._pointerStartedOnWheel) {
269
- const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
270
- const centerX = radius + this._currentMeasure.left;
271
- const centerY = radius + this._currentMeasure.top;
272
- this._h = (Math.atan2(y - centerY, x - centerX) * 180) / Math.PI + 180;
273
- }
274
- else if (this._pointerStartedOnSquare) {
275
- this._updateSquareProps();
276
- this._s = (x - this._squareLeft) / this._squareSize;
277
- this._v = 1 - (y - this._squareTop) / this._squareSize;
278
- this._s = Math.min(this._s, 1);
279
- this._s = Math.max(this._s, ColorPicker._Epsilon);
280
- this._v = Math.min(this._v, 1);
281
- this._v = Math.max(this._v, ColorPicker._Epsilon);
282
- }
283
- Color3.HSVtoRGBToRef(this._h, this._s, this._v, this._tmpColor);
284
- this.value = this._tmpColor;
285
- }
286
- _isPointOnSquare(x, y) {
287
- this._updateSquareProps();
288
- const left = this._squareLeft;
289
- const top = this._squareTop;
290
- const size = this._squareSize;
291
- if (x >= left && x <= left + size && y >= top && y <= top + size) {
292
- return true;
293
- }
294
- return false;
295
- }
296
- _isPointOnWheel(x, y) {
297
- const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
298
- const centerX = radius + this._currentMeasure.left;
299
- const centerY = radius + this._currentMeasure.top;
300
- const wheelThickness = radius * 0.2;
301
- const innerRadius = radius - wheelThickness;
302
- const radiusSq = radius * radius;
303
- const innerRadiusSq = innerRadius * innerRadius;
304
- const dx = x - centerX;
305
- const dy = y - centerY;
306
- const distSq = dx * dx + dy * dy;
307
- if (distSq <= radiusSq && distSq >= innerRadiusSq) {
308
- return true;
309
- }
310
- return false;
311
- }
312
- _onPointerDown(target, coordinates, pointerId, buttonIndex, pi) {
313
- if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex, pi)) {
314
- return false;
315
- }
316
- if (this.isReadOnly) {
317
- return true;
318
- }
319
- this._pointerIsDown = true;
320
- this._pointerStartedOnSquare = false;
321
- this._pointerStartedOnWheel = false;
322
- // Invert transform
323
- this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
324
- const x = this._transformedPosition.x;
325
- const y = this._transformedPosition.y;
326
- if (this._isPointOnSquare(x, y)) {
327
- this._pointerStartedOnSquare = true;
328
- }
329
- else if (this._isPointOnWheel(x, y)) {
330
- this._pointerStartedOnWheel = true;
331
- }
332
- this._updateValueFromPointer(x, y);
333
- this._host._capturingControl[pointerId] = this;
334
- this._lastPointerDownId = pointerId;
335
- return true;
336
- }
337
- _onPointerMove(target, coordinates, pointerId, pi) {
338
- // Only listen to pointer move events coming from the last pointer to click on the element (To support dual vr controller interaction)
339
- if (pointerId != this._lastPointerDownId) {
340
- return;
341
- }
342
- if (!this.isReadOnly) {
343
- // Invert transform
344
- this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
345
- const x = this._transformedPosition.x;
346
- const y = this._transformedPosition.y;
347
- if (this._pointerIsDown) {
348
- this._updateValueFromPointer(x, y);
349
- }
350
- }
351
- super._onPointerMove(target, coordinates, pointerId, pi);
352
- }
353
- _onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick, pi) {
354
- this._pointerIsDown = false;
355
- delete this._host._capturingControl[pointerId];
356
- super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick, pi);
357
- }
358
- _onCanvasBlur() {
359
- this._forcePointerUp();
360
- super._onCanvasBlur();
361
- }
362
- /**
363
- * This function expands the color picker by creating a color picker dialog with manual
364
- * color value input and the ability to save colors into an array to be used later in
365
- * subsequent launches of the dialogue.
366
- * @param advancedTexture defines the AdvancedDynamicTexture the dialog is assigned to
367
- * @param options defines size for dialog and options for saved colors. Also accepts last color picked as hex string and saved colors array as hex strings.
368
- * @param options.pickerWidth
369
- * @param options.pickerHeight
370
- * @param options.headerHeight
371
- * @param options.lastColor
372
- * @param options.swatchLimit
373
- * @param options.numSwatchesPerLine
374
- * @param options.savedColors
375
- * @returns picked color as a hex string and the saved colors array as hex strings.
376
- */
377
- static async ShowPickerDialogAsync(advancedTexture, options) {
378
- return await new Promise((resolve) => {
379
- // Default options
380
- options.pickerWidth = options.pickerWidth || "640px";
381
- options.pickerHeight = options.pickerHeight || "400px";
382
- options.headerHeight = options.headerHeight || "35px";
383
- options.lastColor = options.lastColor || "#000000";
384
- options.swatchLimit = options.swatchLimit || 20;
385
- options.numSwatchesPerLine = options.numSwatchesPerLine || 10;
386
- // Window size settings
387
- const drawerMaxRows = options.swatchLimit / options.numSwatchesPerLine;
388
- const rawSwatchSize = parseFloat(options.pickerWidth) / options.numSwatchesPerLine;
389
- const gutterSize = Math.floor(rawSwatchSize * 0.25);
390
- const colGutters = gutterSize * (options.numSwatchesPerLine + 1);
391
- const swatchSize = Math.floor((parseFloat(options.pickerWidth) - colGutters) / options.numSwatchesPerLine);
392
- const drawerMaxSize = swatchSize * drawerMaxRows + gutterSize * (drawerMaxRows + 1);
393
- const containerSize = (parseInt(options.pickerHeight) + drawerMaxSize + Math.floor(swatchSize * 0.25)).toString() + "px";
394
- // Button Colors
395
- const buttonColor = "#c0c0c0";
396
- const buttonBackgroundColor = "#535353";
397
- const buttonBackgroundHoverColor = "#414141";
398
- const buttonBackgroundClickColor = "515151";
399
- const buttonDisabledColor = "#555555";
400
- const buttonDisabledBackgroundColor = "#454545";
401
- const currentSwatchesOutlineColor = "#404040";
402
- const luminanceLimitColor = Color3.FromHexString("#dddddd");
403
- const luminanceLimit = luminanceLimitColor.r + luminanceLimitColor.g + luminanceLimitColor.b;
404
- const iconColorDark = "#aaaaaa";
405
- const iconColorLight = "#ffffff";
406
- // Button settings
407
- let buttonFontSize;
408
- let butEdit;
409
- // Input Text Colors
410
- const inputFieldLabels = ["R", "G", "B"];
411
- const inputTextBackgroundColor = "#454545";
412
- const inputTextColor = "#f0f0f0";
413
- // This int is used for naming swatches and serves as the index for calling them from the list
414
- let swatchNumber;
415
- // Menu Panel options. We need to know if the swatchDrawer exists so we can create it if needed.
416
- let swatchDrawer;
417
- let editSwatchMode = false;
418
- // Color InputText fields that will be updated upon value change
419
- let butSave;
420
- let lastVal;
421
- let activeField;
422
- // Dialog menu container which will contain both the main dialogue window and the swatch drawer which opens once a color is saved.
423
- const dialogContainer = new Grid();
424
- dialogContainer.name = "Dialog Container";
425
- dialogContainer.width = options.pickerWidth;
426
- if (options.savedColors) {
427
- dialogContainer.height = containerSize;
428
- const topRow = parseInt(options.pickerHeight) / parseInt(containerSize);
429
- dialogContainer.addRowDefinition(topRow, false);
430
- dialogContainer.addRowDefinition(1.0 - topRow, false);
431
- }
432
- else {
433
- dialogContainer.height = options.pickerHeight;
434
- dialogContainer.addRowDefinition(1.0, false);
57
+ /**
58
+ * Gets or sets control width
59
+ * @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#position-and-size
60
+ */
61
+ get width() {
62
+ return this._width.toString(this._host);
435
63
  }
436
- advancedTexture.addControl(dialogContainer);
437
- // Swatch drawer which contains all saved color buttons
438
- if (options.savedColors) {
439
- swatchDrawer = new Grid();
440
- swatchDrawer.name = "Swatch Drawer";
441
- swatchDrawer.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
442
- swatchDrawer.background = buttonBackgroundColor;
443
- swatchDrawer.width = options.pickerWidth;
444
- const initialRows = options.savedColors.length / options.numSwatchesPerLine;
445
- let gutterCount;
446
- if (initialRows == 0) {
447
- gutterCount = 0;
448
- }
449
- else {
450
- gutterCount = initialRows + 1;
64
+ set width(value) {
65
+ if (this._width.toString(this._host) === value) {
66
+ return;
451
67
  }
452
- swatchDrawer.height = (swatchSize * initialRows + gutterCount * gutterSize).toString() + "px";
453
- swatchDrawer.top = Math.floor(swatchSize * 0.25).toString() + "px";
454
- for (let i = 0; i < Math.ceil(options.savedColors.length / options.numSwatchesPerLine) * 2 + 1; i++) {
455
- if (i % 2 != 0) {
456
- swatchDrawer.addRowDefinition(swatchSize, true);
457
- }
458
- else {
459
- swatchDrawer.addRowDefinition(gutterSize, true);
68
+ if (this._width.fromString(value)) {
69
+ if (this._width.getValue(this._host) === 0) {
70
+ value = "1px";
71
+ this._width.fromString(value);
460
72
  }
73
+ this._height.fromString(value);
74
+ this._markAsDirty();
461
75
  }
462
- for (let i = 0; i < options.numSwatchesPerLine * 2 + 1; i++) {
463
- if (i % 2 != 0) {
464
- swatchDrawer.addColumnDefinition(swatchSize, true);
465
- }
466
- else {
467
- swatchDrawer.addColumnDefinition(gutterSize, true);
468
- }
469
- }
470
- dialogContainer.addControl(swatchDrawer, 1, 0);
471
- }
472
- // Picker container
473
- const pickerPanel = new Grid();
474
- pickerPanel.name = "Picker Panel";
475
- pickerPanel.height = options.pickerHeight;
476
- const panelHead = parseInt(options.headerHeight) / parseInt(options.pickerHeight);
477
- const pickerPanelRows = [panelHead, 1.0 - panelHead];
478
- pickerPanel.addRowDefinition(pickerPanelRows[0], false);
479
- pickerPanel.addRowDefinition(pickerPanelRows[1], false);
480
- dialogContainer.addControl(pickerPanel, 0, 0);
481
- // Picker container header
482
- const header = new Rectangle();
483
- header.name = "Dialogue Header Bar";
484
- header.background = "#cccccc";
485
- header.thickness = 0;
486
- pickerPanel.addControl(header, 0, 0);
487
- // Header close button
488
- const closeButton = Button.CreateSimpleButton("closeButton", "a");
489
- closeButton.fontFamily = "coreglyphs";
490
- const headerColor3 = Color3.FromHexString(header.background);
491
- const closeIconColor = new Color3(1.0 - headerColor3.r, 1.0 - headerColor3.g, 1.0 - headerColor3.b);
492
- closeButton.color = closeIconColor.toHexString();
493
- closeButton.fontSize = Math.floor(parseInt(options.headerHeight) * 0.6);
494
- closeButton.textBlock.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
495
- closeButton.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
496
- closeButton.height = closeButton.width = options.headerHeight;
497
- closeButton.background = header.background;
498
- closeButton.thickness = 0;
499
- closeButton.pointerDownAnimation = () => { };
500
- closeButton.pointerUpAnimation = () => {
501
- closeButton.background = header.background;
502
- };
503
- closeButton.pointerEnterAnimation = () => {
504
- closeButton.color = header.background;
505
- closeButton.background = "red";
506
- };
507
- closeButton.pointerOutAnimation = () => {
508
- closeButton.color = closeIconColor.toHexString();
509
- closeButton.background = header.background;
510
- };
511
- closeButton.onPointerClickObservable.add(() => {
512
- closePicker(currentSwatch.background);
513
- });
514
- pickerPanel.addControl(closeButton, 0, 0);
515
- // Dialog container body
516
- const dialogBody = new Grid();
517
- dialogBody.name = "Dialogue Body";
518
- dialogBody.background = buttonBackgroundColor;
519
- const dialogBodyCols = [0.4375, 0.5625];
520
- dialogBody.addRowDefinition(1.0, false);
521
- dialogBody.addColumnDefinition(dialogBodyCols[0], false);
522
- dialogBody.addColumnDefinition(dialogBodyCols[1], false);
523
- pickerPanel.addControl(dialogBody, 1, 0);
524
- // Picker grid
525
- const pickerGrid = new Grid();
526
- pickerGrid.name = "Picker Grid";
527
- pickerGrid.addRowDefinition(0.85, false);
528
- pickerGrid.addRowDefinition(0.15, false);
529
- dialogBody.addControl(pickerGrid, 0, 0);
530
- // Picker control
531
- const picker = new ColorPicker();
532
- picker.name = "GUI Color Picker";
533
- if (options.pickerHeight < options.pickerWidth) {
534
- picker.width = 0.89;
535
76
  }
536
- else {
537
- picker.height = 0.89;
77
+ /**
78
+ * Gets or sets control height
79
+ * @see https://doc.babylonjs.com/features/featuresDeepDive/gui/gui#position-and-size
80
+ */
81
+ get height() {
82
+ return this._height.toString(this._host);
538
83
  }
539
- picker.value = Color3.FromHexString(options.lastColor);
540
- picker.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
541
- picker.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
542
- picker.onPointerDownObservable.add(() => {
543
- activeField = picker.name;
544
- lastVal = "";
545
- editSwatches(false);
546
- });
547
- picker.onValueChangedObservable.add(function (value) {
548
- // value is a color3
549
- if (activeField == picker.name) {
550
- updateValues(value, picker.name);
84
+ /** Gets or sets control height */
85
+ set height(value) {
86
+ if (this._height.toString(this._host) === value) {
87
+ return;
88
+ }
89
+ if (this._height.fromString(value)) {
90
+ if (this._height.getValue(this._host) === 0) {
91
+ value = "1px";
92
+ this._height.fromString(value);
93
+ }
94
+ this._width.fromString(value);
95
+ this._markAsDirty();
551
96
  }
552
- });
553
- pickerGrid.addControl(picker, 0, 0);
554
- // Picker body right quarant
555
- const pickerBodyRight = new Grid();
556
- pickerBodyRight.name = "Dialogue Right Half";
557
- pickerBodyRight.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
558
- const pickerBodyRightRows = [0.514, 0.486];
559
- pickerBodyRight.addRowDefinition(pickerBodyRightRows[0], false);
560
- pickerBodyRight.addRowDefinition(pickerBodyRightRows[1], false);
561
- dialogBody.addControl(pickerBodyRight, 1, 1);
562
- // Picker container swatches and buttons
563
- const pickerSwatchesButtons = new Grid();
564
- pickerSwatchesButtons.name = "Swatches and Buttons";
565
- const pickerButtonsCol = [0.417, 0.583];
566
- pickerSwatchesButtons.addRowDefinition(1.0, false);
567
- pickerSwatchesButtons.addColumnDefinition(pickerButtonsCol[0], false);
568
- pickerSwatchesButtons.addColumnDefinition(pickerButtonsCol[1], false);
569
- pickerBodyRight.addControl(pickerSwatchesButtons, 0, 0);
570
- // Picker Swatches quadrant
571
- const pickerSwatches = new Grid();
572
- pickerSwatches.name = "New and Current Swatches";
573
- const pickeSwatchesRows = [0.04, 0.16, 0.64, 0.16];
574
- pickerSwatches.addRowDefinition(pickeSwatchesRows[0], false);
575
- pickerSwatches.addRowDefinition(pickeSwatchesRows[1], false);
576
- pickerSwatches.addRowDefinition(pickeSwatchesRows[2], false);
577
- pickerSwatches.addRowDefinition(pickeSwatchesRows[3], false);
578
- pickerSwatchesButtons.addControl(pickerSwatches, 0, 0);
579
- // Active swatches
580
- const activeSwatches = new Grid();
581
- activeSwatches.name = "Active Swatches";
582
- activeSwatches.width = 0.67;
583
- activeSwatches.addRowDefinition(0.5, false);
584
- activeSwatches.addRowDefinition(0.5, false);
585
- pickerSwatches.addControl(activeSwatches, 2, 0);
586
- const labelWidth = Math.floor(parseInt(options.pickerWidth) * dialogBodyCols[1] * pickerButtonsCol[0] * 0.11);
587
- const labelHeight = Math.floor(parseInt(options.pickerHeight) * pickerPanelRows[1] * pickerBodyRightRows[0] * pickeSwatchesRows[1] * 0.5);
588
- let labelTextSize;
589
- if (options.pickerWidth > options.pickerHeight) {
590
- labelTextSize = labelHeight;
591
97
  }
592
- else {
593
- labelTextSize = labelWidth;
98
+ /** Gets or sets control size */
99
+ get size() {
100
+ return this.width;
594
101
  }
595
- // New color swatch and previous color button
596
- const newText = new TextBlock();
597
- newText.text = "new";
598
- newText.name = "New Color Label";
599
- newText.color = buttonColor;
600
- newText.fontSize = labelTextSize;
601
- pickerSwatches.addControl(newText, 1, 0);
602
- const newSwatch = new Rectangle();
603
- newSwatch.name = "New Color Swatch";
604
- newSwatch.background = options.lastColor;
605
- newSwatch.thickness = 0;
606
- activeSwatches.addControl(newSwatch, 0, 0);
607
- const currentSwatch = Button.CreateSimpleButton("currentSwatch", "");
608
- currentSwatch.background = options.lastColor;
609
- currentSwatch.thickness = 0;
610
- currentSwatch.onPointerClickObservable.add(() => {
611
- const revertColor = Color3.FromHexString(currentSwatch.background);
612
- updateValues(revertColor, currentSwatch.name);
613
- editSwatches(false);
614
- });
615
- currentSwatch.pointerDownAnimation = () => { };
616
- currentSwatch.pointerUpAnimation = () => { };
617
- currentSwatch.pointerEnterAnimation = () => { };
618
- currentSwatch.pointerOutAnimation = () => { };
619
- activeSwatches.addControl(currentSwatch, 1, 0);
620
- const swatchOutline = new Rectangle();
621
- swatchOutline.name = "Swatch Outline";
622
- swatchOutline.width = 0.67;
623
- swatchOutline.thickness = 2;
624
- swatchOutline.color = currentSwatchesOutlineColor;
625
- swatchOutline.isHitTestVisible = false;
626
- pickerSwatches.addControl(swatchOutline, 2, 0);
627
- const currentText = new TextBlock();
628
- currentText.name = "Current Color Label";
629
- currentText.text = "current";
630
- currentText.color = buttonColor;
631
- currentText.fontSize = labelTextSize;
632
- pickerSwatches.addControl(currentText, 3, 0);
633
- // Buttons grid
634
- const buttonGrid = new Grid();
635
- buttonGrid.name = "Button Grid";
636
- buttonGrid.height = 0.8;
637
- const buttonGridRows = 1 / 3;
638
- buttonGrid.addRowDefinition(buttonGridRows, false);
639
- buttonGrid.addRowDefinition(buttonGridRows, false);
640
- buttonGrid.addRowDefinition(buttonGridRows, false);
641
- pickerSwatchesButtons.addControl(buttonGrid, 0, 1);
642
- // Determine pixel width and height for all buttons from overall panel dimensions
643
- const buttonWidth = Math.floor(parseInt(options.pickerWidth) * dialogBodyCols[1] * pickerButtonsCol[1] * 0.67).toString() + "px";
644
- const buttonHeight = Math.floor(parseInt(options.pickerHeight) * pickerPanelRows[1] * pickerBodyRightRows[0] * (parseFloat(buttonGrid.height.toString()) / 100) * buttonGridRows * 0.7).toString() + "px";
645
- // Determine button type size
646
- if (parseFloat(buttonWidth) > parseFloat(buttonHeight)) {
647
- buttonFontSize = Math.floor(parseFloat(buttonHeight) * 0.45);
102
+ set size(value) {
103
+ this.width = value;
104
+ }
105
+ /**
106
+ * Creates a new ColorPicker
107
+ * @param name defines the control name
108
+ */
109
+ constructor(name) {
110
+ super(name);
111
+ this.name = (__runInitializers(this, _instanceExtraInitializers), name);
112
+ this._value = Color3.Red();
113
+ this._tmpColor = new Color3();
114
+ this._pointerStartedOnSquare = false;
115
+ this._pointerStartedOnWheel = false;
116
+ this._squareLeft = 0;
117
+ this._squareTop = 0;
118
+ this._squareSize = 0;
119
+ this._h = 360;
120
+ this._s = 1;
121
+ this._v = 1;
122
+ this._lastPointerDownId = -1;
123
+ /**
124
+ * Observable raised when the value changes
125
+ */
126
+ this.onValueChangedObservable = new Observable();
127
+ // Events
128
+ this._pointerIsDown = false;
129
+ this.value = new Color3(0.88, 0.1, 0.1);
130
+ this.size = "200px";
131
+ this.isPointerBlocker = true;
648
132
  }
649
- else {
650
- buttonFontSize = Math.floor(parseFloat(buttonWidth) * 0.11);
133
+ _getTypeName() {
134
+ return "ColorPicker";
651
135
  }
652
- // Panel Buttons
653
- const butOK = Button.CreateSimpleButton("butOK", "OK");
654
- butOK.width = buttonWidth;
655
- butOK.height = buttonHeight;
656
- butOK.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
657
- butOK.thickness = 2;
658
- butOK.color = buttonColor;
659
- butOK.fontSize = buttonFontSize;
660
- butOK.background = buttonBackgroundColor;
661
- butOK.onPointerEnterObservable.add(() => {
662
- butOK.background = buttonBackgroundHoverColor;
663
- });
664
- butOK.onPointerOutObservable.add(() => {
665
- butOK.background = buttonBackgroundColor;
666
- });
667
- butOK.pointerDownAnimation = () => {
668
- butOK.background = buttonBackgroundClickColor;
669
- };
670
- butOK.pointerUpAnimation = () => {
671
- butOK.background = buttonBackgroundHoverColor;
672
- };
673
- butOK.onPointerClickObservable.add(() => {
674
- editSwatches(false);
675
- closePicker(newSwatch.background);
676
- });
677
- buttonGrid.addControl(butOK, 0, 0);
678
- const butCancel = Button.CreateSimpleButton("butCancel", "Cancel");
679
- butCancel.width = buttonWidth;
680
- butCancel.height = buttonHeight;
681
- butCancel.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
682
- butCancel.thickness = 2;
683
- butCancel.color = buttonColor;
684
- butCancel.fontSize = buttonFontSize;
685
- butCancel.background = buttonBackgroundColor;
686
- butCancel.onPointerEnterObservable.add(() => {
687
- butCancel.background = buttonBackgroundHoverColor;
688
- });
689
- butCancel.onPointerOutObservable.add(() => {
690
- butCancel.background = buttonBackgroundColor;
691
- });
692
- butCancel.pointerDownAnimation = () => {
693
- butCancel.background = buttonBackgroundClickColor;
694
- };
695
- butCancel.pointerUpAnimation = () => {
696
- butCancel.background = buttonBackgroundHoverColor;
697
- };
698
- butCancel.onPointerClickObservable.add(() => {
699
- editSwatches(false);
700
- closePicker(currentSwatch.background);
701
- });
702
- buttonGrid.addControl(butCancel, 1, 0);
703
- if (options.savedColors) {
704
- butSave = Button.CreateSimpleButton("butSave", "Save");
705
- butSave.width = buttonWidth;
706
- butSave.height = buttonHeight;
707
- butSave.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
708
- butSave.thickness = 2;
709
- butSave.fontSize = buttonFontSize;
710
- if (options.savedColors.length < options.swatchLimit) {
711
- butSave.color = buttonColor;
712
- butSave.background = buttonBackgroundColor;
136
+ /**
137
+ * @internal
138
+ */
139
+ _preMeasure(parentMeasure) {
140
+ if (parentMeasure.width < parentMeasure.height) {
141
+ this._currentMeasure.height = parentMeasure.width;
713
142
  }
714
143
  else {
715
- disableButton(butSave, true);
144
+ this._currentMeasure.width = parentMeasure.height;
716
145
  }
717
- butSave.onPointerEnterObservable.add(() => {
718
- if (options.savedColors) {
719
- if (options.savedColors.length < options.swatchLimit) {
720
- butSave.background = buttonBackgroundHoverColor;
146
+ }
147
+ _updateSquareProps() {
148
+ const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
149
+ const wheelThickness = radius * 0.2;
150
+ const innerDiameter = (radius - wheelThickness) * 2;
151
+ const squareSize = innerDiameter / Math.sqrt(2);
152
+ const offset = radius - squareSize * 0.5;
153
+ this._squareLeft = this._currentMeasure.left + offset;
154
+ this._squareTop = this._currentMeasure.top + offset;
155
+ this._squareSize = squareSize;
156
+ }
157
+ _drawGradientSquare(hueValue, left, top, width, height, context) {
158
+ const lgh = context.createLinearGradient(left, top, width + left, top);
159
+ lgh.addColorStop(0, "#fff");
160
+ lgh.addColorStop(1, "hsl(" + hueValue + ", 100%, 50%)");
161
+ context.fillStyle = lgh;
162
+ context.fillRect(left, top, width, height);
163
+ const lgv = context.createLinearGradient(left, top, left, height + top);
164
+ lgv.addColorStop(0, "rgba(0,0,0,0)");
165
+ lgv.addColorStop(1, "#000");
166
+ context.fillStyle = lgv;
167
+ context.fillRect(left, top, width, height);
168
+ }
169
+ _drawCircle(centerX, centerY, radius, context) {
170
+ context.beginPath();
171
+ context.arc(centerX, centerY, radius + 1, 0, 2 * Math.PI, false);
172
+ context.lineWidth = 3;
173
+ context.strokeStyle = "#333333";
174
+ context.stroke();
175
+ context.beginPath();
176
+ context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
177
+ context.lineWidth = 3;
178
+ context.strokeStyle = "#ffffff";
179
+ context.stroke();
180
+ }
181
+ _createColorWheelCanvas(radius, thickness) {
182
+ // Shoudl abstract platform instead of using LastCreatedEngine
183
+ const engine = EngineStore.LastCreatedEngine;
184
+ if (!engine) {
185
+ throw new Error("Invalid engine. Unable to create a canvas.");
186
+ }
187
+ const canvas = engine.createCanvas(radius * 2, radius * 2);
188
+ const context = canvas.getContext("2d");
189
+ const image = context.getImageData(0, 0, radius * 2, radius * 2);
190
+ const data = image.data;
191
+ const color = this._tmpColor;
192
+ const maxDistSq = radius * radius;
193
+ const innerRadius = radius - thickness;
194
+ const minDistSq = innerRadius * innerRadius;
195
+ for (let x = -radius; x < radius; x++) {
196
+ for (let y = -radius; y < radius; y++) {
197
+ const distSq = x * x + y * y;
198
+ if (distSq > maxDistSq || distSq < minDistSq) {
199
+ continue;
721
200
  }
722
- }
723
- });
724
- butSave.onPointerOutObservable.add(() => {
725
- if (options.savedColors) {
726
- if (options.savedColors.length < options.swatchLimit) {
727
- butSave.background = buttonBackgroundColor;
201
+ const dist = Math.sqrt(distSq);
202
+ const ang = Math.atan2(y, x);
203
+ Color3.HSVtoRGBToRef((ang * 180) / Math.PI + 180, dist / radius, 1, color);
204
+ const index = (x + radius + (y + radius) * 2 * radius) * 4;
205
+ data[index] = color.r * 255;
206
+ data[index + 1] = color.g * 255;
207
+ data[index + 2] = color.b * 255;
208
+ //apply less alpha to bigger color pickers
209
+ let alphaAmount;
210
+ const maxAlpha = 0.2;
211
+ const minAlpha = 0.04;
212
+ const lowerRadius = 50;
213
+ const upperRadius = 150;
214
+ if (radius < lowerRadius) {
215
+ alphaAmount = maxAlpha;
728
216
  }
729
- }
730
- });
731
- butSave.pointerDownAnimation = () => {
732
- if (options.savedColors) {
733
- if (options.savedColors.length < options.swatchLimit) {
734
- butSave.background = buttonBackgroundClickColor;
217
+ else if (radius > upperRadius) {
218
+ alphaAmount = minAlpha;
735
219
  }
736
- }
737
- };
738
- butSave.pointerUpAnimation = () => {
739
- if (options.savedColors) {
740
- if (options.savedColors.length < options.swatchLimit) {
741
- butSave.background = buttonBackgroundHoverColor;
220
+ else {
221
+ alphaAmount = ((minAlpha - maxAlpha) * (radius - lowerRadius)) / (upperRadius - lowerRadius) + maxAlpha;
742
222
  }
743
- }
744
- };
745
- butSave.onPointerClickObservable.add(() => {
746
- if (options.savedColors) {
747
- if (options.savedColors.length == 0) {
748
- setEditButtonVisibility(true);
223
+ const alphaRatio = (dist - innerRadius) / (radius - innerRadius);
224
+ if (alphaRatio < alphaAmount) {
225
+ data[index + 3] = 255 * (alphaRatio / alphaAmount);
749
226
  }
750
- if (options.savedColors.length < options.swatchLimit) {
751
- updateSwatches(newSwatch.background, butSave);
227
+ else if (alphaRatio > 1 - alphaAmount) {
228
+ data[index + 3] = 255 * (1.0 - (alphaRatio - (1 - alphaAmount)) / alphaAmount);
229
+ }
230
+ else {
231
+ data[index + 3] = 255;
752
232
  }
753
- editSwatches(false);
754
233
  }
755
- });
756
- if (options.savedColors.length > 0) {
757
- setEditButtonVisibility(true);
758
234
  }
759
- buttonGrid.addControl(butSave, 2, 0);
235
+ context.putImageData(image, 0, 0);
236
+ return canvas;
760
237
  }
761
- // Picker color values input
762
- const pickerColorValues = new Grid();
763
- pickerColorValues.name = "Dialog Lower Right";
764
- pickerColorValues.addRowDefinition(0.02, false);
765
- pickerColorValues.addRowDefinition(0.63, false);
766
- pickerColorValues.addRowDefinition(0.21, false);
767
- pickerColorValues.addRowDefinition(0.14, false);
768
- pickerBodyRight.addControl(pickerColorValues, 1, 0);
769
- // RGB values text boxes
770
- const currentColor = Color3.FromHexString(options.lastColor);
771
- const rgbValuesQuadrant = new Grid();
772
- rgbValuesQuadrant.name = "RGB Values";
773
- rgbValuesQuadrant.width = 0.82;
774
- rgbValuesQuadrant.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
775
- rgbValuesQuadrant.addRowDefinition(1 / 3, false);
776
- rgbValuesQuadrant.addRowDefinition(1 / 3, false);
777
- rgbValuesQuadrant.addRowDefinition(1 / 3, false);
778
- rgbValuesQuadrant.addColumnDefinition(0.1, false);
779
- rgbValuesQuadrant.addColumnDefinition(0.2, false);
780
- rgbValuesQuadrant.addColumnDefinition(0.7, false);
781
- pickerColorValues.addControl(rgbValuesQuadrant, 1, 0);
782
- for (let i = 0; i < inputFieldLabels.length; i++) {
783
- const labelText = new TextBlock();
784
- labelText.text = inputFieldLabels[i];
785
- labelText.color = buttonColor;
786
- labelText.fontSize = buttonFontSize;
787
- rgbValuesQuadrant.addControl(labelText, i, 0);
238
+ /**
239
+ * @internal
240
+ */
241
+ _draw(context) {
242
+ context.save();
243
+ this._applyStates(context);
244
+ const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
245
+ const wheelThickness = radius * 0.2;
246
+ const left = this._currentMeasure.left;
247
+ const top = this._currentMeasure.top;
248
+ if (!this._colorWheelCanvas || this._colorWheelCanvas.width != radius * 2) {
249
+ this._colorWheelCanvas = this._createColorWheelCanvas(radius, wheelThickness);
250
+ }
251
+ this._updateSquareProps();
252
+ if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
253
+ context.shadowColor = this.shadowColor;
254
+ context.shadowBlur = this.shadowBlur;
255
+ context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
256
+ context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
257
+ context.fillRect(this._squareLeft, this._squareTop, this._squareSize, this._squareSize);
258
+ }
259
+ context.drawImage(this._colorWheelCanvas, left, top);
260
+ if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
261
+ context.shadowBlur = 0;
262
+ context.shadowOffsetX = 0;
263
+ context.shadowOffsetY = 0;
264
+ }
265
+ this._drawGradientSquare(this._h, this._squareLeft, this._squareTop, this._squareSize, this._squareSize, context);
266
+ let cx = this._squareLeft + this._squareSize * this._s;
267
+ let cy = this._squareTop + this._squareSize * (1 - this._v);
268
+ this._drawCircle(cx, cy, radius * 0.04, context);
269
+ const dist = radius - wheelThickness * 0.5;
270
+ cx = left + radius + Math.cos(((this._h - 180) * Math.PI) / 180) * dist;
271
+ cy = top + radius + Math.sin(((this._h - 180) * Math.PI) / 180) * dist;
272
+ this._drawCircle(cx, cy, wheelThickness * 0.35, context);
273
+ context.restore();
788
274
  }
789
- // Input fields for RGB values
790
- const rValInt = new InputText();
791
- rValInt.width = 0.83;
792
- rValInt.height = 0.72;
793
- rValInt.name = "rIntField";
794
- rValInt.fontSize = buttonFontSize;
795
- rValInt.text = (currentColor.r * 255).toString();
796
- rValInt.color = inputTextColor;
797
- rValInt.background = inputTextBackgroundColor;
798
- rValInt.onFocusObservable.add(() => {
799
- activeField = rValInt.name;
800
- lastVal = rValInt.text;
801
- editSwatches(false);
802
- });
803
- rValInt.onBlurObservable.add(() => {
804
- if (rValInt.text == "") {
805
- rValInt.text = "0";
806
- }
807
- updateInt(rValInt, "r");
808
- if (activeField == rValInt.name) {
809
- activeField = "";
810
- }
811
- });
812
- rValInt.onTextChangedObservable.add(() => {
813
- if (activeField == rValInt.name) {
814
- updateInt(rValInt, "r");
815
- }
816
- });
817
- rgbValuesQuadrant.addControl(rValInt, 0, 1);
818
- const gValInt = new InputText();
819
- gValInt.width = 0.83;
820
- gValInt.height = 0.72;
821
- gValInt.name = "gIntField";
822
- gValInt.fontSize = buttonFontSize;
823
- gValInt.text = (currentColor.g * 255).toString();
824
- gValInt.color = inputTextColor;
825
- gValInt.background = inputTextBackgroundColor;
826
- gValInt.onFocusObservable.add(() => {
827
- activeField = gValInt.name;
828
- lastVal = gValInt.text;
829
- editSwatches(false);
830
- });
831
- gValInt.onBlurObservable.add(() => {
832
- if (gValInt.text == "") {
833
- gValInt.text = "0";
834
- }
835
- updateInt(gValInt, "g");
836
- if (activeField == gValInt.name) {
837
- activeField = "";
838
- }
839
- });
840
- gValInt.onTextChangedObservable.add(() => {
841
- if (activeField == gValInt.name) {
842
- updateInt(gValInt, "g");
843
- }
844
- });
845
- rgbValuesQuadrant.addControl(gValInt, 1, 1);
846
- const bValInt = new InputText();
847
- bValInt.width = 0.83;
848
- bValInt.height = 0.72;
849
- bValInt.name = "bIntField";
850
- bValInt.fontSize = buttonFontSize;
851
- bValInt.text = (currentColor.b * 255).toString();
852
- bValInt.color = inputTextColor;
853
- bValInt.background = inputTextBackgroundColor;
854
- bValInt.onFocusObservable.add(() => {
855
- activeField = bValInt.name;
856
- lastVal = bValInt.text;
857
- editSwatches(false);
858
- });
859
- bValInt.onBlurObservable.add(() => {
860
- if (bValInt.text == "") {
861
- bValInt.text = "0";
862
- }
863
- updateInt(bValInt, "b");
864
- if (activeField == bValInt.name) {
865
- activeField = "";
866
- }
867
- });
868
- bValInt.onTextChangedObservable.add(() => {
869
- if (activeField == bValInt.name) {
870
- updateInt(bValInt, "b");
871
- }
872
- });
873
- rgbValuesQuadrant.addControl(bValInt, 2, 1);
874
- const rValDec = new InputText();
875
- rValDec.width = 0.95;
876
- rValDec.height = 0.72;
877
- rValDec.name = "rDecField";
878
- rValDec.fontSize = buttonFontSize;
879
- rValDec.text = currentColor.r.toString();
880
- rValDec.color = inputTextColor;
881
- rValDec.background = inputTextBackgroundColor;
882
- rValDec.onFocusObservable.add(() => {
883
- activeField = rValDec.name;
884
- lastVal = rValDec.text;
885
- editSwatches(false);
886
- });
887
- rValDec.onBlurObservable.add(() => {
888
- if (parseFloat(rValDec.text) == 0 || rValDec.text == "") {
889
- rValDec.text = "0";
890
- updateFloat(rValDec, "r");
891
- }
892
- if (activeField == rValDec.name) {
893
- activeField = "";
894
- }
895
- });
896
- rValDec.onTextChangedObservable.add(() => {
897
- if (activeField == rValDec.name) {
898
- updateFloat(rValDec, "r");
899
- }
900
- });
901
- rgbValuesQuadrant.addControl(rValDec, 0, 2);
902
- const gValDec = new InputText();
903
- gValDec.width = 0.95;
904
- gValDec.height = 0.72;
905
- gValDec.name = "gDecField";
906
- gValDec.fontSize = buttonFontSize;
907
- gValDec.text = currentColor.g.toString();
908
- gValDec.color = inputTextColor;
909
- gValDec.background = inputTextBackgroundColor;
910
- gValDec.onFocusObservable.add(() => {
911
- activeField = gValDec.name;
912
- lastVal = gValDec.text;
913
- editSwatches(false);
914
- });
915
- gValDec.onBlurObservable.add(() => {
916
- if (parseFloat(gValDec.text) == 0 || gValDec.text == "") {
917
- gValDec.text = "0";
918
- updateFloat(gValDec, "g");
919
- }
920
- if (activeField == gValDec.name) {
921
- activeField = "";
922
- }
923
- });
924
- gValDec.onTextChangedObservable.add(() => {
925
- if (activeField == gValDec.name) {
926
- updateFloat(gValDec, "g");
927
- }
928
- });
929
- rgbValuesQuadrant.addControl(gValDec, 1, 2);
930
- const bValDec = new InputText();
931
- bValDec.width = 0.95;
932
- bValDec.height = 0.72;
933
- bValDec.name = "bDecField";
934
- bValDec.fontSize = buttonFontSize;
935
- bValDec.text = currentColor.b.toString();
936
- bValDec.color = inputTextColor;
937
- bValDec.background = inputTextBackgroundColor;
938
- bValDec.onFocusObservable.add(() => {
939
- activeField = bValDec.name;
940
- lastVal = bValDec.text;
941
- editSwatches(false);
942
- });
943
- bValDec.onBlurObservable.add(() => {
944
- if (parseFloat(bValDec.text) == 0 || bValDec.text == "") {
945
- bValDec.text = "0";
946
- updateFloat(bValDec, "b");
947
- }
948
- if (activeField == bValDec.name) {
949
- activeField = "";
950
- }
951
- });
952
- bValDec.onTextChangedObservable.add(() => {
953
- if (activeField == bValDec.name) {
954
- updateFloat(bValDec, "b");
955
- }
956
- });
957
- rgbValuesQuadrant.addControl(bValDec, 2, 2);
958
- // Hex value input
959
- const hexValueQuadrant = new Grid();
960
- hexValueQuadrant.name = "Hex Value";
961
- hexValueQuadrant.width = 0.82;
962
- hexValueQuadrant.addRowDefinition(1.0, false);
963
- hexValueQuadrant.addColumnDefinition(0.1, false);
964
- hexValueQuadrant.addColumnDefinition(0.9, false);
965
- pickerColorValues.addControl(hexValueQuadrant, 2, 0);
966
- const labelText = new TextBlock();
967
- labelText.text = "#";
968
- labelText.color = buttonColor;
969
- labelText.fontSize = buttonFontSize;
970
- hexValueQuadrant.addControl(labelText, 0, 0);
971
- const hexVal = new InputText();
972
- hexVal.width = 0.96;
973
- hexVal.height = 0.72;
974
- hexVal.name = "hexField";
975
- hexVal.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
976
- hexVal.fontSize = buttonFontSize;
977
- const minusPound = options.lastColor.split("#");
978
- hexVal.text = minusPound[1];
979
- hexVal.color = inputTextColor;
980
- hexVal.background = inputTextBackgroundColor;
981
- hexVal.onFocusObservable.add(() => {
982
- activeField = hexVal.name;
983
- lastVal = hexVal.text;
984
- editSwatches(false);
985
- });
986
- hexVal.onBlurObservable.add(() => {
987
- if (hexVal.text.length == 3) {
988
- const val = hexVal.text.split("");
989
- hexVal.text = val[0] + val[0] + val[1] + val[1] + val[2] + val[2];
990
- }
991
- if (hexVal.text == "") {
992
- hexVal.text = "000000";
993
- updateValues(Color3.FromHexString(hexVal.text), "b");
994
- }
995
- if (activeField == hexVal.name) {
996
- activeField = "";
275
+ _updateValueFromPointer(x, y) {
276
+ if (this._pointerStartedOnWheel) {
277
+ const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
278
+ const centerX = radius + this._currentMeasure.left;
279
+ const centerY = radius + this._currentMeasure.top;
280
+ this._h = (Math.atan2(y - centerY, x - centerX) * 180) / Math.PI + 180;
281
+ }
282
+ else if (this._pointerStartedOnSquare) {
283
+ this._updateSquareProps();
284
+ this._s = (x - this._squareLeft) / this._squareSize;
285
+ this._v = 1 - (y - this._squareTop) / this._squareSize;
286
+ this._s = Math.min(this._s, 1);
287
+ this._s = Math.max(this._s, _a._Epsilon);
288
+ this._v = Math.min(this._v, 1);
289
+ this._v = Math.max(this._v, _a._Epsilon);
290
+ }
291
+ Color3.HSVtoRGBToRef(this._h, this._s, this._v, this._tmpColor);
292
+ this.value = this._tmpColor;
293
+ }
294
+ _isPointOnSquare(x, y) {
295
+ this._updateSquareProps();
296
+ const left = this._squareLeft;
297
+ const top = this._squareTop;
298
+ const size = this._squareSize;
299
+ if (x >= left && x <= left + size && y >= top && y <= top + size) {
300
+ return true;
301
+ }
302
+ return false;
303
+ }
304
+ _isPointOnWheel(x, y) {
305
+ const radius = Math.min(this._currentMeasure.width, this._currentMeasure.height) * 0.5;
306
+ const centerX = radius + this._currentMeasure.left;
307
+ const centerY = radius + this._currentMeasure.top;
308
+ const wheelThickness = radius * 0.2;
309
+ const innerRadius = radius - wheelThickness;
310
+ const radiusSq = radius * radius;
311
+ const innerRadiusSq = innerRadius * innerRadius;
312
+ const dx = x - centerX;
313
+ const dy = y - centerY;
314
+ const distSq = dx * dx + dy * dy;
315
+ if (distSq <= radiusSq && distSq >= innerRadiusSq) {
316
+ return true;
317
+ }
318
+ return false;
319
+ }
320
+ _onPointerDown(target, coordinates, pointerId, buttonIndex, pi) {
321
+ if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex, pi)) {
322
+ return false;
323
+ }
324
+ if (this.isReadOnly) {
325
+ return true;
326
+ }
327
+ this._pointerIsDown = true;
328
+ this._pointerStartedOnSquare = false;
329
+ this._pointerStartedOnWheel = false;
330
+ // Invert transform
331
+ this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
332
+ const x = this._transformedPosition.x;
333
+ const y = this._transformedPosition.y;
334
+ if (this._isPointOnSquare(x, y)) {
335
+ this._pointerStartedOnSquare = true;
336
+ }
337
+ else if (this._isPointOnWheel(x, y)) {
338
+ this._pointerStartedOnWheel = true;
997
339
  }
998
- });
999
- hexVal.onTextChangedObservable.add(() => {
1000
- let newHexValue = hexVal.text;
1001
- const checkHex = /[^0-9A-F]/i.test(newHexValue);
1002
- if ((hexVal.text.length > 6 || checkHex) && activeField == hexVal.name) {
1003
- hexVal.text = lastVal;
340
+ this._updateValueFromPointer(x, y);
341
+ this._host._capturingControl[pointerId] = this;
342
+ this._lastPointerDownId = pointerId;
343
+ return true;
344
+ }
345
+ _onPointerMove(target, coordinates, pointerId, pi) {
346
+ // Only listen to pointer move events coming from the last pointer to click on the element (To support dual vr controller interaction)
347
+ if (pointerId != this._lastPointerDownId) {
348
+ return;
1004
349
  }
1005
- else {
1006
- if (hexVal.text.length < 6) {
1007
- const leadingZero = 6 - hexVal.text.length;
1008
- for (let i = 0; i < leadingZero; i++) {
1009
- newHexValue = "0" + newHexValue;
1010
- }
1011
- }
1012
- if (hexVal.text.length == 3) {
1013
- const val = hexVal.text.split("");
1014
- newHexValue = val[0] + val[0] + val[1] + val[1] + val[2] + val[2];
1015
- }
1016
- newHexValue = "#" + newHexValue;
1017
- if (activeField == hexVal.name) {
1018
- lastVal = hexVal.text;
1019
- updateValues(Color3.FromHexString(newHexValue), hexVal.name);
350
+ if (!this.isReadOnly) {
351
+ // Invert transform
352
+ this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
353
+ const x = this._transformedPosition.x;
354
+ const y = this._transformedPosition.y;
355
+ if (this._pointerIsDown) {
356
+ this._updateValueFromPointer(x, y);
1020
357
  }
1021
358
  }
1022
- });
1023
- hexValueQuadrant.addControl(hexVal, 0, 1);
1024
- if (options.savedColors && options.savedColors.length > 0) {
1025
- updateSwatches("", butSave);
359
+ super._onPointerMove(target, coordinates, pointerId, pi);
360
+ }
361
+ _onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick, pi) {
362
+ this._pointerIsDown = false;
363
+ delete this._host._capturingControl[pointerId];
364
+ super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick, pi);
365
+ }
366
+ _onCanvasBlur() {
367
+ this._forcePointerUp();
368
+ super._onCanvasBlur();
1026
369
  }
1027
370
  /**
1028
- * Will update all values for InputText and ColorPicker controls based on the BABYLON.Color3 passed to this function.
1029
- * Each InputText control and the ColorPicker control will be tested to see if they are the activeField and if they
1030
- * are will receive no update. This is to prevent the input from the user being overwritten.
1031
- * @param value
1032
- * @param inputField
371
+ * This function expands the color picker by creating a color picker dialog with manual
372
+ * color value input and the ability to save colors into an array to be used later in
373
+ * subsequent launches of the dialogue.
374
+ * @param advancedTexture defines the AdvancedDynamicTexture the dialog is assigned to
375
+ * @param options defines size for dialog and options for saved colors. Also accepts last color picked as hex string and saved colors array as hex strings.
376
+ * @param options.pickerWidth
377
+ * @param options.pickerHeight
378
+ * @param options.headerHeight
379
+ * @param options.lastColor
380
+ * @param options.swatchLimit
381
+ * @param options.numSwatchesPerLine
382
+ * @param options.savedColors
383
+ * @returns picked color as a hex string and the saved colors array as hex strings.
1033
384
  */
1034
- function updateValues(value, inputField) {
1035
- activeField = inputField;
1036
- const pickedColor = value.toHexString();
1037
- newSwatch.background = pickedColor;
1038
- if (rValInt.name != activeField) {
1039
- rValInt.text = Math.floor(value.r * 255).toString();
1040
- }
1041
- if (gValInt.name != activeField) {
1042
- gValInt.text = Math.floor(value.g * 255).toString();
1043
- }
1044
- if (bValInt.name != activeField) {
1045
- bValInt.text = Math.floor(value.b * 255).toString();
1046
- }
1047
- if (rValDec.name != activeField) {
1048
- rValDec.text = value.r.toString();
1049
- }
1050
- if (gValDec.name != activeField) {
1051
- gValDec.text = value.g.toString();
1052
- }
1053
- if (bValDec.name != activeField) {
1054
- bValDec.text = value.b.toString();
1055
- }
1056
- if (hexVal.name != activeField) {
1057
- const minusPound = pickedColor.split("#");
1058
- hexVal.text = minusPound[1];
1059
- }
1060
- if (picker.name != activeField) {
1061
- picker.value = value;
1062
- }
1063
- }
1064
- // When the user enters an integer for R, G, or B we check to make sure it is a valid number and replace if not.
1065
- function updateInt(field, channel) {
1066
- let newValue = field.text;
1067
- const checkVal = /[^0-9]/g.test(newValue);
1068
- if (checkVal) {
1069
- field.text = lastVal;
1070
- return;
1071
- }
1072
- else {
1073
- if (newValue != "") {
1074
- if (Math.floor(parseInt(newValue)) < 0) {
1075
- newValue = "0";
1076
- }
1077
- else if (Math.floor(parseInt(newValue)) > 255) {
1078
- newValue = "255";
1079
- }
1080
- else if (isNaN(parseInt(newValue))) {
1081
- newValue = "0";
1082
- }
385
+ static async ShowPickerDialogAsync(advancedTexture, options) {
386
+ return await new Promise((resolve) => {
387
+ // Default options
388
+ options.pickerWidth = options.pickerWidth || "640px";
389
+ options.pickerHeight = options.pickerHeight || "400px";
390
+ options.headerHeight = options.headerHeight || "35px";
391
+ options.lastColor = options.lastColor || "#000000";
392
+ options.swatchLimit = options.swatchLimit || 20;
393
+ options.numSwatchesPerLine = options.numSwatchesPerLine || 10;
394
+ // Window size settings
395
+ const drawerMaxRows = options.swatchLimit / options.numSwatchesPerLine;
396
+ const rawSwatchSize = parseFloat(options.pickerWidth) / options.numSwatchesPerLine;
397
+ const gutterSize = Math.floor(rawSwatchSize * 0.25);
398
+ const colGutters = gutterSize * (options.numSwatchesPerLine + 1);
399
+ const swatchSize = Math.floor((parseFloat(options.pickerWidth) - colGutters) / options.numSwatchesPerLine);
400
+ const drawerMaxSize = swatchSize * drawerMaxRows + gutterSize * (drawerMaxRows + 1);
401
+ const containerSize = (parseInt(options.pickerHeight) + drawerMaxSize + Math.floor(swatchSize * 0.25)).toString() + "px";
402
+ // Button Colors
403
+ const buttonColor = "#c0c0c0";
404
+ const buttonBackgroundColor = "#535353";
405
+ const buttonBackgroundHoverColor = "#414141";
406
+ const buttonBackgroundClickColor = "515151";
407
+ const buttonDisabledColor = "#555555";
408
+ const buttonDisabledBackgroundColor = "#454545";
409
+ const currentSwatchesOutlineColor = "#404040";
410
+ const luminanceLimitColor = Color3.FromHexString("#dddddd");
411
+ const luminanceLimit = luminanceLimitColor.r + luminanceLimitColor.g + luminanceLimitColor.b;
412
+ const iconColorDark = "#aaaaaa";
413
+ const iconColorLight = "#ffffff";
414
+ // Button settings
415
+ let buttonFontSize;
416
+ let butEdit;
417
+ // Input Text Colors
418
+ const inputFieldLabels = ["R", "G", "B"];
419
+ const inputTextBackgroundColor = "#454545";
420
+ const inputTextColor = "#f0f0f0";
421
+ // This int is used for naming swatches and serves as the index for calling them from the list
422
+ let swatchNumber;
423
+ // Menu Panel options. We need to know if the swatchDrawer exists so we can create it if needed.
424
+ let swatchDrawer;
425
+ let editSwatchMode = false;
426
+ // Color InputText fields that will be updated upon value change
427
+ let butSave;
428
+ let lastVal;
429
+ let activeField;
430
+ // Dialog menu container which will contain both the main dialogue window and the swatch drawer which opens once a color is saved.
431
+ const dialogContainer = new Grid();
432
+ dialogContainer.name = "Dialog Container";
433
+ dialogContainer.width = options.pickerWidth;
434
+ if (options.savedColors) {
435
+ dialogContainer.height = containerSize;
436
+ const topRow = parseInt(options.pickerHeight) / parseInt(containerSize);
437
+ dialogContainer.addRowDefinition(topRow, false);
438
+ dialogContainer.addRowDefinition(1.0 - topRow, false);
1083
439
  }
1084
- if (activeField == field.name) {
1085
- lastVal = newValue;
440
+ else {
441
+ dialogContainer.height = options.pickerHeight;
442
+ dialogContainer.addRowDefinition(1.0, false);
1086
443
  }
1087
- }
1088
- if (newValue != "") {
1089
- newValue = parseInt(newValue).toString();
1090
- field.text = newValue;
1091
- const newSwatchRGB = Color3.FromHexString(newSwatch.background);
1092
- if (activeField == field.name) {
1093
- if (channel == "r") {
1094
- updateValues(new Color3(parseInt(newValue) / 255, newSwatchRGB.g, newSwatchRGB.b), field.name);
1095
- }
1096
- else if (channel == "g") {
1097
- updateValues(new Color3(newSwatchRGB.r, parseInt(newValue) / 255, newSwatchRGB.b), field.name);
444
+ advancedTexture.addControl(dialogContainer);
445
+ // Swatch drawer which contains all saved color buttons
446
+ if (options.savedColors) {
447
+ swatchDrawer = new Grid();
448
+ swatchDrawer.name = "Swatch Drawer";
449
+ swatchDrawer.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
450
+ swatchDrawer.background = buttonBackgroundColor;
451
+ swatchDrawer.width = options.pickerWidth;
452
+ const initialRows = options.savedColors.length / options.numSwatchesPerLine;
453
+ let gutterCount;
454
+ if (initialRows == 0) {
455
+ gutterCount = 0;
1098
456
  }
1099
457
  else {
1100
- updateValues(new Color3(newSwatchRGB.r, newSwatchRGB.g, parseInt(newValue) / 255), field.name);
1101
- }
1102
- }
1103
- }
1104
- }
1105
- // When the user enters a float for R, G, or B we check to make sure it is a valid number and replace if not.
1106
- function updateFloat(field, channel) {
1107
- let newValue = field.text;
1108
- const checkVal = /[^0-9.]/g.test(newValue);
1109
- if (checkVal) {
1110
- field.text = lastVal;
1111
- return;
1112
- }
1113
- else {
1114
- if (newValue != "" && newValue != "." && parseFloat(newValue) != 0) {
1115
- if (parseFloat(newValue) < 0.0) {
1116
- newValue = "0.0";
458
+ gutterCount = initialRows + 1;
1117
459
  }
1118
- else if (parseFloat(newValue) > 1.0) {
1119
- newValue = "1.0";
460
+ swatchDrawer.height = (swatchSize * initialRows + gutterCount * gutterSize).toString() + "px";
461
+ swatchDrawer.top = Math.floor(swatchSize * 0.25).toString() + "px";
462
+ for (let i = 0; i < Math.ceil(options.savedColors.length / options.numSwatchesPerLine) * 2 + 1; i++) {
463
+ if (i % 2 != 0) {
464
+ swatchDrawer.addRowDefinition(swatchSize, true);
465
+ }
466
+ else {
467
+ swatchDrawer.addRowDefinition(gutterSize, true);
468
+ }
1120
469
  }
1121
- else if (isNaN(parseFloat(newValue))) {
1122
- newValue = "0.0";
470
+ for (let i = 0; i < options.numSwatchesPerLine * 2 + 1; i++) {
471
+ if (i % 2 != 0) {
472
+ swatchDrawer.addColumnDefinition(swatchSize, true);
473
+ }
474
+ else {
475
+ swatchDrawer.addColumnDefinition(gutterSize, true);
476
+ }
1123
477
  }
478
+ dialogContainer.addControl(swatchDrawer, 1, 0);
1124
479
  }
1125
- if (activeField == field.name) {
1126
- lastVal = newValue;
1127
- }
1128
- }
1129
- if (newValue != "" && newValue != "." && parseFloat(newValue) != 0) {
1130
- newValue = parseFloat(newValue).toString();
1131
- field.text = newValue;
1132
- }
1133
- else {
1134
- newValue = "0.0";
1135
- }
1136
- const newSwatchRGB = Color3.FromHexString(newSwatch.background);
1137
- if (activeField == field.name) {
1138
- if (channel == "r") {
1139
- updateValues(new Color3(parseFloat(newValue), newSwatchRGB.g, newSwatchRGB.b), field.name);
1140
- }
1141
- else if (channel == "g") {
1142
- updateValues(new Color3(newSwatchRGB.r, parseFloat(newValue), newSwatchRGB.b), field.name);
480
+ // Picker container
481
+ const pickerPanel = new Grid();
482
+ pickerPanel.name = "Picker Panel";
483
+ pickerPanel.height = options.pickerHeight;
484
+ const panelHead = parseInt(options.headerHeight) / parseInt(options.pickerHeight);
485
+ const pickerPanelRows = [panelHead, 1.0 - panelHead];
486
+ pickerPanel.addRowDefinition(pickerPanelRows[0], false);
487
+ pickerPanel.addRowDefinition(pickerPanelRows[1], false);
488
+ dialogContainer.addControl(pickerPanel, 0, 0);
489
+ // Picker container header
490
+ const header = new Rectangle();
491
+ header.name = "Dialogue Header Bar";
492
+ header.background = "#cccccc";
493
+ header.thickness = 0;
494
+ pickerPanel.addControl(header, 0, 0);
495
+ // Header close button
496
+ const closeButton = Button.CreateSimpleButton("closeButton", "a");
497
+ closeButton.fontFamily = "coreglyphs";
498
+ const headerColor3 = Color3.FromHexString(header.background);
499
+ const closeIconColor = new Color3(1.0 - headerColor3.r, 1.0 - headerColor3.g, 1.0 - headerColor3.b);
500
+ closeButton.color = closeIconColor.toHexString();
501
+ closeButton.fontSize = Math.floor(parseInt(options.headerHeight) * 0.6);
502
+ closeButton.textBlock.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
503
+ closeButton.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
504
+ closeButton.height = closeButton.width = options.headerHeight;
505
+ closeButton.background = header.background;
506
+ closeButton.thickness = 0;
507
+ closeButton.pointerDownAnimation = () => { };
508
+ closeButton.pointerUpAnimation = () => {
509
+ closeButton.background = header.background;
510
+ };
511
+ closeButton.pointerEnterAnimation = () => {
512
+ closeButton.color = header.background;
513
+ closeButton.background = "red";
514
+ };
515
+ closeButton.pointerOutAnimation = () => {
516
+ closeButton.color = closeIconColor.toHexString();
517
+ closeButton.background = header.background;
518
+ };
519
+ closeButton.onPointerClickObservable.add(() => {
520
+ closePicker(currentSwatch.background);
521
+ });
522
+ pickerPanel.addControl(closeButton, 0, 0);
523
+ // Dialog container body
524
+ const dialogBody = new Grid();
525
+ dialogBody.name = "Dialogue Body";
526
+ dialogBody.background = buttonBackgroundColor;
527
+ const dialogBodyCols = [0.4375, 0.5625];
528
+ dialogBody.addRowDefinition(1.0, false);
529
+ dialogBody.addColumnDefinition(dialogBodyCols[0], false);
530
+ dialogBody.addColumnDefinition(dialogBodyCols[1], false);
531
+ pickerPanel.addControl(dialogBody, 1, 0);
532
+ // Picker grid
533
+ const pickerGrid = new Grid();
534
+ pickerGrid.name = "Picker Grid";
535
+ pickerGrid.addRowDefinition(0.85, false);
536
+ pickerGrid.addRowDefinition(0.15, false);
537
+ dialogBody.addControl(pickerGrid, 0, 0);
538
+ // Picker control
539
+ const picker = new _a();
540
+ picker.name = "GUI Color Picker";
541
+ if (options.pickerHeight < options.pickerWidth) {
542
+ picker.width = 0.89;
1143
543
  }
1144
544
  else {
1145
- updateValues(new Color3(newSwatchRGB.r, newSwatchRGB.g, parseFloat(newValue)), field.name);
545
+ picker.height = 0.89;
1146
546
  }
1147
- }
1148
- }
1149
- // Removes the current index from the savedColors array. Drawer can then be regenerated.
1150
- function deleteSwatch(index) {
1151
- if (options.savedColors) {
1152
- options.savedColors.splice(index, 1);
1153
- }
1154
- if (options.savedColors && options.savedColors.length == 0) {
1155
- setEditButtonVisibility(false);
1156
- editSwatchMode = false;
1157
- }
1158
- }
1159
- // Creates and styles an individual swatch when updateSwatches is called.
1160
- function createSwatch() {
1161
- if (options.savedColors && options.savedColors[swatchNumber]) {
1162
- let icon;
1163
- if (editSwatchMode) {
1164
- icon = "b";
547
+ picker.value = Color3.FromHexString(options.lastColor);
548
+ picker.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
549
+ picker.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
550
+ picker.onPointerDownObservable.add(() => {
551
+ activeField = picker.name;
552
+ lastVal = "";
553
+ editSwatches(false);
554
+ });
555
+ picker.onValueChangedObservable.add(function (value) {
556
+ // value is a color3
557
+ if (activeField == picker.name) {
558
+ updateValues(value, picker.name);
559
+ }
560
+ });
561
+ pickerGrid.addControl(picker, 0, 0);
562
+ // Picker body right quarant
563
+ const pickerBodyRight = new Grid();
564
+ pickerBodyRight.name = "Dialogue Right Half";
565
+ pickerBodyRight.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
566
+ const pickerBodyRightRows = [0.514, 0.486];
567
+ pickerBodyRight.addRowDefinition(pickerBodyRightRows[0], false);
568
+ pickerBodyRight.addRowDefinition(pickerBodyRightRows[1], false);
569
+ dialogBody.addControl(pickerBodyRight, 1, 1);
570
+ // Picker container swatches and buttons
571
+ const pickerSwatchesButtons = new Grid();
572
+ pickerSwatchesButtons.name = "Swatches and Buttons";
573
+ const pickerButtonsCol = [0.417, 0.583];
574
+ pickerSwatchesButtons.addRowDefinition(1.0, false);
575
+ pickerSwatchesButtons.addColumnDefinition(pickerButtonsCol[0], false);
576
+ pickerSwatchesButtons.addColumnDefinition(pickerButtonsCol[1], false);
577
+ pickerBodyRight.addControl(pickerSwatchesButtons, 0, 0);
578
+ // Picker Swatches quadrant
579
+ const pickerSwatches = new Grid();
580
+ pickerSwatches.name = "New and Current Swatches";
581
+ const pickeSwatchesRows = [0.04, 0.16, 0.64, 0.16];
582
+ pickerSwatches.addRowDefinition(pickeSwatchesRows[0], false);
583
+ pickerSwatches.addRowDefinition(pickeSwatchesRows[1], false);
584
+ pickerSwatches.addRowDefinition(pickeSwatchesRows[2], false);
585
+ pickerSwatches.addRowDefinition(pickeSwatchesRows[3], false);
586
+ pickerSwatchesButtons.addControl(pickerSwatches, 0, 0);
587
+ // Active swatches
588
+ const activeSwatches = new Grid();
589
+ activeSwatches.name = "Active Swatches";
590
+ activeSwatches.width = 0.67;
591
+ activeSwatches.addRowDefinition(0.5, false);
592
+ activeSwatches.addRowDefinition(0.5, false);
593
+ pickerSwatches.addControl(activeSwatches, 2, 0);
594
+ const labelWidth = Math.floor(parseInt(options.pickerWidth) * dialogBodyCols[1] * pickerButtonsCol[0] * 0.11);
595
+ const labelHeight = Math.floor(parseInt(options.pickerHeight) * pickerPanelRows[1] * pickerBodyRightRows[0] * pickeSwatchesRows[1] * 0.5);
596
+ let labelTextSize;
597
+ if (options.pickerWidth > options.pickerHeight) {
598
+ labelTextSize = labelHeight;
1165
599
  }
1166
600
  else {
1167
- icon = "";
601
+ labelTextSize = labelWidth;
1168
602
  }
1169
- const swatch = Button.CreateSimpleButton("Swatch_" + swatchNumber, icon);
1170
- swatch.fontFamily = "coreglyphs";
1171
- const swatchColor = Color3.FromHexString(options.savedColors[swatchNumber]);
1172
- const swatchLuminence = swatchColor.r + swatchColor.g + swatchColor.b;
1173
- // Set color of outline and textBlock based on luminance of the color swatch so feedback always visible
1174
- if (swatchLuminence > luminanceLimit) {
1175
- swatch.color = iconColorDark;
603
+ // New color swatch and previous color button
604
+ const newText = new TextBlock();
605
+ newText.text = "new";
606
+ newText.name = "New Color Label";
607
+ newText.color = buttonColor;
608
+ newText.fontSize = labelTextSize;
609
+ pickerSwatches.addControl(newText, 1, 0);
610
+ const newSwatch = new Rectangle();
611
+ newSwatch.name = "New Color Swatch";
612
+ newSwatch.background = options.lastColor;
613
+ newSwatch.thickness = 0;
614
+ activeSwatches.addControl(newSwatch, 0, 0);
615
+ const currentSwatch = Button.CreateSimpleButton("currentSwatch", "");
616
+ currentSwatch.background = options.lastColor;
617
+ currentSwatch.thickness = 0;
618
+ currentSwatch.onPointerClickObservable.add(() => {
619
+ const revertColor = Color3.FromHexString(currentSwatch.background);
620
+ updateValues(revertColor, currentSwatch.name);
621
+ editSwatches(false);
622
+ });
623
+ currentSwatch.pointerDownAnimation = () => { };
624
+ currentSwatch.pointerUpAnimation = () => { };
625
+ currentSwatch.pointerEnterAnimation = () => { };
626
+ currentSwatch.pointerOutAnimation = () => { };
627
+ activeSwatches.addControl(currentSwatch, 1, 0);
628
+ const swatchOutline = new Rectangle();
629
+ swatchOutline.name = "Swatch Outline";
630
+ swatchOutline.width = 0.67;
631
+ swatchOutline.thickness = 2;
632
+ swatchOutline.color = currentSwatchesOutlineColor;
633
+ swatchOutline.isHitTestVisible = false;
634
+ pickerSwatches.addControl(swatchOutline, 2, 0);
635
+ const currentText = new TextBlock();
636
+ currentText.name = "Current Color Label";
637
+ currentText.text = "current";
638
+ currentText.color = buttonColor;
639
+ currentText.fontSize = labelTextSize;
640
+ pickerSwatches.addControl(currentText, 3, 0);
641
+ // Buttons grid
642
+ const buttonGrid = new Grid();
643
+ buttonGrid.name = "Button Grid";
644
+ buttonGrid.height = 0.8;
645
+ const buttonGridRows = 1 / 3;
646
+ buttonGrid.addRowDefinition(buttonGridRows, false);
647
+ buttonGrid.addRowDefinition(buttonGridRows, false);
648
+ buttonGrid.addRowDefinition(buttonGridRows, false);
649
+ pickerSwatchesButtons.addControl(buttonGrid, 0, 1);
650
+ // Determine pixel width and height for all buttons from overall panel dimensions
651
+ const buttonWidth = Math.floor(parseInt(options.pickerWidth) * dialogBodyCols[1] * pickerButtonsCol[1] * 0.67).toString() + "px";
652
+ const buttonHeight = Math.floor(parseInt(options.pickerHeight) * pickerPanelRows[1] * pickerBodyRightRows[0] * (parseFloat(buttonGrid.height.toString()) / 100) * buttonGridRows * 0.7).toString() + "px";
653
+ // Determine button type size
654
+ if (parseFloat(buttonWidth) > parseFloat(buttonHeight)) {
655
+ buttonFontSize = Math.floor(parseFloat(buttonHeight) * 0.45);
1176
656
  }
1177
657
  else {
1178
- swatch.color = iconColorLight;
658
+ buttonFontSize = Math.floor(parseFloat(buttonWidth) * 0.11);
1179
659
  }
1180
- swatch.fontSize = Math.floor(swatchSize * 0.7);
1181
- swatch.textBlock.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
1182
- swatch.height = swatch.width = swatchSize.toString() + "px";
1183
- swatch.background = options.savedColors[swatchNumber];
1184
- swatch.thickness = 2;
1185
- const metadata = swatchNumber;
1186
- swatch.pointerDownAnimation = () => {
1187
- swatch.thickness = 4;
660
+ // Panel Buttons
661
+ const butOK = Button.CreateSimpleButton("butOK", "OK");
662
+ butOK.width = buttonWidth;
663
+ butOK.height = buttonHeight;
664
+ butOK.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
665
+ butOK.thickness = 2;
666
+ butOK.color = buttonColor;
667
+ butOK.fontSize = buttonFontSize;
668
+ butOK.background = buttonBackgroundColor;
669
+ butOK.onPointerEnterObservable.add(() => {
670
+ butOK.background = buttonBackgroundHoverColor;
671
+ });
672
+ butOK.onPointerOutObservable.add(() => {
673
+ butOK.background = buttonBackgroundColor;
674
+ });
675
+ butOK.pointerDownAnimation = () => {
676
+ butOK.background = buttonBackgroundClickColor;
1188
677
  };
1189
- swatch.pointerUpAnimation = () => {
1190
- swatch.thickness = 3;
678
+ butOK.pointerUpAnimation = () => {
679
+ butOK.background = buttonBackgroundHoverColor;
1191
680
  };
1192
- swatch.pointerEnterAnimation = () => {
1193
- swatch.thickness = 3;
681
+ butOK.onPointerClickObservable.add(() => {
682
+ editSwatches(false);
683
+ closePicker(newSwatch.background);
684
+ });
685
+ buttonGrid.addControl(butOK, 0, 0);
686
+ const butCancel = Button.CreateSimpleButton("butCancel", "Cancel");
687
+ butCancel.width = buttonWidth;
688
+ butCancel.height = buttonHeight;
689
+ butCancel.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
690
+ butCancel.thickness = 2;
691
+ butCancel.color = buttonColor;
692
+ butCancel.fontSize = buttonFontSize;
693
+ butCancel.background = buttonBackgroundColor;
694
+ butCancel.onPointerEnterObservable.add(() => {
695
+ butCancel.background = buttonBackgroundHoverColor;
696
+ });
697
+ butCancel.onPointerOutObservable.add(() => {
698
+ butCancel.background = buttonBackgroundColor;
699
+ });
700
+ butCancel.pointerDownAnimation = () => {
701
+ butCancel.background = buttonBackgroundClickColor;
1194
702
  };
1195
- swatch.pointerOutAnimation = () => {
1196
- swatch.thickness = 2;
703
+ butCancel.pointerUpAnimation = () => {
704
+ butCancel.background = buttonBackgroundHoverColor;
1197
705
  };
1198
- swatch.onPointerClickObservable.add(() => {
1199
- if (!editSwatchMode) {
706
+ butCancel.onPointerClickObservable.add(() => {
707
+ editSwatches(false);
708
+ closePicker(currentSwatch.background);
709
+ });
710
+ buttonGrid.addControl(butCancel, 1, 0);
711
+ if (options.savedColors) {
712
+ butSave = Button.CreateSimpleButton("butSave", "Save");
713
+ butSave.width = buttonWidth;
714
+ butSave.height = buttonHeight;
715
+ butSave.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
716
+ butSave.thickness = 2;
717
+ butSave.fontSize = buttonFontSize;
718
+ if (options.savedColors.length < options.swatchLimit) {
719
+ butSave.color = buttonColor;
720
+ butSave.background = buttonBackgroundColor;
721
+ }
722
+ else {
723
+ disableButton(butSave, true);
724
+ }
725
+ butSave.onPointerEnterObservable.add(() => {
1200
726
  if (options.savedColors) {
1201
- updateValues(Color3.FromHexString(options.savedColors[metadata]), swatch.name);
727
+ if (options.savedColors.length < options.swatchLimit) {
728
+ butSave.background = buttonBackgroundHoverColor;
729
+ }
1202
730
  }
731
+ });
732
+ butSave.onPointerOutObservable.add(() => {
733
+ if (options.savedColors) {
734
+ if (options.savedColors.length < options.swatchLimit) {
735
+ butSave.background = buttonBackgroundColor;
736
+ }
737
+ }
738
+ });
739
+ butSave.pointerDownAnimation = () => {
740
+ if (options.savedColors) {
741
+ if (options.savedColors.length < options.swatchLimit) {
742
+ butSave.background = buttonBackgroundClickColor;
743
+ }
744
+ }
745
+ };
746
+ butSave.pointerUpAnimation = () => {
747
+ if (options.savedColors) {
748
+ if (options.savedColors.length < options.swatchLimit) {
749
+ butSave.background = buttonBackgroundHoverColor;
750
+ }
751
+ }
752
+ };
753
+ butSave.onPointerClickObservable.add(() => {
754
+ if (options.savedColors) {
755
+ if (options.savedColors.length == 0) {
756
+ setEditButtonVisibility(true);
757
+ }
758
+ if (options.savedColors.length < options.swatchLimit) {
759
+ updateSwatches(newSwatch.background, butSave);
760
+ }
761
+ editSwatches(false);
762
+ }
763
+ });
764
+ if (options.savedColors.length > 0) {
765
+ setEditButtonVisibility(true);
766
+ }
767
+ buttonGrid.addControl(butSave, 2, 0);
768
+ }
769
+ // Picker color values input
770
+ const pickerColorValues = new Grid();
771
+ pickerColorValues.name = "Dialog Lower Right";
772
+ pickerColorValues.addRowDefinition(0.02, false);
773
+ pickerColorValues.addRowDefinition(0.63, false);
774
+ pickerColorValues.addRowDefinition(0.21, false);
775
+ pickerColorValues.addRowDefinition(0.14, false);
776
+ pickerBodyRight.addControl(pickerColorValues, 1, 0);
777
+ // RGB values text boxes
778
+ const currentColor = Color3.FromHexString(options.lastColor);
779
+ const rgbValuesQuadrant = new Grid();
780
+ rgbValuesQuadrant.name = "RGB Values";
781
+ rgbValuesQuadrant.width = 0.82;
782
+ rgbValuesQuadrant.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
783
+ rgbValuesQuadrant.addRowDefinition(1 / 3, false);
784
+ rgbValuesQuadrant.addRowDefinition(1 / 3, false);
785
+ rgbValuesQuadrant.addRowDefinition(1 / 3, false);
786
+ rgbValuesQuadrant.addColumnDefinition(0.1, false);
787
+ rgbValuesQuadrant.addColumnDefinition(0.2, false);
788
+ rgbValuesQuadrant.addColumnDefinition(0.7, false);
789
+ pickerColorValues.addControl(rgbValuesQuadrant, 1, 0);
790
+ for (let i = 0; i < inputFieldLabels.length; i++) {
791
+ const labelText = new TextBlock();
792
+ labelText.text = inputFieldLabels[i];
793
+ labelText.color = buttonColor;
794
+ labelText.fontSize = buttonFontSize;
795
+ rgbValuesQuadrant.addControl(labelText, i, 0);
796
+ }
797
+ // Input fields for RGB values
798
+ const rValInt = new InputText();
799
+ rValInt.width = 0.83;
800
+ rValInt.height = 0.72;
801
+ rValInt.name = "rIntField";
802
+ rValInt.fontSize = buttonFontSize;
803
+ rValInt.text = (currentColor.r * 255).toString();
804
+ rValInt.color = inputTextColor;
805
+ rValInt.background = inputTextBackgroundColor;
806
+ rValInt.onFocusObservable.add(() => {
807
+ activeField = rValInt.name;
808
+ lastVal = rValInt.text;
809
+ editSwatches(false);
810
+ });
811
+ rValInt.onBlurObservable.add(() => {
812
+ if (rValInt.text == "") {
813
+ rValInt.text = "0";
814
+ }
815
+ updateInt(rValInt, "r");
816
+ if (activeField == rValInt.name) {
817
+ activeField = "";
818
+ }
819
+ });
820
+ rValInt.onTextChangedObservable.add(() => {
821
+ if (activeField == rValInt.name) {
822
+ updateInt(rValInt, "r");
823
+ }
824
+ });
825
+ rgbValuesQuadrant.addControl(rValInt, 0, 1);
826
+ const gValInt = new InputText();
827
+ gValInt.width = 0.83;
828
+ gValInt.height = 0.72;
829
+ gValInt.name = "gIntField";
830
+ gValInt.fontSize = buttonFontSize;
831
+ gValInt.text = (currentColor.g * 255).toString();
832
+ gValInt.color = inputTextColor;
833
+ gValInt.background = inputTextBackgroundColor;
834
+ gValInt.onFocusObservable.add(() => {
835
+ activeField = gValInt.name;
836
+ lastVal = gValInt.text;
837
+ editSwatches(false);
838
+ });
839
+ gValInt.onBlurObservable.add(() => {
840
+ if (gValInt.text == "") {
841
+ gValInt.text = "0";
842
+ }
843
+ updateInt(gValInt, "g");
844
+ if (activeField == gValInt.name) {
845
+ activeField = "";
846
+ }
847
+ });
848
+ gValInt.onTextChangedObservable.add(() => {
849
+ if (activeField == gValInt.name) {
850
+ updateInt(gValInt, "g");
851
+ }
852
+ });
853
+ rgbValuesQuadrant.addControl(gValInt, 1, 1);
854
+ const bValInt = new InputText();
855
+ bValInt.width = 0.83;
856
+ bValInt.height = 0.72;
857
+ bValInt.name = "bIntField";
858
+ bValInt.fontSize = buttonFontSize;
859
+ bValInt.text = (currentColor.b * 255).toString();
860
+ bValInt.color = inputTextColor;
861
+ bValInt.background = inputTextBackgroundColor;
862
+ bValInt.onFocusObservable.add(() => {
863
+ activeField = bValInt.name;
864
+ lastVal = bValInt.text;
865
+ editSwatches(false);
866
+ });
867
+ bValInt.onBlurObservable.add(() => {
868
+ if (bValInt.text == "") {
869
+ bValInt.text = "0";
870
+ }
871
+ updateInt(bValInt, "b");
872
+ if (activeField == bValInt.name) {
873
+ activeField = "";
874
+ }
875
+ });
876
+ bValInt.onTextChangedObservable.add(() => {
877
+ if (activeField == bValInt.name) {
878
+ updateInt(bValInt, "b");
879
+ }
880
+ });
881
+ rgbValuesQuadrant.addControl(bValInt, 2, 1);
882
+ const rValDec = new InputText();
883
+ rValDec.width = 0.95;
884
+ rValDec.height = 0.72;
885
+ rValDec.name = "rDecField";
886
+ rValDec.fontSize = buttonFontSize;
887
+ rValDec.text = currentColor.r.toString();
888
+ rValDec.color = inputTextColor;
889
+ rValDec.background = inputTextBackgroundColor;
890
+ rValDec.onFocusObservable.add(() => {
891
+ activeField = rValDec.name;
892
+ lastVal = rValDec.text;
893
+ editSwatches(false);
894
+ });
895
+ rValDec.onBlurObservable.add(() => {
896
+ if (parseFloat(rValDec.text) == 0 || rValDec.text == "") {
897
+ rValDec.text = "0";
898
+ updateFloat(rValDec, "r");
899
+ }
900
+ if (activeField == rValDec.name) {
901
+ activeField = "";
902
+ }
903
+ });
904
+ rValDec.onTextChangedObservable.add(() => {
905
+ if (activeField == rValDec.name) {
906
+ updateFloat(rValDec, "r");
907
+ }
908
+ });
909
+ rgbValuesQuadrant.addControl(rValDec, 0, 2);
910
+ const gValDec = new InputText();
911
+ gValDec.width = 0.95;
912
+ gValDec.height = 0.72;
913
+ gValDec.name = "gDecField";
914
+ gValDec.fontSize = buttonFontSize;
915
+ gValDec.text = currentColor.g.toString();
916
+ gValDec.color = inputTextColor;
917
+ gValDec.background = inputTextBackgroundColor;
918
+ gValDec.onFocusObservable.add(() => {
919
+ activeField = gValDec.name;
920
+ lastVal = gValDec.text;
921
+ editSwatches(false);
922
+ });
923
+ gValDec.onBlurObservable.add(() => {
924
+ if (parseFloat(gValDec.text) == 0 || gValDec.text == "") {
925
+ gValDec.text = "0";
926
+ updateFloat(gValDec, "g");
927
+ }
928
+ if (activeField == gValDec.name) {
929
+ activeField = "";
930
+ }
931
+ });
932
+ gValDec.onTextChangedObservable.add(() => {
933
+ if (activeField == gValDec.name) {
934
+ updateFloat(gValDec, "g");
935
+ }
936
+ });
937
+ rgbValuesQuadrant.addControl(gValDec, 1, 2);
938
+ const bValDec = new InputText();
939
+ bValDec.width = 0.95;
940
+ bValDec.height = 0.72;
941
+ bValDec.name = "bDecField";
942
+ bValDec.fontSize = buttonFontSize;
943
+ bValDec.text = currentColor.b.toString();
944
+ bValDec.color = inputTextColor;
945
+ bValDec.background = inputTextBackgroundColor;
946
+ bValDec.onFocusObservable.add(() => {
947
+ activeField = bValDec.name;
948
+ lastVal = bValDec.text;
949
+ editSwatches(false);
950
+ });
951
+ bValDec.onBlurObservable.add(() => {
952
+ if (parseFloat(bValDec.text) == 0 || bValDec.text == "") {
953
+ bValDec.text = "0";
954
+ updateFloat(bValDec, "b");
955
+ }
956
+ if (activeField == bValDec.name) {
957
+ activeField = "";
958
+ }
959
+ });
960
+ bValDec.onTextChangedObservable.add(() => {
961
+ if (activeField == bValDec.name) {
962
+ updateFloat(bValDec, "b");
963
+ }
964
+ });
965
+ rgbValuesQuadrant.addControl(bValDec, 2, 2);
966
+ // Hex value input
967
+ const hexValueQuadrant = new Grid();
968
+ hexValueQuadrant.name = "Hex Value";
969
+ hexValueQuadrant.width = 0.82;
970
+ hexValueQuadrant.addRowDefinition(1.0, false);
971
+ hexValueQuadrant.addColumnDefinition(0.1, false);
972
+ hexValueQuadrant.addColumnDefinition(0.9, false);
973
+ pickerColorValues.addControl(hexValueQuadrant, 2, 0);
974
+ const labelText = new TextBlock();
975
+ labelText.text = "#";
976
+ labelText.color = buttonColor;
977
+ labelText.fontSize = buttonFontSize;
978
+ hexValueQuadrant.addControl(labelText, 0, 0);
979
+ const hexVal = new InputText();
980
+ hexVal.width = 0.96;
981
+ hexVal.height = 0.72;
982
+ hexVal.name = "hexField";
983
+ hexVal.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
984
+ hexVal.fontSize = buttonFontSize;
985
+ const minusPound = options.lastColor.split("#");
986
+ hexVal.text = minusPound[1];
987
+ hexVal.color = inputTextColor;
988
+ hexVal.background = inputTextBackgroundColor;
989
+ hexVal.onFocusObservable.add(() => {
990
+ activeField = hexVal.name;
991
+ lastVal = hexVal.text;
992
+ editSwatches(false);
993
+ });
994
+ hexVal.onBlurObservable.add(() => {
995
+ if (hexVal.text.length == 3) {
996
+ const val = hexVal.text.split("");
997
+ hexVal.text = val[0] + val[0] + val[1] + val[1] + val[2] + val[2];
998
+ }
999
+ if (hexVal.text == "") {
1000
+ hexVal.text = "000000";
1001
+ updateValues(Color3.FromHexString(hexVal.text), "b");
1002
+ }
1003
+ if (activeField == hexVal.name) {
1004
+ activeField = "";
1005
+ }
1006
+ });
1007
+ hexVal.onTextChangedObservable.add(() => {
1008
+ let newHexValue = hexVal.text;
1009
+ const checkHex = /[^0-9A-F]/i.test(newHexValue);
1010
+ if ((hexVal.text.length > 6 || checkHex) && activeField == hexVal.name) {
1011
+ hexVal.text = lastVal;
1203
1012
  }
1204
1013
  else {
1205
- deleteSwatch(metadata);
1206
- updateSwatches("", butSave);
1014
+ if (hexVal.text.length < 6) {
1015
+ const leadingZero = 6 - hexVal.text.length;
1016
+ for (let i = 0; i < leadingZero; i++) {
1017
+ newHexValue = "0" + newHexValue;
1018
+ }
1019
+ }
1020
+ if (hexVal.text.length == 3) {
1021
+ const val = hexVal.text.split("");
1022
+ newHexValue = val[0] + val[0] + val[1] + val[1] + val[2] + val[2];
1023
+ }
1024
+ newHexValue = "#" + newHexValue;
1025
+ if (activeField == hexVal.name) {
1026
+ lastVal = hexVal.text;
1027
+ updateValues(Color3.FromHexString(newHexValue), hexVal.name);
1028
+ }
1207
1029
  }
1208
1030
  });
1209
- return swatch;
1210
- }
1211
- else {
1212
- return null;
1213
- }
1214
- }
1215
- // Mode switch to render button text and close symbols on swatch controls
1216
- function editSwatches(mode) {
1217
- if (mode !== undefined) {
1218
- editSwatchMode = mode;
1219
- }
1220
- let thisButton;
1221
- if (editSwatchMode) {
1222
- for (let i = 0; i < swatchDrawer.children.length; i++) {
1223
- thisButton = swatchDrawer.children[i];
1224
- thisButton.textBlock.text = "b";
1225
- }
1226
- if (butEdit !== undefined) {
1227
- butEdit.textBlock.text = "Done";
1031
+ hexValueQuadrant.addControl(hexVal, 0, 1);
1032
+ if (options.savedColors && options.savedColors.length > 0) {
1033
+ updateSwatches("", butSave);
1228
1034
  }
1229
- }
1230
- else {
1231
- for (let i = 0; i < swatchDrawer.children.length; i++) {
1232
- thisButton = swatchDrawer.children[i];
1233
- thisButton.textBlock.text = "";
1234
- }
1235
- if (butEdit !== undefined) {
1236
- butEdit.textBlock.text = "Edit";
1237
- }
1238
- }
1239
- }
1240
- /**
1241
- * When Save Color button is pressed this function will first create a swatch drawer if one is not already
1242
- * made. Then all controls are removed from the drawer and we step through the savedColors array and
1243
- * creates one swatch per color. It will also set the height of the drawer control based on how many
1244
- * saved colors there are and how many can be stored per row.
1245
- * @param color
1246
- * @param button
1247
- */
1248
- function updateSwatches(color, button) {
1249
- if (options.savedColors) {
1250
- if (color != "") {
1251
- options.savedColors.push(color);
1035
+ /**
1036
+ * Will update all values for InputText and ColorPicker controls based on the BABYLON.Color3 passed to this function.
1037
+ * Each InputText control and the ColorPicker control will be tested to see if they are the activeField and if they
1038
+ * are will receive no update. This is to prevent the input from the user being overwritten.
1039
+ * @param value
1040
+ * @param inputField
1041
+ */
1042
+ function updateValues(value, inputField) {
1043
+ activeField = inputField;
1044
+ const pickedColor = value.toHexString();
1045
+ newSwatch.background = pickedColor;
1046
+ if (rValInt.name != activeField) {
1047
+ rValInt.text = Math.floor(value.r * 255).toString();
1048
+ }
1049
+ if (gValInt.name != activeField) {
1050
+ gValInt.text = Math.floor(value.g * 255).toString();
1051
+ }
1052
+ if (bValInt.name != activeField) {
1053
+ bValInt.text = Math.floor(value.b * 255).toString();
1054
+ }
1055
+ if (rValDec.name != activeField) {
1056
+ rValDec.text = value.r.toString();
1057
+ }
1058
+ if (gValDec.name != activeField) {
1059
+ gValDec.text = value.g.toString();
1060
+ }
1061
+ if (bValDec.name != activeField) {
1062
+ bValDec.text = value.b.toString();
1063
+ }
1064
+ if (hexVal.name != activeField) {
1065
+ const minusPound = pickedColor.split("#");
1066
+ hexVal.text = minusPound[1];
1067
+ }
1068
+ if (picker.name != activeField) {
1069
+ picker.value = value;
1070
+ }
1252
1071
  }
1253
- swatchNumber = 0;
1254
- swatchDrawer.clearControls();
1255
- const rowCount = Math.ceil(options.savedColors.length / options.numSwatchesPerLine);
1256
- let gutterCount;
1257
- if (rowCount == 0) {
1258
- gutterCount = 0;
1072
+ // When the user enters an integer for R, G, or B we check to make sure it is a valid number and replace if not.
1073
+ function updateInt(field, channel) {
1074
+ let newValue = field.text;
1075
+ const checkVal = /[^0-9]/g.test(newValue);
1076
+ if (checkVal) {
1077
+ field.text = lastVal;
1078
+ return;
1079
+ }
1080
+ else {
1081
+ if (newValue != "") {
1082
+ if (Math.floor(parseInt(newValue)) < 0) {
1083
+ newValue = "0";
1084
+ }
1085
+ else if (Math.floor(parseInt(newValue)) > 255) {
1086
+ newValue = "255";
1087
+ }
1088
+ else if (isNaN(parseInt(newValue))) {
1089
+ newValue = "0";
1090
+ }
1091
+ }
1092
+ if (activeField == field.name) {
1093
+ lastVal = newValue;
1094
+ }
1095
+ }
1096
+ if (newValue != "") {
1097
+ newValue = parseInt(newValue).toString();
1098
+ field.text = newValue;
1099
+ const newSwatchRGB = Color3.FromHexString(newSwatch.background);
1100
+ if (activeField == field.name) {
1101
+ if (channel == "r") {
1102
+ updateValues(new Color3(parseInt(newValue) / 255, newSwatchRGB.g, newSwatchRGB.b), field.name);
1103
+ }
1104
+ else if (channel == "g") {
1105
+ updateValues(new Color3(newSwatchRGB.r, parseInt(newValue) / 255, newSwatchRGB.b), field.name);
1106
+ }
1107
+ else {
1108
+ updateValues(new Color3(newSwatchRGB.r, newSwatchRGB.g, parseInt(newValue) / 255), field.name);
1109
+ }
1110
+ }
1111
+ }
1259
1112
  }
1260
- else {
1261
- gutterCount = rowCount + 1;
1113
+ // When the user enters a float for R, G, or B we check to make sure it is a valid number and replace if not.
1114
+ function updateFloat(field, channel) {
1115
+ let newValue = field.text;
1116
+ const checkVal = /[^0-9.]/g.test(newValue);
1117
+ if (checkVal) {
1118
+ field.text = lastVal;
1119
+ return;
1120
+ }
1121
+ else {
1122
+ if (newValue != "" && newValue != "." && parseFloat(newValue) != 0) {
1123
+ if (parseFloat(newValue) < 0.0) {
1124
+ newValue = "0.0";
1125
+ }
1126
+ else if (parseFloat(newValue) > 1.0) {
1127
+ newValue = "1.0";
1128
+ }
1129
+ else if (isNaN(parseFloat(newValue))) {
1130
+ newValue = "0.0";
1131
+ }
1132
+ }
1133
+ if (activeField == field.name) {
1134
+ lastVal = newValue;
1135
+ }
1136
+ }
1137
+ if (newValue != "" && newValue != "." && parseFloat(newValue) != 0) {
1138
+ newValue = parseFloat(newValue).toString();
1139
+ field.text = newValue;
1140
+ }
1141
+ else {
1142
+ newValue = "0.0";
1143
+ }
1144
+ const newSwatchRGB = Color3.FromHexString(newSwatch.background);
1145
+ if (activeField == field.name) {
1146
+ if (channel == "r") {
1147
+ updateValues(new Color3(parseFloat(newValue), newSwatchRGB.g, newSwatchRGB.b), field.name);
1148
+ }
1149
+ else if (channel == "g") {
1150
+ updateValues(new Color3(newSwatchRGB.r, parseFloat(newValue), newSwatchRGB.b), field.name);
1151
+ }
1152
+ else {
1153
+ updateValues(new Color3(newSwatchRGB.r, newSwatchRGB.g, parseFloat(newValue)), field.name);
1154
+ }
1155
+ }
1262
1156
  }
1263
- if (swatchDrawer.rowCount != rowCount + gutterCount) {
1264
- const currentRows = swatchDrawer.rowCount;
1265
- for (let i = 0; i < currentRows; i++) {
1266
- swatchDrawer.removeRowDefinition(0);
1157
+ // Removes the current index from the savedColors array. Drawer can then be regenerated.
1158
+ function deleteSwatch(index) {
1159
+ if (options.savedColors) {
1160
+ options.savedColors.splice(index, 1);
1267
1161
  }
1268
- for (let i = 0; i < rowCount + gutterCount; i++) {
1269
- if (i % 2) {
1270
- swatchDrawer.addRowDefinition(swatchSize, true);
1162
+ if (options.savedColors && options.savedColors.length == 0) {
1163
+ setEditButtonVisibility(false);
1164
+ editSwatchMode = false;
1165
+ }
1166
+ }
1167
+ // Creates and styles an individual swatch when updateSwatches is called.
1168
+ function createSwatch() {
1169
+ if (options.savedColors && options.savedColors[swatchNumber]) {
1170
+ let icon;
1171
+ if (editSwatchMode) {
1172
+ icon = "b";
1271
1173
  }
1272
1174
  else {
1273
- swatchDrawer.addRowDefinition(gutterSize, true);
1175
+ icon = "";
1176
+ }
1177
+ const swatch = Button.CreateSimpleButton("Swatch_" + swatchNumber, icon);
1178
+ swatch.fontFamily = "coreglyphs";
1179
+ const swatchColor = Color3.FromHexString(options.savedColors[swatchNumber]);
1180
+ const swatchLuminence = swatchColor.r + swatchColor.g + swatchColor.b;
1181
+ // Set color of outline and textBlock based on luminance of the color swatch so feedback always visible
1182
+ if (swatchLuminence > luminanceLimit) {
1183
+ swatch.color = iconColorDark;
1274
1184
  }
1185
+ else {
1186
+ swatch.color = iconColorLight;
1187
+ }
1188
+ swatch.fontSize = Math.floor(swatchSize * 0.7);
1189
+ swatch.textBlock.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
1190
+ swatch.height = swatch.width = swatchSize.toString() + "px";
1191
+ swatch.background = options.savedColors[swatchNumber];
1192
+ swatch.thickness = 2;
1193
+ const metadata = swatchNumber;
1194
+ swatch.pointerDownAnimation = () => {
1195
+ swatch.thickness = 4;
1196
+ };
1197
+ swatch.pointerUpAnimation = () => {
1198
+ swatch.thickness = 3;
1199
+ };
1200
+ swatch.pointerEnterAnimation = () => {
1201
+ swatch.thickness = 3;
1202
+ };
1203
+ swatch.pointerOutAnimation = () => {
1204
+ swatch.thickness = 2;
1205
+ };
1206
+ swatch.onPointerClickObservable.add(() => {
1207
+ if (!editSwatchMode) {
1208
+ if (options.savedColors) {
1209
+ updateValues(Color3.FromHexString(options.savedColors[metadata]), swatch.name);
1210
+ }
1211
+ }
1212
+ else {
1213
+ deleteSwatch(metadata);
1214
+ updateSwatches("", butSave);
1215
+ }
1216
+ });
1217
+ return swatch;
1218
+ }
1219
+ else {
1220
+ return null;
1275
1221
  }
1276
1222
  }
1277
- swatchDrawer.height = (swatchSize * rowCount + gutterCount * gutterSize).toString() + "px";
1278
- for (let y = 1, thisRow = 1; y < rowCount + gutterCount; y += 2, thisRow++) {
1279
- // Determine number of buttons to create per row based on the button limit per row and number of saved colors
1280
- let totalButtonsThisRow;
1281
- if (options.savedColors.length > thisRow * options.numSwatchesPerLine) {
1282
- totalButtonsThisRow = options.numSwatchesPerLine;
1223
+ // Mode switch to render button text and close symbols on swatch controls
1224
+ function editSwatches(mode) {
1225
+ if (mode !== undefined) {
1226
+ editSwatchMode = mode;
1227
+ }
1228
+ let thisButton;
1229
+ if (editSwatchMode) {
1230
+ for (let i = 0; i < swatchDrawer.children.length; i++) {
1231
+ thisButton = swatchDrawer.children[i];
1232
+ thisButton.textBlock.text = "b";
1233
+ }
1234
+ if (butEdit !== undefined) {
1235
+ butEdit.textBlock.text = "Done";
1236
+ }
1283
1237
  }
1284
1238
  else {
1285
- totalButtonsThisRow = options.savedColors.length - (thisRow - 1) * options.numSwatchesPerLine;
1239
+ for (let i = 0; i < swatchDrawer.children.length; i++) {
1240
+ thisButton = swatchDrawer.children[i];
1241
+ thisButton.textBlock.text = "";
1242
+ }
1243
+ if (butEdit !== undefined) {
1244
+ butEdit.textBlock.text = "Edit";
1245
+ }
1286
1246
  }
1287
- const buttonIterations = Math.min(Math.max(totalButtonsThisRow, 0), options.numSwatchesPerLine);
1288
- for (let x = 0, w = 1; x < buttonIterations; x++) {
1289
- if (x > options.numSwatchesPerLine) {
1290
- continue;
1247
+ }
1248
+ /**
1249
+ * When Save Color button is pressed this function will first create a swatch drawer if one is not already
1250
+ * made. Then all controls are removed from the drawer and we step through the savedColors array and
1251
+ * creates one swatch per color. It will also set the height of the drawer control based on how many
1252
+ * saved colors there are and how many can be stored per row.
1253
+ * @param color
1254
+ * @param button
1255
+ */
1256
+ function updateSwatches(color, button) {
1257
+ if (options.savedColors) {
1258
+ if (color != "") {
1259
+ options.savedColors.push(color);
1291
1260
  }
1292
- const swatch = createSwatch();
1293
- if (swatch != null) {
1294
- swatchDrawer.addControl(swatch, y, w);
1295
- w += 2;
1296
- swatchNumber++;
1261
+ swatchNumber = 0;
1262
+ swatchDrawer.clearControls();
1263
+ const rowCount = Math.ceil(options.savedColors.length / options.numSwatchesPerLine);
1264
+ let gutterCount;
1265
+ if (rowCount == 0) {
1266
+ gutterCount = 0;
1297
1267
  }
1298
1268
  else {
1299
- continue;
1269
+ gutterCount = rowCount + 1;
1270
+ }
1271
+ if (swatchDrawer.rowCount != rowCount + gutterCount) {
1272
+ const currentRows = swatchDrawer.rowCount;
1273
+ for (let i = 0; i < currentRows; i++) {
1274
+ swatchDrawer.removeRowDefinition(0);
1275
+ }
1276
+ for (let i = 0; i < rowCount + gutterCount; i++) {
1277
+ if (i % 2) {
1278
+ swatchDrawer.addRowDefinition(swatchSize, true);
1279
+ }
1280
+ else {
1281
+ swatchDrawer.addRowDefinition(gutterSize, true);
1282
+ }
1283
+ }
1284
+ }
1285
+ swatchDrawer.height = (swatchSize * rowCount + gutterCount * gutterSize).toString() + "px";
1286
+ for (let y = 1, thisRow = 1; y < rowCount + gutterCount; y += 2, thisRow++) {
1287
+ // Determine number of buttons to create per row based on the button limit per row and number of saved colors
1288
+ let totalButtonsThisRow;
1289
+ if (options.savedColors.length > thisRow * options.numSwatchesPerLine) {
1290
+ totalButtonsThisRow = options.numSwatchesPerLine;
1291
+ }
1292
+ else {
1293
+ totalButtonsThisRow = options.savedColors.length - (thisRow - 1) * options.numSwatchesPerLine;
1294
+ }
1295
+ const buttonIterations = Math.min(Math.max(totalButtonsThisRow, 0), options.numSwatchesPerLine);
1296
+ for (let x = 0, w = 1; x < buttonIterations; x++) {
1297
+ if (x > options.numSwatchesPerLine) {
1298
+ continue;
1299
+ }
1300
+ const swatch = createSwatch();
1301
+ if (swatch != null) {
1302
+ swatchDrawer.addControl(swatch, y, w);
1303
+ w += 2;
1304
+ swatchNumber++;
1305
+ }
1306
+ else {
1307
+ continue;
1308
+ }
1309
+ }
1310
+ }
1311
+ if (options.savedColors.length >= options.swatchLimit) {
1312
+ disableButton(button, true);
1313
+ }
1314
+ else {
1315
+ disableButton(button, false);
1300
1316
  }
1301
1317
  }
1302
1318
  }
1303
- if (options.savedColors.length >= options.swatchLimit) {
1304
- disableButton(button, true);
1319
+ // Shows or hides edit swatches button depending on if there are saved swatches
1320
+ function setEditButtonVisibility(enableButton) {
1321
+ if (enableButton) {
1322
+ butEdit = Button.CreateSimpleButton("butEdit", "Edit");
1323
+ butEdit.width = buttonWidth;
1324
+ butEdit.height = buttonHeight;
1325
+ butEdit.left = Math.floor(parseInt(buttonWidth) * 0.1).toString() + "px";
1326
+ butEdit.top = (parseFloat(butEdit.left) * -1).toString() + "px";
1327
+ butEdit.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
1328
+ butEdit.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
1329
+ butEdit.thickness = 2;
1330
+ butEdit.color = buttonColor;
1331
+ butEdit.fontSize = buttonFontSize;
1332
+ butEdit.background = buttonBackgroundColor;
1333
+ butEdit.onPointerEnterObservable.add(() => {
1334
+ butEdit.background = buttonBackgroundHoverColor;
1335
+ });
1336
+ butEdit.onPointerOutObservable.add(() => {
1337
+ butEdit.background = buttonBackgroundColor;
1338
+ });
1339
+ butEdit.pointerDownAnimation = () => {
1340
+ butEdit.background = buttonBackgroundClickColor;
1341
+ };
1342
+ butEdit.pointerUpAnimation = () => {
1343
+ butEdit.background = buttonBackgroundHoverColor;
1344
+ };
1345
+ butEdit.onPointerClickObservable.add(() => {
1346
+ if (editSwatchMode) {
1347
+ editSwatchMode = false;
1348
+ }
1349
+ else {
1350
+ editSwatchMode = true;
1351
+ }
1352
+ editSwatches();
1353
+ });
1354
+ pickerGrid.addControl(butEdit, 1, 0);
1355
+ }
1356
+ else {
1357
+ pickerGrid.removeControl(butEdit);
1358
+ }
1305
1359
  }
1306
- else {
1307
- disableButton(button, false);
1360
+ // Called when the user hits the limit of saved colors in the drawer.
1361
+ function disableButton(button, disabled) {
1362
+ if (disabled) {
1363
+ button.color = buttonDisabledColor;
1364
+ button.background = buttonDisabledBackgroundColor;
1365
+ }
1366
+ else {
1367
+ button.color = buttonColor;
1368
+ button.background = buttonBackgroundColor;
1369
+ }
1308
1370
  }
1309
- }
1310
- }
1311
- // Shows or hides edit swatches button depending on if there are saved swatches
1312
- function setEditButtonVisibility(enableButton) {
1313
- if (enableButton) {
1314
- butEdit = Button.CreateSimpleButton("butEdit", "Edit");
1315
- butEdit.width = buttonWidth;
1316
- butEdit.height = buttonHeight;
1317
- butEdit.left = Math.floor(parseInt(buttonWidth) * 0.1).toString() + "px";
1318
- butEdit.top = (parseFloat(butEdit.left) * -1).toString() + "px";
1319
- butEdit.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
1320
- butEdit.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
1321
- butEdit.thickness = 2;
1322
- butEdit.color = buttonColor;
1323
- butEdit.fontSize = buttonFontSize;
1324
- butEdit.background = buttonBackgroundColor;
1325
- butEdit.onPointerEnterObservable.add(() => {
1326
- butEdit.background = buttonBackgroundHoverColor;
1327
- });
1328
- butEdit.onPointerOutObservable.add(() => {
1329
- butEdit.background = buttonBackgroundColor;
1330
- });
1331
- butEdit.pointerDownAnimation = () => {
1332
- butEdit.background = buttonBackgroundClickColor;
1333
- };
1334
- butEdit.pointerUpAnimation = () => {
1335
- butEdit.background = buttonBackgroundHoverColor;
1336
- };
1337
- butEdit.onPointerClickObservable.add(() => {
1338
- if (editSwatchMode) {
1339
- editSwatchMode = false;
1371
+ // Passes last chosen color back to scene and kills dialog by removing from AdvancedDynamicTexture
1372
+ function closePicker(color) {
1373
+ if (options.savedColors && options.savedColors.length > 0) {
1374
+ resolve({
1375
+ savedColors: options.savedColors,
1376
+ pickedColor: color,
1377
+ });
1340
1378
  }
1341
1379
  else {
1342
- editSwatchMode = true;
1380
+ resolve({
1381
+ pickedColor: color,
1382
+ });
1343
1383
  }
1344
- editSwatches();
1345
- });
1346
- pickerGrid.addControl(butEdit, 1, 0);
1347
- }
1348
- else {
1349
- pickerGrid.removeControl(butEdit);
1350
- }
1351
- }
1352
- // Called when the user hits the limit of saved colors in the drawer.
1353
- function disableButton(button, disabled) {
1354
- if (disabled) {
1355
- button.color = buttonDisabledColor;
1356
- button.background = buttonDisabledBackgroundColor;
1357
- }
1358
- else {
1359
- button.color = buttonColor;
1360
- button.background = buttonBackgroundColor;
1361
- }
1362
- }
1363
- // Passes last chosen color back to scene and kills dialog by removing from AdvancedDynamicTexture
1364
- function closePicker(color) {
1365
- if (options.savedColors && options.savedColors.length > 0) {
1366
- resolve({
1367
- savedColors: options.savedColors,
1368
- pickedColor: color,
1369
- });
1370
- }
1371
- else {
1372
- resolve({
1373
- pickedColor: color,
1374
- });
1375
- }
1376
- advancedTexture.removeControl(dialogContainer);
1384
+ advancedTexture.removeControl(dialogContainer);
1385
+ }
1386
+ });
1377
1387
  }
1378
- });
1379
- }
1380
- }
1381
- ColorPicker._Epsilon = 0.000001;
1382
- __decorate([
1383
- serialize()
1384
- ], ColorPicker.prototype, "value", null);
1385
- __decorate([
1386
- serialize()
1387
- ], ColorPicker.prototype, "width", null);
1388
- __decorate([
1389
- serialize()
1390
- ], ColorPicker.prototype, "height", null);
1391
- __decorate([
1392
- serialize()
1393
- ], ColorPicker.prototype, "size", null);
1388
+ },
1389
+ (() => {
1390
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1391
+ _get_value_decorators = [serialize()];
1392
+ _get_width_decorators = [serialize()];
1393
+ _get_height_decorators = [serialize()];
1394
+ _get_size_decorators = [serialize()];
1395
+ __esDecorate(_a, null, _get_value_decorators, { kind: "getter", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value }, metadata: _metadata }, null, _instanceExtraInitializers);
1396
+ __esDecorate(_a, null, _get_width_decorators, { kind: "getter", name: "width", static: false, private: false, access: { has: obj => "width" in obj, get: obj => obj.width }, metadata: _metadata }, null, _instanceExtraInitializers);
1397
+ __esDecorate(_a, null, _get_height_decorators, { kind: "getter", name: "height", static: false, private: false, access: { has: obj => "height" in obj, get: obj => obj.height }, metadata: _metadata }, null, _instanceExtraInitializers);
1398
+ __esDecorate(_a, null, _get_size_decorators, { kind: "getter", name: "size", static: false, private: false, access: { has: obj => "size" in obj, get: obj => obj.size }, metadata: _metadata }, null, _instanceExtraInitializers);
1399
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1400
+ })(),
1401
+ _a._Epsilon = 0.000001,
1402
+ _a;
1403
+ })();
1404
+ export { ColorPicker };
1394
1405
  let _Registered = false;
1395
1406
  /**
1396
1407
  * Registers the ColorPicker class with the type store for serialization support.