perfect-gui 2.6.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -25
- package/package.json +1 -1
- package/src/index.js +162 -17
- package/src/styles.js +53 -2
- package/test/src/index.html +139 -41
- package/test/src/index.js +7 -2
- package/test/src/js/basics.js +25 -12
- package/test/src/js/folders.js +4 -4
- package/test/src/js/full_featured.js +14 -14
- package/test/src/js/kill_create.js +36 -0
- package/test/src/js/multiple.js +9 -9
- package/test/src/js/other.js +12 -10
- package/test/src/js/vectors.js +27 -0
- package/test/src/styles/main.scss +18 -1
- package/test/webpack.config.js +0 -1
- package/test/build/bundle.js +0 -1
- package/test/build/index.html +0 -162
- package/test/build/main.css +0 -91
package/README.md
CHANGED
|
@@ -19,24 +19,21 @@ https://thibka.github.io/perfect-gui/public/
|
|
|
19
19
|
npm i perfect-gui
|
|
20
20
|
```
|
|
21
21
|
```javascript
|
|
22
|
-
import
|
|
22
|
+
import GUI from 'perfect-gui';
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Usage
|
|
26
26
|
|
|
27
27
|
```javascript
|
|
28
|
-
const gui = new
|
|
28
|
+
const gui = new GUI();
|
|
29
29
|
|
|
30
|
-
gui.
|
|
30
|
+
gui.button('Click me', callback);
|
|
31
31
|
|
|
32
|
-
function doSomething() {
|
|
33
|
-
// ...
|
|
34
|
-
}
|
|
35
32
|
```
|
|
36
33
|
|
|
37
34
|
## Options
|
|
38
35
|
```javascript
|
|
39
|
-
const gui = new
|
|
36
|
+
const gui = new GUI({
|
|
40
37
|
name: 'My GUI',
|
|
41
38
|
// Name of the panel.
|
|
42
39
|
// Default is null.
|
|
@@ -50,14 +47,14 @@ const gui = new perfectGUI({
|
|
|
50
47
|
// Default is 290.
|
|
51
48
|
|
|
52
49
|
closed: false,
|
|
53
|
-
// Defines whether the panel should be open or closed
|
|
50
|
+
// Defines whether the panel should be open or closed by default.
|
|
54
51
|
// Default is false (open).
|
|
55
52
|
|
|
56
53
|
position: 'bottom right',
|
|
57
54
|
// Defines where to place the panel on screen.
|
|
58
55
|
// Accepted values are 'top', 'bottom', 'left' and 'right'
|
|
59
56
|
// in no particular order ('bottom right' = 'right bottom').
|
|
60
|
-
// If multiple instances have the same position, they will
|
|
57
|
+
// If multiple instances have the same position, they will be stacked horizontally.
|
|
61
58
|
// Default is 'top left'.
|
|
62
59
|
|
|
63
60
|
draggable: false,
|
|
@@ -74,53 +71,67 @@ const gui = new perfectGUI({
|
|
|
74
71
|
## Methods
|
|
75
72
|
<table>
|
|
76
73
|
<tr><th>Method</th><th>Example</th></tr>
|
|
77
|
-
<tr><td>
|
|
74
|
+
<tr><td>button</td><td>
|
|
78
75
|
|
|
79
76
|
```javascript
|
|
80
|
-
gui.
|
|
77
|
+
gui.button('Click me!', () => {
|
|
81
78
|
...
|
|
82
79
|
});
|
|
83
80
|
```
|
|
84
81
|
</td></tr>
|
|
85
|
-
<tr><td>
|
|
82
|
+
<tr><td>image</td><td>
|
|
86
83
|
|
|
87
84
|
```javascript
|
|
88
|
-
gui.
|
|
85
|
+
gui.image('Click this', 'path/to/image', () => {
|
|
89
86
|
...
|
|
90
87
|
});
|
|
91
88
|
```
|
|
92
89
|
</td></tr>
|
|
93
|
-
<tr><td>
|
|
90
|
+
<tr><td>slider</td><td>
|
|
94
91
|
|
|
95
92
|
```javascript
|
|
96
|
-
|
|
93
|
+
// Simple slider, only returns a value to the callback
|
|
94
|
+
gui.slider('Slide this', { value: 5, min: 0, max: 10, step: .1 }, value => {
|
|
97
95
|
console.log('Slider value : ' + value);
|
|
98
96
|
});
|
|
97
|
+
|
|
98
|
+
// Object-based slider, automatically updates the value of the object property.
|
|
99
|
+
// Directly updating the property will also update the slider.
|
|
100
|
+
gui.slider('Slide this', { object: foo, prop: 'bar', min: 0, max: 10, step: .1 });
|
|
99
101
|
```
|
|
100
102
|
</td></tr>
|
|
101
|
-
<tr><td>
|
|
103
|
+
<tr><td>toggle</td><td>
|
|
102
104
|
|
|
103
105
|
```javascript
|
|
104
|
-
gui.
|
|
105
|
-
console.log('
|
|
106
|
+
gui.toggle('Toggle me!', true, state => {
|
|
107
|
+
console.log('Toggle boolean value: ' + state);
|
|
106
108
|
});
|
|
107
109
|
```
|
|
108
110
|
</td></tr>
|
|
109
|
-
<tr><td>
|
|
111
|
+
<tr><td>list</td><td>
|
|
110
112
|
|
|
111
113
|
```javascript
|
|
112
|
-
gui.
|
|
114
|
+
gui.list('Select one', ['apple', 'lime', 'peach'], function(item) {
|
|
113
115
|
console.log('Selected item: ' + item);
|
|
114
116
|
});
|
|
115
117
|
```
|
|
116
118
|
</td></tr>
|
|
117
|
-
<tr><td>
|
|
119
|
+
<tr><td>vector2</td><td>
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
let folder = gui.vector2('Position', {
|
|
123
|
+
x: { object: myObject.position, prop: 'x', min: -10, max: 10 },
|
|
124
|
+
y: { object: myObject.position, prop: 'y', min: -10, max: 10 },
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
</td></tr>
|
|
128
|
+
<tr><td>folder</td><td>
|
|
118
129
|
|
|
119
130
|
```javascript
|
|
120
|
-
let folder = gui.
|
|
131
|
+
let folder = gui.folder('folder name', {
|
|
121
132
|
closed: false // default is false
|
|
122
133
|
});
|
|
123
|
-
folder.
|
|
134
|
+
folder.button('click me!', callback);
|
|
124
135
|
```
|
|
125
136
|
</td></tr>
|
|
126
137
|
<tr><td>toggleClose</td><td>
|
|
@@ -134,5 +145,4 @@ gui.toggleClose();
|
|
|
134
145
|
|
|
135
146
|
## To do
|
|
136
147
|
- Adding scrollbars if window is too short
|
|
137
|
-
- Adding color palette component
|
|
138
|
-
- Adding object binding
|
|
148
|
+
- Adding color palette component
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -17,9 +17,13 @@ export default class GUI {
|
|
|
17
17
|
|
|
18
18
|
this.name = (options != undefined && typeof options.name == "string") ? options.name : '';
|
|
19
19
|
|
|
20
|
-
if (this instanceof GUI) {
|
|
21
|
-
if (typeof GUI[GUI.instanceCounter] != 'number')
|
|
22
|
-
|
|
20
|
+
if ( this instanceof GUI ) {
|
|
21
|
+
if ( typeof GUI[GUI.instanceCounter] != 'number' ) {
|
|
22
|
+
GUI[GUI.instanceCounter] = 0;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
GUI[GUI.instanceCounter]++;
|
|
26
|
+
}
|
|
23
27
|
}
|
|
24
28
|
this.instanceId = GUI[GUI.instanceCounter];
|
|
25
29
|
|
|
@@ -30,7 +34,9 @@ export default class GUI {
|
|
|
30
34
|
document.head.append(this.stylesheet);
|
|
31
35
|
|
|
32
36
|
// Common styles
|
|
33
|
-
if (this.instanceId == 0)
|
|
37
|
+
if (this.instanceId == 0) {
|
|
38
|
+
this._addStyles(`${styles(this.position_type)}`);
|
|
39
|
+
}
|
|
34
40
|
|
|
35
41
|
// Instance styles
|
|
36
42
|
this.screenCorner = this._parseScreenCorner(options.position);
|
|
@@ -71,6 +77,8 @@ export default class GUI {
|
|
|
71
77
|
if (options.closed) this.toggleClose();
|
|
72
78
|
|
|
73
79
|
this.folders = [];
|
|
80
|
+
|
|
81
|
+
this.propReferences = [];
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
_folderConstructor(folderOptions) {
|
|
@@ -158,7 +166,7 @@ export default class GUI {
|
|
|
158
166
|
});
|
|
159
167
|
}
|
|
160
168
|
|
|
161
|
-
|
|
169
|
+
button(text, callback) {
|
|
162
170
|
let params = {
|
|
163
171
|
text: text,
|
|
164
172
|
callback: callback
|
|
@@ -177,7 +185,7 @@ export default class GUI {
|
|
|
177
185
|
})
|
|
178
186
|
}
|
|
179
187
|
|
|
180
|
-
|
|
188
|
+
image(text, path, callback) {
|
|
181
189
|
let params = {
|
|
182
190
|
text: text,
|
|
183
191
|
path: path,
|
|
@@ -212,14 +220,34 @@ export default class GUI {
|
|
|
212
220
|
image.onclick = () => params.callback({ path: params.path, text: params.text });
|
|
213
221
|
}
|
|
214
222
|
|
|
215
|
-
|
|
223
|
+
slider (text, sliderParams, callback) {
|
|
216
224
|
this._checkMandatoryParams({
|
|
217
225
|
min: 'number',
|
|
218
226
|
max: 'number',
|
|
219
|
-
value: 'number',
|
|
220
227
|
step: 'number'
|
|
221
228
|
}, sliderParams);
|
|
222
229
|
|
|
230
|
+
let isObject = false;
|
|
231
|
+
let propReferenceIndex = null;
|
|
232
|
+
let object;
|
|
233
|
+
let prop;
|
|
234
|
+
|
|
235
|
+
if ( sliderParams.value ) {
|
|
236
|
+
this._checkMandatoryParams({
|
|
237
|
+
value: 'number'
|
|
238
|
+
}, sliderParams);
|
|
239
|
+
} else {
|
|
240
|
+
this._checkMandatoryParams({
|
|
241
|
+
object: 'object',
|
|
242
|
+
prop: 'string'
|
|
243
|
+
}, sliderParams);
|
|
244
|
+
|
|
245
|
+
object = sliderParams.object;
|
|
246
|
+
prop = sliderParams.prop;
|
|
247
|
+
propReferenceIndex = this.propReferences.push(object[prop]) - 1;
|
|
248
|
+
isObject = true;
|
|
249
|
+
}
|
|
250
|
+
|
|
223
251
|
this.imageContainer = null;
|
|
224
252
|
|
|
225
253
|
var container = this._createElement({
|
|
@@ -227,7 +255,7 @@ export default class GUI {
|
|
|
227
255
|
textContent: text
|
|
228
256
|
});
|
|
229
257
|
|
|
230
|
-
var
|
|
258
|
+
var slider_ctrl = this._createElement({
|
|
231
259
|
parent: container,
|
|
232
260
|
el: 'input',
|
|
233
261
|
class: 'p-gui__slider-ctrl',
|
|
@@ -240,19 +268,39 @@ export default class GUI {
|
|
|
240
268
|
}
|
|
241
269
|
});
|
|
242
270
|
|
|
243
|
-
var
|
|
271
|
+
var slider_value = this._createElement({
|
|
244
272
|
parent: container,
|
|
245
273
|
class: 'p-gui__slider-value',
|
|
246
|
-
textContent: sliderParams.value
|
|
274
|
+
textContent: isObject ? String(object[prop]) : sliderParams.value
|
|
247
275
|
});
|
|
248
276
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
277
|
+
slider_ctrl.addEventListener('input', () => {
|
|
278
|
+
slider_value.textContent = slider_ctrl.value;
|
|
279
|
+
|
|
280
|
+
if ( isObject ) {
|
|
281
|
+
object[prop] = slider_ctrl.value;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (typeof callback == "function") {
|
|
285
|
+
callback(slider_ctrl.value);
|
|
286
|
+
}
|
|
252
287
|
});
|
|
288
|
+
|
|
289
|
+
if ( isObject ) {
|
|
290
|
+
Object.defineProperty( object, prop, {
|
|
291
|
+
set: val => {
|
|
292
|
+
this.propReferences[propReferenceIndex] = val;
|
|
293
|
+
slider_ctrl.value = val;
|
|
294
|
+
slider_value.textContent = String( val );
|
|
295
|
+
},
|
|
296
|
+
get: () => {
|
|
297
|
+
return this.propReferences[propReferenceIndex];
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
}
|
|
253
301
|
}
|
|
254
302
|
|
|
255
|
-
|
|
303
|
+
toggle(text, state, callback) {
|
|
256
304
|
let params = {
|
|
257
305
|
text: text,
|
|
258
306
|
state: state,
|
|
@@ -288,7 +336,7 @@ export default class GUI {
|
|
|
288
336
|
});
|
|
289
337
|
}
|
|
290
338
|
|
|
291
|
-
|
|
339
|
+
list(text, list, callback) {
|
|
292
340
|
let params = {
|
|
293
341
|
text: text,
|
|
294
342
|
list: list,
|
|
@@ -328,7 +376,96 @@ export default class GUI {
|
|
|
328
376
|
});
|
|
329
377
|
}
|
|
330
378
|
|
|
331
|
-
|
|
379
|
+
vector2(text, data, callback) {
|
|
380
|
+
this._checkMandatoryParams({
|
|
381
|
+
text: 'string',
|
|
382
|
+
data: 'object',
|
|
383
|
+
minX: 'number',
|
|
384
|
+
maxX: 'number',
|
|
385
|
+
minY: 'number',
|
|
386
|
+
maxY: 'number',
|
|
387
|
+
}, {
|
|
388
|
+
text,
|
|
389
|
+
data,
|
|
390
|
+
minX: data.x.min,
|
|
391
|
+
maxX: data.x.max,
|
|
392
|
+
minY: data.y.min,
|
|
393
|
+
maxY: data.y.max,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const objectX = data.x.object;
|
|
397
|
+
const propX = data.x.prop;
|
|
398
|
+
const propXReferenceIndex = this.propReferences.push(objectX[propX]) - 1;
|
|
399
|
+
|
|
400
|
+
const objectY = data.y.object;
|
|
401
|
+
const propY = data.y.prop;
|
|
402
|
+
const propYReferenceIndex = this.propReferences.push(objectY[propY]) - 1;
|
|
403
|
+
|
|
404
|
+
this.imageContainer = null;
|
|
405
|
+
|
|
406
|
+
const container = this._createElement({
|
|
407
|
+
class: 'p-gui__vector2',
|
|
408
|
+
textContent: text
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const vector_value = this._createElement({
|
|
412
|
+
parent: container,
|
|
413
|
+
class: 'p-gui__vector-value',
|
|
414
|
+
textContent: objectX[propX] + ', ' + objectY[propY]
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const area = this._createElement({
|
|
418
|
+
parent: container,
|
|
419
|
+
el: 'div',
|
|
420
|
+
class: 'p-gui__vector2-area',
|
|
421
|
+
onclick: (evt) => {
|
|
422
|
+
objectX[propX] = parseFloat(this._mapLinear(evt.offsetX, 0, area.clientWidth, data.x.min, data.x.max).toFixed(1));
|
|
423
|
+
objectY[propY] = parseFloat(this._mapLinear(evt.offsetY, 0, area.clientHeight, data.y.max, data.y.min).toFixed(1));
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
this._createElement({
|
|
428
|
+
parent: area,
|
|
429
|
+
class: 'p-gui__vector2-line p-gui__vector2-line-x'
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
this._createElement({
|
|
433
|
+
parent: area,
|
|
434
|
+
class: 'p-gui__vector2-line p-gui__vector2-line-y'
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
const dot = this._createElement({
|
|
438
|
+
parent: area,
|
|
439
|
+
class: 'p-gui__vector2-dot'
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
dot.style.left = this._mapLinear(objectX[propX], data.x.min, data.x.max, 0, area.clientWidth) + 'px';
|
|
443
|
+
dot.style.top = this._mapLinear(objectY[propY], data.y.min, data.y.max, area.clientHeight, 0) + 'px';
|
|
444
|
+
|
|
445
|
+
Object.defineProperty( objectX, propX, {
|
|
446
|
+
set: val => {
|
|
447
|
+
this.propReferences[propXReferenceIndex] = val;
|
|
448
|
+
dot.style.left = this._mapLinear(val, data.x.min, data.x.max, 0, area.clientWidth) + 'px';
|
|
449
|
+
vector_value.textContent = String( val ) + ', ' + objectY[propY];
|
|
450
|
+
},
|
|
451
|
+
get: () => {
|
|
452
|
+
return this.propReferences[propXReferenceIndex];
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
Object.defineProperty( objectY, propY, {
|
|
457
|
+
set: val => {
|
|
458
|
+
this.propReferences[propYReferenceIndex] = val;
|
|
459
|
+
dot.style.top = this._mapLinear(val, data.y.min, data.y.max, area.clientHeight, 0) + 'px';
|
|
460
|
+
vector_value.textContent = objectX[propX] + ', ' + String( val );
|
|
461
|
+
},
|
|
462
|
+
get: () => {
|
|
463
|
+
return this.propReferences[propYReferenceIndex];
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
folder(name, options = {}) {
|
|
332
469
|
let closed = typeof options.closed == 'boolean' ? options.closed : false;
|
|
333
470
|
|
|
334
471
|
let params = {
|
|
@@ -419,4 +556,12 @@ export default class GUI {
|
|
|
419
556
|
this.closed = !this.closed;
|
|
420
557
|
this.wrapper.classList.toggle('p-gui--collapsed');
|
|
421
558
|
}
|
|
559
|
+
|
|
560
|
+
kill() {
|
|
561
|
+
this.wrapper.remove();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
_mapLinear( x, a1, a2, b1, b2 ) {
|
|
565
|
+
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
|
|
566
|
+
}
|
|
422
567
|
}
|
package/src/styles.js
CHANGED
|
@@ -89,7 +89,8 @@ return /* css */`
|
|
|
89
89
|
|
|
90
90
|
.p-gui__button,
|
|
91
91
|
.p-gui__switch,
|
|
92
|
-
.p-gui__list
|
|
92
|
+
.p-gui__list,
|
|
93
|
+
.p-gui__vector2 {
|
|
93
94
|
width: 100%;
|
|
94
95
|
margin: 3px;
|
|
95
96
|
padding: 7px;
|
|
@@ -102,6 +103,55 @@ return /* css */`
|
|
|
102
103
|
box-sizing: border-box;
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
.p-gui__vector2 {
|
|
107
|
+
border-bottom: 1px solid #ff9999;
|
|
108
|
+
aspect-ratio: 1;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.p-gui__vector2-area {
|
|
112
|
+
position: relative;
|
|
113
|
+
background: black;
|
|
114
|
+
margin-top: 11px;
|
|
115
|
+
width: 100%;
|
|
116
|
+
height: calc(100% - 33px);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.p-gui__vector2-line {
|
|
120
|
+
position: absolute;
|
|
121
|
+
background: white;
|
|
122
|
+
opacity: .3;
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.p-gui__vector2-line-x {
|
|
127
|
+
width: 100%;
|
|
128
|
+
height: 1px;
|
|
129
|
+
left: 0;
|
|
130
|
+
top: 50%;
|
|
131
|
+
transform: translateY(-50%);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.p-gui__vector2-line-y {
|
|
135
|
+
width: 1px;
|
|
136
|
+
height: 100%;
|
|
137
|
+
top: 0;
|
|
138
|
+
left: 50%;
|
|
139
|
+
transform: translateX(-50%);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.p-gui__vector2-dot {
|
|
143
|
+
position: absolute;
|
|
144
|
+
top: 0;
|
|
145
|
+
left: 0;
|
|
146
|
+
width: 8px;
|
|
147
|
+
height: 8px;
|
|
148
|
+
border-radius: 50%;
|
|
149
|
+
background: #d5d5d5;
|
|
150
|
+
border: 2px solid #ff9999;
|
|
151
|
+
transform: translate(-50%, -50%);
|
|
152
|
+
pointer-events: none;
|
|
153
|
+
}
|
|
154
|
+
|
|
105
155
|
.p-gui__list {
|
|
106
156
|
cursor: default;
|
|
107
157
|
}
|
|
@@ -185,7 +235,8 @@ return /* css */`
|
|
|
185
235
|
border: 2px solid #00a1ff;
|
|
186
236
|
}
|
|
187
237
|
|
|
188
|
-
.p-gui__slider-value
|
|
238
|
+
.p-gui__slider-value,
|
|
239
|
+
.p-gui__vector-value {
|
|
189
240
|
display: inline-block;
|
|
190
241
|
position: absolute;
|
|
191
242
|
right: 7px;
|