spoint 0.1.0 → 0.1.10

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 (204) hide show
  1. package/README.md +134 -209
  2. package/SKILL.md +95 -0
  3. package/apps/environment/index.js +200 -1
  4. package/apps/environment/models/decorative/.gitkeep +0 -0
  5. package/apps/environment/models/hazards/.gitkeep +0 -0
  6. package/apps/environment/models/interactive/.gitkeep +0 -0
  7. package/apps/environment/models/structures/.gitkeep +0 -0
  8. package/apps/environment/smartObjects.js +114 -0
  9. package/apps/interactable/index.js +155 -0
  10. package/apps/physics-crate/index.js +15 -9
  11. package/apps/power-crate/index.js +18 -12
  12. package/apps/tps-game/$GDUPI.vrm +0 -0
  13. package/apps/tps-game/Cleetus.vrm +0 -0
  14. package/apps/tps-game/index.js +185 -27
  15. package/apps/world/index.js +68 -22
  16. package/bin/create-app.js +337 -0
  17. package/client/ARControls.js +301 -0
  18. package/client/LoadingManager.js +117 -0
  19. package/client/MobileControls.js +1122 -0
  20. package/client/anim-lib.glb +0 -0
  21. package/client/animation.js +306 -0
  22. package/client/app.js +1341 -65
  23. package/client/camera.js +191 -33
  24. package/client/createLoadingScreen.js +69 -0
  25. package/client/editor/bridge.js +113 -0
  26. package/client/editor/css/main.css +794 -0
  27. package/client/editor/images/rotate.svg +4 -0
  28. package/client/editor/images/scale.svg +4 -0
  29. package/client/editor/images/translate.svg +4 -0
  30. package/client/editor/index.html +103 -0
  31. package/client/editor/js/Command.js +41 -0
  32. package/client/editor/js/Config.js +81 -0
  33. package/client/editor/js/Editor.js +785 -0
  34. package/client/editor/js/EditorControls.js +438 -0
  35. package/client/editor/js/History.js +321 -0
  36. package/client/editor/js/Loader.js +987 -0
  37. package/client/editor/js/LoaderUtils.js +90 -0
  38. package/client/editor/js/Menubar.Add.js +510 -0
  39. package/client/editor/js/Menubar.Edit.js +145 -0
  40. package/client/editor/js/Menubar.File.js +466 -0
  41. package/client/editor/js/Menubar.Help.js +73 -0
  42. package/client/editor/js/Menubar.Status.js +51 -0
  43. package/client/editor/js/Menubar.View.js +183 -0
  44. package/client/editor/js/Menubar.js +27 -0
  45. package/client/editor/js/Player.js +53 -0
  46. package/client/editor/js/Resizer.js +58 -0
  47. package/client/editor/js/Script.js +503 -0
  48. package/client/editor/js/Selector.js +102 -0
  49. package/client/editor/js/Sidebar.Geometry.BoxGeometry.js +121 -0
  50. package/client/editor/js/Sidebar.Geometry.BufferGeometry.js +115 -0
  51. package/client/editor/js/Sidebar.Geometry.CapsuleGeometry.js +97 -0
  52. package/client/editor/js/Sidebar.Geometry.CircleGeometry.js +97 -0
  53. package/client/editor/js/Sidebar.Geometry.CylinderGeometry.js +121 -0
  54. package/client/editor/js/Sidebar.Geometry.DodecahedronGeometry.js +73 -0
  55. package/client/editor/js/Sidebar.Geometry.ExtrudeGeometry.js +196 -0
  56. package/client/editor/js/Sidebar.Geometry.IcosahedronGeometry.js +73 -0
  57. package/client/editor/js/Sidebar.Geometry.LatheGeometry.js +98 -0
  58. package/client/editor/js/Sidebar.Geometry.Modifiers.js +73 -0
  59. package/client/editor/js/Sidebar.Geometry.OctahedronGeometry.js +74 -0
  60. package/client/editor/js/Sidebar.Geometry.PlaneGeometry.js +97 -0
  61. package/client/editor/js/Sidebar.Geometry.RingGeometry.js +121 -0
  62. package/client/editor/js/Sidebar.Geometry.ShapeGeometry.js +76 -0
  63. package/client/editor/js/Sidebar.Geometry.SphereGeometry.js +133 -0
  64. package/client/editor/js/Sidebar.Geometry.TetrahedronGeometry.js +74 -0
  65. package/client/editor/js/Sidebar.Geometry.TorusGeometry.js +109 -0
  66. package/client/editor/js/Sidebar.Geometry.TorusKnotGeometry.js +121 -0
  67. package/client/editor/js/Sidebar.Geometry.TubeGeometry.js +135 -0
  68. package/client/editor/js/Sidebar.Geometry.js +332 -0
  69. package/client/editor/js/Sidebar.Material.BooleanProperty.js +60 -0
  70. package/client/editor/js/Sidebar.Material.ColorProperty.js +87 -0
  71. package/client/editor/js/Sidebar.Material.ConstantProperty.js +62 -0
  72. package/client/editor/js/Sidebar.Material.MapProperty.js +249 -0
  73. package/client/editor/js/Sidebar.Material.NumberProperty.js +60 -0
  74. package/client/editor/js/Sidebar.Material.Program.js +73 -0
  75. package/client/editor/js/Sidebar.Material.RangeValueProperty.js +63 -0
  76. package/client/editor/js/Sidebar.Material.js +751 -0
  77. package/client/editor/js/Sidebar.Object.Animation.js +102 -0
  78. package/client/editor/js/Sidebar.Object.js +898 -0
  79. package/client/editor/js/Sidebar.Project.App.js +165 -0
  80. package/client/editor/js/Sidebar.Project.Image.js +225 -0
  81. package/client/editor/js/Sidebar.Project.Materials.js +82 -0
  82. package/client/editor/js/Sidebar.Project.Renderer.js +144 -0
  83. package/client/editor/js/Sidebar.Project.Video.js +242 -0
  84. package/client/editor/js/Sidebar.Project.js +31 -0
  85. package/client/editor/js/Sidebar.Properties.js +73 -0
  86. package/client/editor/js/Sidebar.Scene.js +585 -0
  87. package/client/editor/js/Sidebar.Script.js +129 -0
  88. package/client/editor/js/Sidebar.Settings.History.js +146 -0
  89. package/client/editor/js/Sidebar.Settings.Shortcuts.js +175 -0
  90. package/client/editor/js/Sidebar.Settings.js +60 -0
  91. package/client/editor/js/Sidebar.js +41 -0
  92. package/client/editor/js/Storage.js +98 -0
  93. package/client/editor/js/Strings.js +2028 -0
  94. package/client/editor/js/Toolbar.js +84 -0
  95. package/client/editor/js/Viewport.Controls.js +92 -0
  96. package/client/editor/js/Viewport.Info.js +136 -0
  97. package/client/editor/js/Viewport.Pathtracer.js +91 -0
  98. package/client/editor/js/Viewport.ViewHelper.js +39 -0
  99. package/client/editor/js/Viewport.XR.js +222 -0
  100. package/client/editor/js/Viewport.js +900 -0
  101. package/client/editor/js/commands/AddObjectCommand.js +68 -0
  102. package/client/editor/js/commands/AddScriptCommand.js +75 -0
  103. package/client/editor/js/commands/Commands.js +23 -0
  104. package/client/editor/js/commands/MoveObjectCommand.js +111 -0
  105. package/client/editor/js/commands/MultiCmdsCommand.js +85 -0
  106. package/client/editor/js/commands/RemoveObjectCommand.js +88 -0
  107. package/client/editor/js/commands/RemoveScriptCommand.js +81 -0
  108. package/client/editor/js/commands/SetColorCommand.js +73 -0
  109. package/client/editor/js/commands/SetGeometryCommand.js +87 -0
  110. package/client/editor/js/commands/SetGeometryValueCommand.js +70 -0
  111. package/client/editor/js/commands/SetMaterialColorCommand.js +86 -0
  112. package/client/editor/js/commands/SetMaterialCommand.js +79 -0
  113. package/client/editor/js/commands/SetMaterialMapCommand.js +143 -0
  114. package/client/editor/js/commands/SetMaterialRangeCommand.js +91 -0
  115. package/client/editor/js/commands/SetMaterialValueCommand.js +90 -0
  116. package/client/editor/js/commands/SetMaterialVectorCommand.js +79 -0
  117. package/client/editor/js/commands/SetPositionCommand.js +84 -0
  118. package/client/editor/js/commands/SetRotationCommand.js +84 -0
  119. package/client/editor/js/commands/SetScaleCommand.js +84 -0
  120. package/client/editor/js/commands/SetSceneCommand.js +103 -0
  121. package/client/editor/js/commands/SetScriptValueCommand.js +80 -0
  122. package/client/editor/js/commands/SetShadowValueCommand.js +73 -0
  123. package/client/editor/js/commands/SetUuidCommand.js +70 -0
  124. package/client/editor/js/commands/SetValueCommand.js +75 -0
  125. package/client/editor/js/libs/acorn/acorn.js +3236 -0
  126. package/client/editor/js/libs/acorn/acorn_loose.js +1299 -0
  127. package/client/editor/js/libs/acorn/walk.js +344 -0
  128. package/client/editor/js/libs/app/index.html +57 -0
  129. package/client/editor/js/libs/app.js +251 -0
  130. package/client/editor/js/libs/codemirror/addon/dialog.css +32 -0
  131. package/client/editor/js/libs/codemirror/addon/dialog.js +163 -0
  132. package/client/editor/js/libs/codemirror/addon/show-hint.css +36 -0
  133. package/client/editor/js/libs/codemirror/addon/show-hint.js +529 -0
  134. package/client/editor/js/libs/codemirror/addon/tern.css +87 -0
  135. package/client/editor/js/libs/codemirror/addon/tern.js +750 -0
  136. package/client/editor/js/libs/codemirror/codemirror.css +344 -0
  137. package/client/editor/js/libs/codemirror/codemirror.js +9849 -0
  138. package/client/editor/js/libs/codemirror/mode/glsl.js +233 -0
  139. package/client/editor/js/libs/codemirror/mode/javascript.js +959 -0
  140. package/client/editor/js/libs/codemirror/theme/monokai.css +41 -0
  141. package/client/editor/js/libs/esprima.js +6401 -0
  142. package/client/editor/js/libs/jsonlint.js +453 -0
  143. package/client/editor/js/libs/signals.min.js +14 -0
  144. package/client/editor/js/libs/tern-threejs/threejs.js +5031 -0
  145. package/client/editor/js/libs/ternjs/comment.js +87 -0
  146. package/client/editor/js/libs/ternjs/def.js +588 -0
  147. package/client/editor/js/libs/ternjs/doc_comment.js +401 -0
  148. package/client/editor/js/libs/ternjs/infer.js +1635 -0
  149. package/client/editor/js/libs/ternjs/polyfill.js +80 -0
  150. package/client/editor/js/libs/ternjs/signal.js +26 -0
  151. package/client/editor/js/libs/ternjs/tern.js +993 -0
  152. package/client/editor/js/libs/ui.js +1346 -0
  153. package/client/editor/js/libs/ui.three.js +855 -0
  154. package/client/facial-animation.js +455 -0
  155. package/client/index.html +7 -4
  156. package/client/loading.css +147 -0
  157. package/client/loading.html +25 -0
  158. package/client/style.css +251 -0
  159. package/package.json +7 -3
  160. package/server.js +9 -1
  161. package/src/apps/AppContext.js +1 -1
  162. package/src/apps/AppLoader.js +50 -37
  163. package/src/apps/AppRuntime.js +32 -8
  164. package/src/client/InputHandler.js +233 -0
  165. package/src/client/JitterBuffer.js +207 -0
  166. package/src/client/KalmanFilter.js +125 -0
  167. package/src/client/MessageHandler.js +101 -0
  168. package/src/client/PhysicsNetworkClient.js +141 -68
  169. package/src/client/ReconnectManager.js +62 -0
  170. package/src/client/SmoothInterpolation.js +127 -0
  171. package/src/client/SnapshotProcessor.js +144 -0
  172. package/src/connection/ConnectionManager.js +21 -3
  173. package/src/connection/SessionStore.js +13 -3
  174. package/src/index.client.js +4 -6
  175. package/src/netcode/EventLog.js +29 -15
  176. package/src/netcode/LagCompensator.js +25 -26
  177. package/src/netcode/NetworkState.js +4 -1
  178. package/src/netcode/PhysicsIntegration.js +20 -6
  179. package/src/netcode/PlayerManager.js +10 -2
  180. package/src/netcode/SnapshotEncoder.js +66 -19
  181. package/src/netcode/TickSystem.js +13 -4
  182. package/src/physics/World.js +66 -13
  183. package/src/protocol/msgpack.js +90 -63
  184. package/src/sdk/ReloadHandlers.js +12 -2
  185. package/src/sdk/ReloadManager.js +5 -0
  186. package/src/sdk/ServerHandlers.js +50 -11
  187. package/src/sdk/StaticHandler.js +22 -6
  188. package/src/sdk/TickHandler.js +101 -34
  189. package/src/sdk/scaffold.js +28 -0
  190. package/src/sdk/server.js +59 -33
  191. package/src/shared/movement.js +2 -1
  192. package/src/spatial/Octree.js +5 -0
  193. package/apps/interactive-door/index.js +0 -33
  194. package/apps/patrol-npc/index.js +0 -37
  195. package/src/connection/QualityMonitor.js +0 -46
  196. package/src/debug/StateInspector.js +0 -42
  197. package/src/index.js +0 -1
  198. package/src/index.server.js +0 -27
  199. package/src/protocol/Codec.js +0 -60
  200. package/src/protocol/SequenceTracker.js +0 -71
  201. package/src/sdk/ClientMessageHandler.js +0 -80
  202. package/src/sdk/client.js +0 -122
  203. package/world/kaira.glb +0 -0
  204. package/world/schwust.glb +0 -0
@@ -0,0 +1,1346 @@
1
+ class UIElement {
2
+
3
+ constructor( dom ) {
4
+
5
+ this.dom = dom;
6
+
7
+ }
8
+
9
+ add() {
10
+
11
+ for ( let i = 0; i < arguments.length; i ++ ) {
12
+
13
+ const argument = arguments[ i ];
14
+
15
+ if ( argument instanceof UIElement ) {
16
+
17
+ this.dom.appendChild( argument.dom );
18
+
19
+ } else {
20
+
21
+ console.error( 'UIElement:', argument, 'is not an instance of UIElement.' );
22
+
23
+ }
24
+
25
+ }
26
+
27
+ return this;
28
+
29
+ }
30
+
31
+ remove() {
32
+
33
+ for ( let i = 0; i < arguments.length; i ++ ) {
34
+
35
+ const argument = arguments[ i ];
36
+
37
+ if ( argument instanceof UIElement ) {
38
+
39
+ this.dom.removeChild( argument.dom );
40
+
41
+ } else {
42
+
43
+ console.error( 'UIElement:', argument, 'is not an instance of UIElement.' );
44
+
45
+ }
46
+
47
+ }
48
+
49
+ return this;
50
+
51
+ }
52
+
53
+ clear() {
54
+
55
+ while ( this.dom.children.length ) {
56
+
57
+ this.dom.removeChild( this.dom.lastChild );
58
+
59
+ }
60
+
61
+ }
62
+
63
+ setId( id ) {
64
+
65
+ this.dom.id = id;
66
+
67
+ return this;
68
+
69
+ }
70
+
71
+ getId() {
72
+
73
+ return this.dom.id;
74
+
75
+ }
76
+
77
+ setClass( name ) {
78
+
79
+ this.dom.className = name;
80
+
81
+ return this;
82
+
83
+ }
84
+
85
+ addClass( name ) {
86
+
87
+ this.dom.classList.add( name );
88
+
89
+ return this;
90
+
91
+ }
92
+
93
+ removeClass( name ) {
94
+
95
+ this.dom.classList.remove( name );
96
+
97
+ return this;
98
+
99
+ }
100
+
101
+ toggleClass( name, toggle ) {
102
+
103
+ this.dom.classList.toggle( name, toggle );
104
+
105
+ return this;
106
+
107
+ }
108
+
109
+ setStyle( style, array ) {
110
+
111
+ for ( let i = 0; i < array.length; i ++ ) {
112
+
113
+ this.dom.style[ style ] = array[ i ];
114
+
115
+ }
116
+
117
+ return this;
118
+
119
+ }
120
+
121
+ setHidden( isHidden ) {
122
+
123
+ this.dom.hidden = isHidden;
124
+
125
+ return this;
126
+
127
+ }
128
+
129
+ isHidden() {
130
+
131
+ return this.dom.hidden;
132
+
133
+ }
134
+
135
+ setDisabled( value ) {
136
+
137
+ this.dom.disabled = value;
138
+
139
+ return this;
140
+
141
+ }
142
+
143
+ setTextContent( value ) {
144
+
145
+ this.dom.textContent = value;
146
+
147
+ return this;
148
+
149
+ }
150
+
151
+ setInnerHTML( value ) {
152
+
153
+ this.dom.innerHTML = value;
154
+
155
+ }
156
+
157
+ getIndexOfChild( element ) {
158
+
159
+ return Array.prototype.indexOf.call( this.dom.children, element.dom );
160
+
161
+ }
162
+
163
+ }
164
+
165
+ // properties
166
+
167
+ const properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height',
168
+ 'display', 'verticalAlign', 'overflow', 'color', 'background', 'backgroundColor', 'opacity',
169
+ 'border', 'borderLeft', 'borderTop', 'borderRight', 'borderBottom', 'borderColor',
170
+ 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom',
171
+ 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom',
172
+ 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex' ];
173
+
174
+ properties.forEach( function ( property ) {
175
+
176
+ const method = 'set' + property.substring( 0, 1 ).toUpperCase() + property.substring( 1 );
177
+
178
+ UIElement.prototype[ method ] = function () {
179
+
180
+ this.setStyle( property, arguments );
181
+
182
+ return this;
183
+
184
+ };
185
+
186
+ } );
187
+
188
+ // events
189
+
190
+ const events = [ 'KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'DblClick', 'Change', 'Input' ];
191
+
192
+ events.forEach( function ( event ) {
193
+
194
+ const method = 'on' + event;
195
+
196
+ UIElement.prototype[ method ] = function ( callback ) {
197
+
198
+ this.dom.addEventListener( event.toLowerCase(), callback.bind( this ) );
199
+
200
+ return this;
201
+
202
+ };
203
+
204
+ } );
205
+
206
+ class UISpan extends UIElement {
207
+
208
+ constructor() {
209
+
210
+ super( document.createElement( 'span' ) );
211
+
212
+ }
213
+
214
+ }
215
+
216
+ class UIDiv extends UIElement {
217
+
218
+ constructor() {
219
+
220
+ super( document.createElement( 'div' ) );
221
+
222
+ }
223
+
224
+ }
225
+
226
+ class UIRow extends UIDiv {
227
+
228
+ constructor() {
229
+
230
+ super();
231
+
232
+ this.dom.className = 'Row';
233
+
234
+ }
235
+
236
+ }
237
+
238
+ class UIPanel extends UIDiv {
239
+
240
+ constructor() {
241
+
242
+ super();
243
+
244
+ this.dom.className = 'Panel';
245
+
246
+ }
247
+
248
+ }
249
+
250
+ class UIText extends UISpan {
251
+
252
+ constructor( text ) {
253
+
254
+ super();
255
+
256
+ this.dom.className = 'Text';
257
+ this.dom.style.cursor = 'default';
258
+ this.dom.style.display = 'inline-block';
259
+
260
+ this.setValue( text );
261
+
262
+ }
263
+
264
+ getValue() {
265
+
266
+ return this.dom.textContent;
267
+
268
+ }
269
+
270
+ setValue( value ) {
271
+
272
+ if ( value !== undefined ) {
273
+
274
+ this.dom.textContent = value;
275
+
276
+ }
277
+
278
+ return this;
279
+
280
+ }
281
+
282
+ }
283
+
284
+
285
+ class UIInput extends UIElement {
286
+
287
+ constructor( text ) {
288
+
289
+ super( document.createElement( 'input' ) );
290
+
291
+ this.dom.className = 'Input';
292
+ this.dom.style.padding = '2px';
293
+ this.dom.style.border = '1px solid transparent';
294
+
295
+ this.dom.setAttribute( 'autocomplete', 'off' );
296
+
297
+ this.dom.addEventListener( 'keydown', function ( event ) {
298
+
299
+ event.stopPropagation();
300
+
301
+ } );
302
+
303
+ this.setValue( text );
304
+
305
+ }
306
+
307
+ getValue() {
308
+
309
+ return this.dom.value;
310
+
311
+ }
312
+
313
+ setValue( value ) {
314
+
315
+ this.dom.value = value;
316
+
317
+ return this;
318
+
319
+ }
320
+
321
+ }
322
+
323
+ class UITextArea extends UIElement {
324
+
325
+ constructor() {
326
+
327
+ super( document.createElement( 'textarea' ) );
328
+
329
+ this.dom.className = 'TextArea';
330
+ this.dom.style.padding = '2px';
331
+ this.dom.spellcheck = false;
332
+
333
+ this.dom.setAttribute( 'autocomplete', 'off' );
334
+
335
+ this.dom.addEventListener( 'keydown', function ( event ) {
336
+
337
+ event.stopPropagation();
338
+
339
+ if ( event.code === 'Tab' ) {
340
+
341
+ event.preventDefault();
342
+
343
+ const cursor = this.selectionStart;
344
+
345
+ this.value = this.value.substring( 0, cursor ) + '\t' + this.value.substring( cursor );
346
+ this.selectionStart = cursor + 1;
347
+ this.selectionEnd = this.selectionStart;
348
+
349
+ }
350
+
351
+ } );
352
+
353
+ }
354
+
355
+ getValue() {
356
+
357
+ return this.dom.value;
358
+
359
+ }
360
+
361
+ setValue( value ) {
362
+
363
+ this.dom.value = value;
364
+
365
+ return this;
366
+
367
+ }
368
+
369
+ }
370
+
371
+ class UISelect extends UIElement {
372
+
373
+ constructor() {
374
+
375
+ super( document.createElement( 'select' ) );
376
+
377
+ this.dom.className = 'Select';
378
+ this.dom.style.padding = '2px';
379
+
380
+ this.dom.setAttribute( 'autocomplete', 'off' );
381
+
382
+ this.dom.addEventListener( 'pointerdown', function ( event ) {
383
+
384
+ event.stopPropagation();
385
+
386
+ } );
387
+
388
+ }
389
+
390
+ setMultiple( boolean ) {
391
+
392
+ this.dom.multiple = boolean;
393
+
394
+ return this;
395
+
396
+ }
397
+
398
+ setOptions( options ) {
399
+
400
+ const selected = this.dom.value;
401
+
402
+ while ( this.dom.children.length > 0 ) {
403
+
404
+ this.dom.removeChild( this.dom.firstChild );
405
+
406
+ }
407
+
408
+ for ( const key in options ) {
409
+
410
+ const option = document.createElement( 'option' );
411
+ option.value = key;
412
+ option.innerHTML = options[ key ];
413
+ this.dom.appendChild( option );
414
+
415
+ }
416
+
417
+ this.dom.value = selected;
418
+
419
+ return this;
420
+
421
+ }
422
+
423
+ getValue() {
424
+
425
+ return this.dom.value;
426
+
427
+ }
428
+
429
+ setValue( value ) {
430
+
431
+ value = String( value );
432
+
433
+ if ( this.dom.value !== value ) {
434
+
435
+ this.dom.value = value;
436
+
437
+ }
438
+
439
+ return this;
440
+
441
+ }
442
+
443
+ }
444
+
445
+ class UICheckbox extends UIElement {
446
+
447
+ constructor( boolean ) {
448
+
449
+ super( document.createElement( 'input' ) );
450
+
451
+ this.dom.className = 'Checkbox';
452
+ this.dom.type = 'checkbox';
453
+
454
+ this.dom.addEventListener( 'pointerdown', function ( event ) {
455
+
456
+ // Workaround for TransformControls blocking events in Viewport.Controls checkboxes
457
+
458
+ event.stopPropagation();
459
+
460
+ } );
461
+
462
+ this.setValue( boolean );
463
+
464
+ }
465
+
466
+ getValue() {
467
+
468
+ return this.dom.checked;
469
+
470
+ }
471
+
472
+ setValue( value ) {
473
+
474
+ if ( value !== undefined ) {
475
+
476
+ this.dom.checked = value;
477
+
478
+ }
479
+
480
+ return this;
481
+
482
+ }
483
+
484
+ }
485
+
486
+
487
+ class UIColor extends UIElement {
488
+
489
+ constructor() {
490
+
491
+ super( document.createElement( 'input' ) );
492
+
493
+ this.dom.className = 'Color';
494
+ this.dom.style.width = '32px';
495
+ this.dom.style.height = '16px';
496
+ this.dom.style.border = '0px';
497
+ this.dom.style.padding = '2px';
498
+ this.dom.style.backgroundColor = 'transparent';
499
+
500
+ this.dom.setAttribute( 'autocomplete', 'off' );
501
+
502
+ try {
503
+
504
+ this.dom.type = 'color';
505
+ this.dom.value = '#ffffff';
506
+
507
+ } catch ( exception ) {}
508
+
509
+ }
510
+
511
+ getValue() {
512
+
513
+ return this.dom.value;
514
+
515
+ }
516
+
517
+ getHexValue() {
518
+
519
+ return parseInt( this.dom.value.substring( 1 ), 16 );
520
+
521
+ }
522
+
523
+ setValue( value ) {
524
+
525
+ this.dom.value = value;
526
+
527
+ return this;
528
+
529
+ }
530
+
531
+ setHexValue( hex ) {
532
+
533
+ this.dom.value = '#' + ( '000000' + hex.toString( 16 ) ).slice( - 6 );
534
+
535
+ return this;
536
+
537
+ }
538
+
539
+ }
540
+
541
+ class UINumber extends UIElement {
542
+
543
+ constructor( number ) {
544
+
545
+ super( document.createElement( 'input' ) );
546
+
547
+ this.dom.style.cursor = 'ns-resize';
548
+ this.dom.className = 'Number';
549
+ this.dom.value = '0.00';
550
+
551
+ this.dom.setAttribute( 'autocomplete', 'off' );
552
+
553
+ this.value = 0;
554
+
555
+ this.min = - Infinity;
556
+ this.max = Infinity;
557
+
558
+ this.precision = 2;
559
+ this.step = 1;
560
+ this.unit = '';
561
+ this.nudge = 0.01;
562
+
563
+ this.setValue( number );
564
+
565
+ const scope = this;
566
+
567
+ const changeEvent = new Event( 'change', { bubbles: true, cancelable: true } );
568
+
569
+ let distance = 0;
570
+ let onMouseDownValue = 0;
571
+
572
+ const pointer = { x: 0, y: 0 };
573
+ const prevPointer = { x: 0, y: 0 };
574
+
575
+ function onMouseDown( event ) {
576
+
577
+ if ( document.activeElement === scope.dom ) return;
578
+
579
+ event.preventDefault();
580
+
581
+ distance = 0;
582
+
583
+ onMouseDownValue = scope.value;
584
+
585
+ prevPointer.x = event.clientX;
586
+ prevPointer.y = event.clientY;
587
+
588
+ document.addEventListener( 'mousemove', onMouseMove );
589
+ document.addEventListener( 'mouseup', onMouseUp );
590
+
591
+ }
592
+
593
+ function onMouseMove( event ) {
594
+
595
+ const currentValue = scope.value;
596
+
597
+ pointer.x = event.clientX;
598
+ pointer.y = event.clientY;
599
+
600
+ distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
601
+
602
+ let value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
603
+ value = Math.min( scope.max, Math.max( scope.min, value ) );
604
+
605
+ if ( currentValue !== value ) {
606
+
607
+ scope.setValue( value );
608
+ scope.dom.dispatchEvent( changeEvent );
609
+
610
+ }
611
+
612
+ prevPointer.x = event.clientX;
613
+ prevPointer.y = event.clientY;
614
+
615
+ }
616
+
617
+ function onMouseUp() {
618
+
619
+ document.removeEventListener( 'mousemove', onMouseMove );
620
+ document.removeEventListener( 'mouseup', onMouseUp );
621
+
622
+ if ( Math.abs( distance ) < 2 ) {
623
+
624
+ scope.dom.focus();
625
+ scope.dom.select();
626
+
627
+ }
628
+
629
+ }
630
+
631
+ function onTouchStart( event ) {
632
+
633
+ if ( event.touches.length === 1 ) {
634
+
635
+ distance = 0;
636
+
637
+ onMouseDownValue = scope.value;
638
+
639
+ prevPointer.x = event.touches[ 0 ].pageX;
640
+ prevPointer.y = event.touches[ 0 ].pageY;
641
+
642
+ document.addEventListener( 'touchmove', onTouchMove, { passive: false } );
643
+ document.addEventListener( 'touchend', onTouchEnd );
644
+
645
+ }
646
+
647
+ }
648
+
649
+ function onTouchMove( event ) {
650
+
651
+ event.preventDefault();
652
+
653
+ const currentValue = scope.value;
654
+
655
+ pointer.x = event.touches[ 0 ].pageX;
656
+ pointer.y = event.touches[ 0 ].pageY;
657
+
658
+ distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
659
+
660
+ let value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
661
+ value = Math.min( scope.max, Math.max( scope.min, value ) );
662
+
663
+ if ( currentValue !== value ) {
664
+
665
+ scope.setValue( value );
666
+ scope.dom.dispatchEvent( changeEvent );
667
+
668
+ }
669
+
670
+ prevPointer.x = event.touches[ 0 ].pageX;
671
+ prevPointer.y = event.touches[ 0 ].pageY;
672
+
673
+ }
674
+
675
+ function onTouchEnd( event ) {
676
+
677
+ if ( event.touches.length === 0 ) {
678
+
679
+ document.removeEventListener( 'touchmove', onTouchMove );
680
+ document.removeEventListener( 'touchend', onTouchEnd );
681
+
682
+ }
683
+
684
+ }
685
+
686
+ function onChange() {
687
+
688
+ scope.setValue( scope.dom.value );
689
+
690
+ }
691
+
692
+ function onFocus() {
693
+
694
+ scope.dom.style.backgroundColor = '';
695
+ scope.dom.style.cursor = '';
696
+
697
+ }
698
+
699
+ function onBlur() {
700
+
701
+ scope.dom.style.backgroundColor = 'transparent';
702
+ scope.dom.style.cursor = 'ns-resize';
703
+
704
+ }
705
+
706
+ function onKeyDown( event ) {
707
+
708
+ event.stopPropagation();
709
+
710
+ switch ( event.code ) {
711
+
712
+ case 'Enter':
713
+ scope.dom.blur();
714
+ break;
715
+
716
+ case 'ArrowUp':
717
+ event.preventDefault();
718
+ scope.setValue( scope.getValue() + scope.nudge );
719
+ scope.dom.dispatchEvent( changeEvent );
720
+ break;
721
+
722
+ case 'ArrowDown':
723
+ event.preventDefault();
724
+ scope.setValue( scope.getValue() - scope.nudge );
725
+ scope.dom.dispatchEvent( changeEvent );
726
+ break;
727
+
728
+ }
729
+
730
+ }
731
+
732
+ onBlur();
733
+
734
+ this.dom.addEventListener( 'keydown', onKeyDown );
735
+ this.dom.addEventListener( 'mousedown', onMouseDown );
736
+ this.dom.addEventListener( 'touchstart', onTouchStart, { passive: false } );
737
+ this.dom.addEventListener( 'change', onChange );
738
+ this.dom.addEventListener( 'focus', onFocus );
739
+ this.dom.addEventListener( 'blur', onBlur );
740
+
741
+ }
742
+
743
+ getValue() {
744
+
745
+ return this.value;
746
+
747
+ }
748
+
749
+ setValue( value ) {
750
+
751
+ if ( value !== undefined ) {
752
+
753
+ value = parseFloat( value );
754
+
755
+ if ( value < this.min ) value = this.min;
756
+ if ( value > this.max ) value = this.max;
757
+
758
+ this.value = value;
759
+ this.dom.value = value.toFixed( this.precision );
760
+
761
+ if ( this.unit !== '' ) this.dom.value += ' ' + this.unit;
762
+
763
+ }
764
+
765
+ return this;
766
+
767
+ }
768
+
769
+ setPrecision( precision ) {
770
+
771
+ this.precision = precision;
772
+
773
+ return this;
774
+
775
+ }
776
+
777
+ setStep( step ) {
778
+
779
+ this.step = step;
780
+
781
+ return this;
782
+
783
+ }
784
+
785
+ setNudge( nudge ) {
786
+
787
+ this.nudge = nudge;
788
+
789
+ return this;
790
+
791
+ }
792
+
793
+ setRange( min, max ) {
794
+
795
+ this.min = min;
796
+ this.max = max;
797
+
798
+ return this;
799
+
800
+ }
801
+
802
+ setUnit( unit ) {
803
+
804
+ this.unit = unit;
805
+
806
+ this.setValue( this.value );
807
+
808
+ return this;
809
+
810
+ }
811
+
812
+ }
813
+
814
+ class UIInteger extends UIElement {
815
+
816
+ constructor( number ) {
817
+
818
+ super( document.createElement( 'input' ) );
819
+
820
+ this.dom.style.cursor = 'ns-resize';
821
+ this.dom.className = 'Number';
822
+ this.dom.value = '0';
823
+
824
+ this.dom.setAttribute( 'autocomplete', 'off' );
825
+
826
+ this.value = 0;
827
+
828
+ this.min = - Infinity;
829
+ this.max = Infinity;
830
+
831
+ this.step = 1;
832
+ this.nudge = 1;
833
+
834
+ this.setValue( number );
835
+
836
+ const scope = this;
837
+
838
+ const changeEvent = new Event( 'change', { bubbles: true, cancelable: true } );
839
+
840
+ let distance = 0;
841
+ let onMouseDownValue = 0;
842
+
843
+ const pointer = { x: 0, y: 0 };
844
+ const prevPointer = { x: 0, y: 0 };
845
+
846
+ function onMouseDown( event ) {
847
+
848
+ if ( document.activeElement === scope.dom ) return;
849
+
850
+ event.preventDefault();
851
+
852
+ distance = 0;
853
+
854
+ onMouseDownValue = scope.value;
855
+
856
+ prevPointer.x = event.clientX;
857
+ prevPointer.y = event.clientY;
858
+
859
+ document.addEventListener( 'mousemove', onMouseMove );
860
+ document.addEventListener( 'mouseup', onMouseUp );
861
+
862
+ }
863
+
864
+ function onMouseMove( event ) {
865
+
866
+ const currentValue = scope.value;
867
+
868
+ pointer.x = event.clientX;
869
+ pointer.y = event.clientY;
870
+
871
+ distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
872
+
873
+ let value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
874
+ value = Math.min( scope.max, Math.max( scope.min, value ) ) | 0;
875
+
876
+ if ( currentValue !== value ) {
877
+
878
+ scope.setValue( value );
879
+ scope.dom.dispatchEvent( changeEvent );
880
+
881
+ }
882
+
883
+ prevPointer.x = event.clientX;
884
+ prevPointer.y = event.clientY;
885
+
886
+ }
887
+
888
+ function onMouseUp() {
889
+
890
+ document.removeEventListener( 'mousemove', onMouseMove );
891
+ document.removeEventListener( 'mouseup', onMouseUp );
892
+
893
+ if ( Math.abs( distance ) < 2 ) {
894
+
895
+ scope.dom.focus();
896
+ scope.dom.select();
897
+
898
+ }
899
+
900
+ }
901
+
902
+ function onChange() {
903
+
904
+ scope.setValue( scope.dom.value );
905
+
906
+ }
907
+
908
+ function onFocus() {
909
+
910
+ scope.dom.style.backgroundColor = '';
911
+ scope.dom.style.cursor = '';
912
+
913
+ }
914
+
915
+ function onBlur() {
916
+
917
+ scope.dom.style.backgroundColor = 'transparent';
918
+ scope.dom.style.cursor = 'ns-resize';
919
+
920
+ }
921
+
922
+ function onKeyDown( event ) {
923
+
924
+ event.stopPropagation();
925
+
926
+ switch ( event.code ) {
927
+
928
+ case 'Enter':
929
+ scope.dom.blur();
930
+ break;
931
+
932
+ case 'ArrowUp':
933
+ event.preventDefault();
934
+ scope.setValue( scope.getValue() + scope.nudge );
935
+ scope.dom.dispatchEvent( changeEvent );
936
+ break;
937
+
938
+ case 'ArrowDown':
939
+ event.preventDefault();
940
+ scope.setValue( scope.getValue() - scope.nudge );
941
+ scope.dom.dispatchEvent( changeEvent );
942
+ break;
943
+
944
+ }
945
+
946
+ }
947
+
948
+ onBlur();
949
+
950
+ this.dom.addEventListener( 'keydown', onKeyDown );
951
+ this.dom.addEventListener( 'mousedown', onMouseDown );
952
+ this.dom.addEventListener( 'change', onChange );
953
+ this.dom.addEventListener( 'focus', onFocus );
954
+ this.dom.addEventListener( 'blur', onBlur );
955
+
956
+ }
957
+
958
+ getValue() {
959
+
960
+ return this.value;
961
+
962
+ }
963
+
964
+ setValue( value ) {
965
+
966
+ if ( value !== undefined ) {
967
+
968
+ value = parseInt( value );
969
+
970
+ this.value = value;
971
+ this.dom.value = value;
972
+
973
+ }
974
+
975
+ return this;
976
+
977
+ }
978
+
979
+ setStep( step ) {
980
+
981
+ this.step = parseInt( step );
982
+
983
+ return this;
984
+
985
+ }
986
+
987
+ setNudge( nudge ) {
988
+
989
+ this.nudge = nudge;
990
+
991
+ return this;
992
+
993
+ }
994
+
995
+ setRange( min, max ) {
996
+
997
+ this.min = min;
998
+ this.max = max;
999
+
1000
+ return this;
1001
+
1002
+ }
1003
+
1004
+ }
1005
+
1006
+ class UIBreak extends UIElement {
1007
+
1008
+ constructor() {
1009
+
1010
+ super( document.createElement( 'br' ) );
1011
+
1012
+ this.dom.className = 'Break';
1013
+
1014
+ }
1015
+
1016
+ }
1017
+
1018
+ class UIHorizontalRule extends UIElement {
1019
+
1020
+ constructor() {
1021
+
1022
+ super( document.createElement( 'hr' ) );
1023
+
1024
+ this.dom.className = 'HorizontalRule';
1025
+
1026
+ }
1027
+
1028
+ }
1029
+
1030
+ class UIButton extends UIElement {
1031
+
1032
+ constructor( value ) {
1033
+
1034
+ super( document.createElement( 'button' ) );
1035
+
1036
+ this.dom.className = 'Button';
1037
+ this.dom.textContent = value;
1038
+
1039
+ }
1040
+
1041
+ }
1042
+
1043
+ class UIProgress extends UIElement {
1044
+
1045
+ constructor( value ) {
1046
+
1047
+ super( document.createElement( 'progress' ) );
1048
+
1049
+ this.dom.value = value;
1050
+
1051
+ }
1052
+
1053
+ setValue( value ) {
1054
+
1055
+ this.dom.value = value;
1056
+
1057
+ }
1058
+
1059
+ }
1060
+
1061
+ class UITabbedPanel extends UIDiv {
1062
+
1063
+ constructor() {
1064
+
1065
+ super();
1066
+
1067
+ this.dom.className = 'TabbedPanel';
1068
+
1069
+ this.tabs = [];
1070
+ this.panels = [];
1071
+
1072
+ this.tabsDiv = new UIDiv();
1073
+ this.tabsDiv.setClass( 'Tabs' );
1074
+
1075
+ this.panelsDiv = new UIDiv();
1076
+ this.panelsDiv.setClass( 'Panels' );
1077
+
1078
+ this.add( this.tabsDiv );
1079
+ this.add( this.panelsDiv );
1080
+
1081
+ this.selected = '';
1082
+
1083
+ }
1084
+
1085
+ select( id ) {
1086
+
1087
+ let tab;
1088
+ let panel;
1089
+ const scope = this;
1090
+
1091
+ // Deselect current selection
1092
+ if ( this.selected && this.selected.length ) {
1093
+
1094
+ tab = this.tabs.find( function ( item ) {
1095
+
1096
+ return item.dom.id === scope.selected;
1097
+
1098
+ } );
1099
+ panel = this.panels.find( function ( item ) {
1100
+
1101
+ return item.dom.id === scope.selected;
1102
+
1103
+ } );
1104
+
1105
+ if ( tab ) {
1106
+
1107
+ tab.removeClass( 'selected' );
1108
+
1109
+ }
1110
+
1111
+ if ( panel ) {
1112
+
1113
+ panel.setDisplay( 'none' );
1114
+
1115
+ }
1116
+
1117
+ }
1118
+
1119
+ tab = this.tabs.find( function ( item ) {
1120
+
1121
+ return item.dom.id === id;
1122
+
1123
+ } );
1124
+ panel = this.panels.find( function ( item ) {
1125
+
1126
+ return item.dom.id === id;
1127
+
1128
+ } );
1129
+
1130
+ if ( tab ) {
1131
+
1132
+ tab.addClass( 'selected' );
1133
+
1134
+ }
1135
+
1136
+ if ( panel ) {
1137
+
1138
+ panel.setDisplay( '' );
1139
+
1140
+ }
1141
+
1142
+ this.selected = id;
1143
+
1144
+ // Scrolls to tab
1145
+ if ( tab ) {
1146
+
1147
+ const tabOffsetRight = tab.dom.offsetLeft + tab.dom.offsetWidth;
1148
+ const containerWidth = this.tabsDiv.dom.getBoundingClientRect().width;
1149
+
1150
+ if ( tabOffsetRight > containerWidth ) {
1151
+
1152
+ this.tabsDiv.dom.scrollTo( { left: tabOffsetRight - containerWidth, behavior: 'smooth' } );
1153
+
1154
+ }
1155
+
1156
+ if ( tab.dom.offsetLeft < this.tabsDiv.dom.scrollLeft ) {
1157
+
1158
+ this.tabsDiv.dom.scrollTo( { left: 0, behavior: 'smooth' } );
1159
+
1160
+ }
1161
+
1162
+ }
1163
+
1164
+ return this;
1165
+
1166
+ }
1167
+
1168
+ addTab( id, label, items ) {
1169
+
1170
+ const tab = new UITab( label, this );
1171
+ tab.setId( id );
1172
+ this.tabs.push( tab );
1173
+ this.tabsDiv.add( tab );
1174
+
1175
+ const panel = new UIDiv();
1176
+ panel.setId( id );
1177
+ panel.add( items );
1178
+ panel.setDisplay( 'none' );
1179
+ this.panels.push( panel );
1180
+ this.panelsDiv.add( panel );
1181
+
1182
+ this.select( id );
1183
+
1184
+ }
1185
+
1186
+ }
1187
+
1188
+ class UITab extends UIText {
1189
+
1190
+ constructor( text, parent ) {
1191
+
1192
+ super( text );
1193
+
1194
+ this.dom.className = 'Tab';
1195
+
1196
+ this.parent = parent;
1197
+
1198
+ const scope = this;
1199
+
1200
+ this.dom.addEventListener( 'click', function () {
1201
+
1202
+ scope.parent.select( scope.dom.id );
1203
+
1204
+ } );
1205
+
1206
+ }
1207
+
1208
+ }
1209
+
1210
+ class UIListbox extends UIDiv {
1211
+
1212
+ constructor() {
1213
+
1214
+ super();
1215
+
1216
+ this.dom.className = 'Listbox';
1217
+ this.dom.tabIndex = 0;
1218
+
1219
+ this.items = [];
1220
+ this.listitems = [];
1221
+ this.selectedIndex = 0;
1222
+ this.selectedValue = null;
1223
+
1224
+ }
1225
+
1226
+ setItems( items ) {
1227
+
1228
+ if ( Array.isArray( items ) ) {
1229
+
1230
+ this.items = items;
1231
+
1232
+ }
1233
+
1234
+ this.render();
1235
+
1236
+ }
1237
+
1238
+ render( ) {
1239
+
1240
+ while ( this.listitems.length ) {
1241
+
1242
+ const item = this.listitems[ 0 ];
1243
+
1244
+ item.dom.remove();
1245
+
1246
+ this.listitems.splice( 0, 1 );
1247
+
1248
+ }
1249
+
1250
+ for ( let i = 0; i < this.items.length; i ++ ) {
1251
+
1252
+ const item = this.items[ i ];
1253
+
1254
+ const listitem = new ListboxItem( this );
1255
+ listitem.setId( item.id || `Listbox-${i}` );
1256
+ listitem.setTextContent( item.name || item.type );
1257
+ this.add( listitem );
1258
+
1259
+ }
1260
+
1261
+ }
1262
+
1263
+ add() {
1264
+
1265
+ const items = Array.from( arguments );
1266
+
1267
+ this.listitems = this.listitems.concat( items );
1268
+
1269
+ UIElement.prototype.add.apply( this, items );
1270
+
1271
+ }
1272
+
1273
+ selectIndex( index ) {
1274
+
1275
+ if ( index >= 0 && index < this.items.length ) {
1276
+
1277
+ this.setValue( this.listitems[ index ].getId() );
1278
+
1279
+ }
1280
+
1281
+ this.selectedIndex = index;
1282
+
1283
+ }
1284
+
1285
+ getValue() {
1286
+
1287
+ return this.selectedValue;
1288
+
1289
+ }
1290
+
1291
+ setValue( value ) {
1292
+
1293
+ for ( let i = 0; i < this.listitems.length; i ++ ) {
1294
+
1295
+ const element = this.listitems[ i ];
1296
+
1297
+ if ( element.getId() === value ) {
1298
+
1299
+ element.addClass( 'active' );
1300
+
1301
+ } else {
1302
+
1303
+ element.removeClass( 'active' );
1304
+
1305
+ }
1306
+
1307
+ }
1308
+
1309
+ this.selectedValue = value;
1310
+
1311
+ const changeEvent = new Event( 'change', { bubbles: true, cancelable: true } );
1312
+ this.dom.dispatchEvent( changeEvent );
1313
+
1314
+ }
1315
+
1316
+ }
1317
+
1318
+ class ListboxItem extends UIDiv {
1319
+
1320
+ constructor( parent ) {
1321
+
1322
+ super();
1323
+
1324
+ this.dom.className = 'ListboxItem';
1325
+
1326
+ this.parent = parent;
1327
+
1328
+ const scope = this;
1329
+
1330
+ function onClick() {
1331
+
1332
+ if ( scope.parent ) {
1333
+
1334
+ scope.parent.setValue( scope.getId( ) );
1335
+
1336
+ }
1337
+
1338
+ }
1339
+
1340
+ this.dom.addEventListener( 'click', onClick );
1341
+
1342
+ }
1343
+
1344
+ }
1345
+
1346
+ export { UIElement, UISpan, UIDiv, UIRow, UIPanel, UIText, UIInput, UITextArea, UISelect, UICheckbox, UIColor, UINumber, UIInteger, UIBreak, UIHorizontalRule, UIButton, UIProgress, UITabbedPanel, UIListbox, ListboxItem };