lexgui 0.1.36 → 0.1.37

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.
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  var LX = {
11
- version: "0.1.36",
11
+ version: "0.1.37",
12
12
  ready: false,
13
13
  components: [], // specific pre-build components
14
14
  signals: {} // events and triggers
@@ -25,7 +25,10 @@ LX.CURVE_MOVEOUT_CLAMP = 0;
25
25
  LX.CURVE_MOVEOUT_DELETE = 1;
26
26
 
27
27
  function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
28
- function round( num, n ) { return +num.toFixed( n ); }
28
+ function round( number, precision ) { return +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
29
+
30
+ LX.clamp = clamp;
31
+ LX.round = round;
29
32
 
30
33
  function getSupportedDOMName( string )
31
34
  {
@@ -109,6 +112,8 @@ function simple_guidGenerator() {
109
112
  return (S4()+"-"+S4()+"-"+S4());
110
113
  }
111
114
 
115
+ LX.guidGenerator = simple_guidGenerator;
116
+
112
117
  // Timer that works everywhere (from litegraph.js)
113
118
  if (typeof performance != "undefined") {
114
119
  LX.getTime = performance.now.bind(performance);
@@ -300,11 +305,18 @@ function create_global_searchbar( root ) {
300
305
  else
301
306
  {
302
307
  for( let c of LX.components )
303
- if( LX[c].prototype.onKeyPressed )
308
+ {
309
+ if( !LX[c] || !LX[c].prototype.onKeyPressed )
304
310
  {
305
- const instances = LX.CodeEditor.getInstances();
306
- for( let i of instances ) i.onKeyPressed( e );
311
+ continue;
307
312
  }
313
+
314
+ const instances = LX.CodeEditor.getInstances();
315
+ for( let i of instances )
316
+ {
317
+ i.onKeyPressed( e );
318
+ }
319
+ }
308
320
  }
309
321
  });
310
322
 
@@ -631,6 +643,8 @@ class IEvent {
631
643
  }
632
644
  };
633
645
 
646
+ LX.IEvent = IEvent;
647
+
634
648
  class TreeEvent {
635
649
 
636
650
  static NONE = 0;
@@ -2448,6 +2462,7 @@ class Widget {
2448
2462
  static CONTENT = 20;
2449
2463
  static CUSTOM = 21;
2450
2464
  static SEPARATOR = 22;
2465
+ static KNOB = 23;
2451
2466
 
2452
2467
  static NO_CONTEXT_TYPES = [
2453
2468
  Widget.BUTTON,
@@ -2456,7 +2471,7 @@ class Widget {
2456
2471
  Widget.PROGRESS
2457
2472
  ];
2458
2473
 
2459
- constructor(name, type, options) {
2474
+ constructor( name, type, options ) {
2460
2475
  this.name = name;
2461
2476
  this.type = type;
2462
2477
  this.options = options;
@@ -2464,10 +2479,12 @@ class Widget {
2464
2479
 
2465
2480
  value() {
2466
2481
 
2467
- if(this.onGetValue)
2482
+ if( this.onGetValue )
2483
+ {
2468
2484
  return this.onGetValue();
2485
+ }
2469
2486
 
2470
- console.warn("Can't get value of " + this.typeName());
2487
+ console.warn( "Can't get value of " + this.typeName() );
2471
2488
  }
2472
2489
 
2473
2490
  set( value, skipCallback = false, signalName = "" ) {
@@ -2527,6 +2544,7 @@ class Widget {
2527
2544
  case Widget.LIST: return "List";
2528
2545
  case Widget.TAGS: return "Tags";
2529
2546
  case Widget.CURVE: return "Curve";
2547
+ case Widget.KNOB: return "Knob";
2530
2548
  case Widget.CUSTOM: return this.customName;
2531
2549
  }
2532
2550
  }
@@ -5084,6 +5102,7 @@ class Panel {
5084
5102
  * precision: The number of digits to appear after the decimal point
5085
5103
  * min, max: Min and Max values for the input
5086
5104
  * skipSlider: If there are min and max values, skip the slider
5105
+ * units: Unit as string added to the end of the value
5087
5106
  */
5088
5107
 
5089
5108
  addNumber( name, value, callback, options = {} ) {
@@ -5094,7 +5113,7 @@ class Panel {
5094
5113
  return +vecinput.value;
5095
5114
  };
5096
5115
  widget.onSetValue = ( newValue, skipCallback ) => {
5097
- vecinput.value = newValue;
5116
+ vecinput.value = round( newValue, options.precision );
5098
5117
  Panel._dispatch_event( vecinput, "change", skipCallback );
5099
5118
  };
5100
5119
 
@@ -5119,27 +5138,48 @@ class Panel {
5119
5138
  box.className = "numberbox";
5120
5139
 
5121
5140
  let vecinput = document.createElement( 'input' );
5141
+ vecinput.id = "number_" + simple_guidGenerator();
5122
5142
  vecinput.className = "vecinput";
5123
5143
  vecinput.min = options.min ?? -1e24;
5124
5144
  vecinput.max = options.max ?? 1e24;
5125
5145
  vecinput.step = options.step ?? "any";
5126
5146
  vecinput.type = "number";
5127
- vecinput.id = "number_" + simple_guidGenerator();
5128
5147
 
5129
5148
  if( value.constructor == Number )
5130
5149
  {
5131
5150
  value = clamp( value, +vecinput.min, +vecinput.max );
5132
- value = options.precision ? round( value, options.precision ) : value;
5151
+ value = round( value, options.precision );
5133
5152
  }
5134
5153
 
5135
5154
  vecinput.value = vecinput.iValue = value;
5136
5155
  box.appendChild( vecinput );
5137
5156
 
5138
- let drag_icon = document.createElement( 'a' );
5139
- drag_icon.className = "fa-solid fa-arrows-up-down drag-icon hidden";
5140
- box.appendChild( drag_icon );
5157
+ let measureRealWidth = function( value, paddingPlusMargin = 8 ) {
5158
+ var i = document.createElement( "span" );
5159
+ i.className = "lexinputmeasure";
5160
+ i.innerHTML = value;
5161
+ document.body.appendChild( i );
5162
+ var rect = i.getBoundingClientRect();
5163
+ LX.UTILS.deleteElement( i );
5164
+ return rect.width + paddingPlusMargin;
5165
+ }
5141
5166
 
5142
- if( options.disabled ) {
5167
+ if( options.units )
5168
+ {
5169
+ let unitSpan = document.createElement( 'span' );
5170
+ unitSpan.className = "lexunit";
5171
+ unitSpan.innerText = options.units;
5172
+ unitSpan.style.left = measureRealWidth( vecinput.value ) + "px";
5173
+ vecinput.unitSpan = unitSpan;
5174
+ box.appendChild( unitSpan );
5175
+ }
5176
+
5177
+ let dragIcon = document.createElement( 'a' );
5178
+ dragIcon.className = "fa-solid fa-arrows-up-down drag-icon hidden";
5179
+ box.appendChild( dragIcon );
5180
+
5181
+ if( options.disabled )
5182
+ {
5143
5183
  vecinput.disabled = true;
5144
5184
  }
5145
5185
 
@@ -5154,7 +5194,7 @@ class Panel {
5154
5194
  slider.value = value;
5155
5195
  slider.addEventListener( "input", function( e ) {
5156
5196
  let new_value = +this.valueAsNumber;
5157
- vecinput.value = ( +new_value ).toFixed( 4 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' );
5197
+ vecinput.value = round( new_value, options.precision );
5158
5198
  Panel._dispatch_event( vecinput, "change" );
5159
5199
  }, false );
5160
5200
  box.appendChild( slider );
@@ -5170,7 +5210,7 @@ class Panel {
5170
5210
  if( e.shiftKey ) mult *= 10;
5171
5211
  else if( e.altKey ) mult *= 0.1;
5172
5212
  let new_value = ( +this.valueAsNumber - mult * ( e.deltaY > 0 ? 1 : -1 ) );
5173
- this.value = ( +new_value ).toFixed( 4 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' );
5213
+ this.value = round( new_value, options.precision );
5174
5214
  Panel._dispatch_event(vecinput, "change");
5175
5215
  }, { passive: false });
5176
5216
 
@@ -5183,12 +5223,20 @@ class Panel {
5183
5223
 
5184
5224
  let val = e.target.value = clamp( +e.target.valueAsNumber, +vecinput.min, +vecinput.max );
5185
5225
  val = options.precision ? round( val, options.precision ) : val;
5186
- // update slider!
5226
+
5227
+ // Update slider!
5187
5228
  if( box.querySelector( ".lexinputslider" ) )
5229
+ {
5188
5230
  box.querySelector( ".lexinputslider" ).value = val;
5231
+ }
5189
5232
 
5190
5233
  vecinput.value = val;
5191
5234
 
5235
+ if( options.units )
5236
+ {
5237
+ vecinput.unitSpan.style.left = measureRealWidth( vecinput.value ) + "px";
5238
+ }
5239
+
5192
5240
  // Reset button (default value)
5193
5241
  if( !skipCallback )
5194
5242
  {
@@ -5213,7 +5261,7 @@ class Panel {
5213
5261
  lastY = e.pageY;
5214
5262
  document.body.classList.add('nocursor');
5215
5263
  document.body.classList.add('noevents');
5216
- drag_icon.classList.remove('hidden');
5264
+ dragIcon.classList.remove('hidden');
5217
5265
  e.stopImmediatePropagation();
5218
5266
  e.stopPropagation();
5219
5267
  }
@@ -5225,8 +5273,8 @@ class Panel {
5225
5273
  if(e.shiftKey) mult *= 10;
5226
5274
  else if(e.altKey) mult *= 0.1;
5227
5275
  let new_value = (+vecinput.valueAsNumber + mult * dt);
5228
- vecinput.value = (+new_value).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1');
5229
- Panel._dispatch_event(vecinput, "change");
5276
+ vecinput.value = (+new_value).toFixed( 4 ).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1');
5277
+ Panel._dispatch_event( vecinput, "change" );
5230
5278
  }
5231
5279
 
5232
5280
  lastY = e.pageY;
@@ -5240,7 +5288,7 @@ class Panel {
5240
5288
  doc.removeEventListener("mouseup",inner_mouseup);
5241
5289
  document.body.classList.remove('nocursor');
5242
5290
  document.body.classList.remove('noevents');
5243
- drag_icon.classList.add('hidden');
5291
+ dragIcon.classList.add('hidden');
5244
5292
  }
5245
5293
 
5246
5294
  container.appendChild(box);
@@ -5277,9 +5325,15 @@ class Panel {
5277
5325
  };
5278
5326
  widget.onSetValue = ( newValue, skipCallback ) => {
5279
5327
  const inputs = element.querySelectorAll( ".vecinput" );
5328
+ if( inputs.length == newValue.length )
5329
+ {
5330
+ console.error( "Input length does not match vector length." );
5331
+ return;
5332
+ }
5333
+
5280
5334
  for( var i = 0; i < inputs.length; ++i ) {
5281
5335
  let value = newValue[ i ];
5282
- inputs[ i ].value = value ?? 0;
5336
+ inputs[ i ].value = round( value, options.precision ) ?? 0;
5283
5337
  Panel._dispatch_event( inputs[ i ], "change", skipCallback );
5284
5338
  }
5285
5339
  };
@@ -5319,14 +5373,14 @@ class Panel {
5319
5373
  if( value[ i ].constructor == Number )
5320
5374
  {
5321
5375
  value[ i ] = clamp(value[ i ], +vecinput.min, +vecinput.max);
5322
- value[ i ] = options.precision ? round(value[ i ], options.precision) : value[ i ];
5376
+ value[ i ] = round( value[ i ], options.precision );
5323
5377
  }
5324
5378
 
5325
5379
  vecinput.value = vecinput.iValue = value[ i ];
5326
5380
 
5327
- let drag_icon = document.createElement( 'a' );
5328
- drag_icon.className = "fa-solid fa-arrows-up-down drag-icon hidden";
5329
- box.appendChild( drag_icon );
5381
+ let dragIcon = document.createElement( 'a' );
5382
+ dragIcon.className = "fa-solid fa-arrows-up-down drag-icon hidden";
5383
+ box.appendChild( dragIcon );
5330
5384
 
5331
5385
  if( options.disabled ) {
5332
5386
  vecinput.disabled = true;
@@ -5342,14 +5396,17 @@ class Panel {
5342
5396
  if( e.shiftKey ) mult = 10;
5343
5397
  else if( e.altKey ) mult = 0.1;
5344
5398
 
5345
- if( lock_icon.locked )
5399
+ if( locker.locked )
5346
5400
  {
5347
- for( let v of element.querySelectorAll(".vecinput") ) {
5348
- v.value = ( +v.valueAsNumber - mult * ( e.deltaY > 0 ? 1 : -1 ) ).toPrecision( 5 );
5401
+ for( let v of element.querySelectorAll(".vecinput") )
5402
+ {
5403
+ v.value = round( +v.valueAsNumber - mult * ( e.deltaY > 0 ? 1 : -1 ), options.precision );
5349
5404
  Panel._dispatch_event(v, "change");
5350
5405
  }
5351
- } else {
5352
- this.value = ( +this.valueAsNumber - mult * ( e.deltaY > 0 ? 1 : -1 ) ).toPrecision( 5 );
5406
+ }
5407
+ else
5408
+ {
5409
+ this.value = round( +this.valueAsNumber - mult * ( e.deltaY > 0 ? 1 : -1 ), options.precision );
5353
5410
  Panel._dispatch_event( vecinput, "change" );
5354
5411
  }
5355
5412
  }, { passive: false } );
@@ -5362,7 +5419,7 @@ class Panel {
5362
5419
  const skipCallback = e.detail;
5363
5420
 
5364
5421
  let val = e.target.value = clamp( e.target.value, +vecinput.min, +vecinput.max );
5365
- val = options.precision ? round( val, options.precision ) : val;
5422
+ val = round( val, options.precision );
5366
5423
 
5367
5424
  // Reset button (default value)
5368
5425
  if( !skipCallback )
@@ -5371,7 +5428,7 @@ class Panel {
5371
5428
  if( btn ) btn.style.display = val != vecinput.iValue ? "block": "none";
5372
5429
  }
5373
5430
 
5374
- if( lock_icon.locked )
5431
+ if( locker.locked )
5375
5432
  {
5376
5433
  for( let v of element.querySelectorAll( ".vecinput" ) ) {
5377
5434
  v.value = val;
@@ -5399,7 +5456,7 @@ class Panel {
5399
5456
  lastY = e.pageY;
5400
5457
  document.body.classList.add('nocursor');
5401
5458
  document.body.classList.add('noevents');
5402
- drag_icon.classList.remove('hidden');
5459
+ dragIcon.classList.remove('hidden');
5403
5460
  e.stopImmediatePropagation();
5404
5461
  e.stopPropagation();
5405
5462
  }
@@ -5411,14 +5468,14 @@ class Panel {
5411
5468
  if(e.shiftKey) mult = 10;
5412
5469
  else if(e.altKey) mult = 0.1;
5413
5470
 
5414
- if( lock_icon.locked )
5471
+ if( locker.locked )
5415
5472
  {
5416
5473
  for( let v of element.querySelectorAll(".vecinput") ) {
5417
- v.value = (+v.valueAsNumber + mult * dt).toPrecision(5);
5474
+ v.value = round( +v.valueAsNumber + mult * dt, options.precision );
5418
5475
  Panel._dispatch_event(v, "change");
5419
5476
  }
5420
5477
  } else {
5421
- vecinput.value = (+vecinput.valueAsNumber + mult * dt).toPrecision(5);
5478
+ vecinput.value = round( +vecinput.valueAsNumber + mult * dt, options.precision );
5422
5479
  Panel._dispatch_event(vecinput, "change");
5423
5480
  }
5424
5481
  }
@@ -5428,23 +5485,23 @@ class Panel {
5428
5485
  e.preventDefault();
5429
5486
  }
5430
5487
 
5431
- function inner_mouseup(e) {
5488
+ function inner_mouseup( e ) {
5432
5489
  var doc = that.root.ownerDocument;
5433
5490
  doc.removeEventListener("mousemove",inner_mousemove);
5434
5491
  doc.removeEventListener("mouseup",inner_mouseup);
5435
5492
  document.body.classList.remove('nocursor');
5436
5493
  document.body.classList.remove('noevents');
5437
- drag_icon.classList.add('hidden');
5494
+ dragIcon.classList.add('hidden');
5438
5495
  }
5439
5496
 
5440
- box.appendChild(vecinput);
5441
- container.appendChild(box);
5497
+ box.appendChild( vecinput );
5498
+ container.appendChild( box );
5442
5499
  }
5443
5500
 
5444
- let lock_icon = document.createElement('a');
5445
- lock_icon.className = "fa-solid fa-lock-open lexicon";
5446
- container.appendChild(lock_icon);
5447
- lock_icon.addEventListener("click", function(e) {
5501
+ let locker = document.createElement('a');
5502
+ locker.className = "fa-solid fa-lock-open lexicon";
5503
+ container.appendChild(locker);
5504
+ locker.addEventListener("click", function(e) {
5448
5505
  this.locked = !this.locked;
5449
5506
  if(this.locked){
5450
5507
  this.classList.add("fa-lock");
@@ -5455,7 +5512,7 @@ class Panel {
5455
5512
  }
5456
5513
  }, false);
5457
5514
 
5458
- element.appendChild(container);
5515
+ element.appendChild( container );
5459
5516
 
5460
5517
  return widget;
5461
5518
  }
@@ -6380,7 +6437,8 @@ class ContextMenu {
6380
6437
  this.items = [];
6381
6438
  this.colors = {};
6382
6439
 
6383
- if(title) {
6440
+ if( title )
6441
+ {
6384
6442
  const item = {};
6385
6443
  item[ title ] = [];
6386
6444
  item[ 'className' ] = "cmtitle";
@@ -6395,7 +6453,7 @@ class ContextMenu {
6395
6453
 
6396
6454
  if(!useAbsolute)
6397
6455
  {
6398
- let width = rect.width + 36; // this has paddings
6456
+ let width = rect.width;
6399
6457
  if(window.innerWidth - rect.right < 0)
6400
6458
  div.style.left = (window.innerWidth - width - margin) + "px";
6401
6459
 
@@ -6436,7 +6494,6 @@ class ContextMenu {
6436
6494
  contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
6437
6495
 
6438
6496
  // Set final width
6439
- // contextmenu.style.width = contextmenu.offsetWidth + "px";
6440
6497
  this._adjust_position( contextmenu, 6, true );
6441
6498
  }
6442
6499
 
@@ -6510,7 +6567,7 @@ class ContextMenu {
6510
6567
  }
6511
6568
 
6512
6569
  onCreate() {
6513
- this._adjust_position( this.root, 6 );
6570
+ doAsync( () => this._adjust_position( this.root, 6 ) );
6514
6571
  }
6515
6572
 
6516
6573
  add( path, options = {} ) {
@@ -6615,10 +6672,12 @@ LX.ContextMenu = ContextMenu;
6615
6672
  function addContextMenu( title, event, callback, options )
6616
6673
  {
6617
6674
  var menu = new ContextMenu( event, title, options );
6618
- LX.root.appendChild(menu.root);
6675
+ LX.root.appendChild( menu.root );
6619
6676
 
6620
- if(callback)
6677
+ if( callback )
6678
+ {
6621
6679
  callback( menu );
6680
+ }
6622
6681
 
6623
6682
  menu.onCreate();
6624
6683
 
package/changelog.md CHANGED
@@ -1,8 +1,18 @@
1
1
  # lexgui.js changelog
2
2
 
3
- ## 0.1.37 (dev)
3
+ ## 0.1.37
4
4
 
5
+ Audio:
6
+ - Start new audio widgets (Knob wip).
5
7
 
8
+ Timeline:
9
+ - Major refactor of Timeline
10
+ - Fixed examples
11
+
12
+ Allow unit labels for Number widgets.
13
+ Fixed Number/Vector precision.
14
+ Fixed ContextMenu position on creation over window size.
15
+ Minor bug fixes.
6
16
 
7
17
  ## 0.1.36 (master)
8
18
 
package/demo.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { LX } from 'lexgui';
2
2
  import 'lexgui/components/codeeditor.js';
3
3
  import 'lexgui/components/timeline.js';
4
+ import 'lexgui/components/audio.js';
4
5
 
5
6
  window.LX = LX;
6
7
 
@@ -477,6 +478,7 @@ function fillPanel( panel ) {
477
478
  panel.branch("Preferences", {icon: "fa-solid fa-gear"});
478
479
  panel.addButton(null, "Click me, Im Full Width...");
479
480
  panel.addText("Text", "Warning text", null, { warning: true });
481
+ panel.addKnob("A Knob", 4, 0, 200, value => { console.log(value) }, /*{ size: 'sm' }*/);
480
482
  panel.sameLine(2);
481
483
  panel.addFile("Img1", data => { console.log(data) }, {} );
482
484
  panel.addFile("Img2", data => { console.log(data) }, {} );
@@ -547,7 +549,7 @@ function fillPanel( panel ) {
547
549
  });
548
550
  panel.addNumber("Font Size", 36, (value, event) => {
549
551
  console.log(value);
550
- }, { min: 1, max: 48, step: 1});
552
+ }, { min: 1, max: 48, step: 1, units: "px"});
551
553
  panel.addVector2("2D Position", [250, 350], (value, event) => {
552
554
  console.log(value);
553
555
  }, { min: 0, max: 1024 });
@@ -18,7 +18,7 @@
18
18
  <script type="module">
19
19
 
20
20
  import { LX } from 'lexgui';
21
- import { Timeline, KeyFramesTimeline, ClipsTimeline, CurvesTimeline, CurvesKeyFramesTimeline } from 'lexgui/components/timeline.js';
21
+ import { Timeline, KeyFramesTimeline, ClipsTimeline, CurvesTimeline } from 'lexgui/components/timeline.js';
22
22
 
23
23
  // init library and get main area
24
24
  let area = LX.init();
@@ -123,8 +123,16 @@
123
123
  console.log(value);
124
124
  }, { min: 1, max: 48, step: 1});
125
125
  panel.addVector2("2D Position", position, (value, event) => {
126
-
127
- activeTimeline.updateSelectedKeyframe(value);
126
+ let currentSelection = activeTimeline.lastKeyFramesSelected[0];
127
+ if( currentSelection ){
128
+ const track = activeTimeline.animationClip.tracks[0];
129
+ const keyframe = currentSelection[2];
130
+ const dim = track.dim;
131
+
132
+ track.values[keyframe * track.dim] = value[0];
133
+ track.values[keyframe * track.dim + 1] = value[1];
134
+ track.edited[keyframe] = true;
135
+ }
128
136
  }, { min: 0, max: 1024 });
129
137
  panel.branch_open = true;
130
138
  panel.merge();
@@ -177,7 +185,7 @@
177
185
  keyframesPanel.onresize = () => {
178
186
  kfTimeline.resize();
179
187
  }
180
- let kfTimeline = new LX.KeyFramesTimeline('', {
188
+ let kfTimeline = new LX.KeyFramesTimeline('keyframesTimeline', {
181
189
  disableNewTracks: true,
182
190
  onBeforeCreateTopBar: (panel) => {
183
191
  panel.addDropdown("Animation", ["Anim 1", "Anim 2", "Anim 3"], "Anim 1", ()=> {})
@@ -189,13 +197,13 @@
189
197
  });
190
198
 
191
199
  keyframesPanel.attach(kfTimeline.root);
200
+ kfTimeline.setAnimationClip({tracks: [{name: "Font.position", values: [250, 450, 250, 250, 250, 450], times: [0, 0.5, 1.0]}, {name: "Item 1.scale", values: [0,1,0, 0.5], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 2", values: [0,1,0,1], times: [0.1]}, {name: "Item 3.position", values: [0,1,0,0,0,0], times: [0.1, 0.2, 0.3]}, {name: "Item 3.scale", values: [0,1,0], times: [ 0.1, 0.2, 0.3]}], duration: 1});
192
201
  kfTimeline.setSelectedItems(["Font", "Item 2", "Item 3"]);
193
- kfTimeline.setAnimationClip({tracks: [{name: "Font.position", values: [250, 350, 250, 250, 250, 350], times: [0, 0.1, 0.2]}, {name: "Item 1.scale", values: [0,1,0, 0.5], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 2", values: [0,1,0,1], times: [0.1]}, {name: "Item 3.position", values: [0,1,0,0,0,0], times: [0.1, 0.2, 0.3]}, {name: "Item 3.scale", values: [0,1,0], times: [ 0.1, 0.2, 0.3]}], duration: 1});
194
202
  activeTimeline = kfTimeline;
195
203
  kfTimeline.show();
196
204
 
197
205
 
198
- kfTimeline.onSelectKeyFrame = (data, currentSelection, keyFrameIndex) => {
206
+ kfTimeline.onSelectKeyFrame = (data, currentSelection) => {
199
207
  if(data.multipleSelection) {
200
208
  rightArea.hide();
201
209
  return;
@@ -209,6 +217,8 @@
209
217
  let values = kfTimeline.animationClip.tracks[id].values;
210
218
  const dim = kfTimeline.animationClip.tracks[id].dim;
211
219
 
220
+ //currentSelection == [track.name, track.idx, frameIdx, track.clipIdx, track.times[frameIdx]]
221
+ const keyFrameIndex = currentSelection[2];
212
222
  position = values.slice(keyFrameIndex * dim, keyFrameIndex * dim + dim);
213
223
  fillPanel(panel);
214
224
  //kfTimeline.animationClip.tracks[currentSelection[0][0]];
@@ -216,21 +226,23 @@
216
226
 
217
227
  kfTimeline.onSetTime = ( time ) => {
218
228
  rightArea.show();
219
- const frametime = kfTimeline.getNearestKeyFrame( kfTimeline.animationClip.tracks[0], time);
220
- let keyframe = kfTimeline.animationClip.tracks[0].times.indexOf(frametime);
221
- let values = kfTimeline.animationClip.tracks[0].values;
222
- let valueX = values[keyframe * 2];
223
- let valueY = values[keyframe * 2 + 1];
224
- if(keyframe != undefined) {
225
- let t = Math.abs(frametime - time);
226
- let sign = frametime - time > 0 ? -1 : 1;
227
- const nearestFrame = keyframe * 2 + sign;
228
- if (nearestFrame <= values.length - 2 && nearestFrame >= 0) {
229
- valueX = valueX * (1 - t) + values[keyframe * 2 + sign] * t;
230
- valueY = valueY * (1 - t) + values[keyframe * 2 + sign + 1] * t;
229
+ const keyframe = kfTimeline.getNearestKeyFrame( kfTimeline.animationClip.tracks[0], time, -1);
230
+ if(keyframe != -1) {
231
+ const trackLength = kfTimeline.animationClip.tracks[0].times.length;
232
+ const nextKeyframe = keyframe < (trackLength-1) ? (keyframe + 1) : keyframe;
233
+ const frametime = kfTimeline.animationClip.tracks[0].times[keyframe];
234
+ const nextframeTime = kfTimeline.animationClip.tracks[0].times[nextKeyframe];
235
+
236
+ let t = 1;
237
+ if ( keyframe < trackLength-1){
238
+ t = (time - frametime) / (nextframeTime - frametime);
231
239
  }
240
+
241
+ let values = kfTimeline.animationClip.tracks[0].values;
242
+ let valueX = values[keyframe * 2] * (1-t) + t * values[nextKeyframe * 2];
243
+ let valueY = values[keyframe * 2 + 1] * (1-t) + t * values[nextKeyframe * 2 + 1];
244
+ position = [valueX, valueY];
232
245
  }
233
- position = [valueX, valueY];
234
246
  fillPanel( panel );
235
247
  }
236
248
  }
@@ -282,10 +294,10 @@
282
294
 
283
295
  }});
284
296
 
285
- let curvesTimeline = new LX.CurvesKeyFramesTimeline("curves-timeline", { range: [-1,1]});
297
+ let curvesTimeline = new LX.CurvesTimeline("curves-timeline", { range: [-1,1]});
286
298
  curvesPanel.attach(curvesTimeline.root);
287
- curvesTimeline.setSelectedItems(["Item 1", "Item 2", "Item 3"]);
288
299
  curvesTimeline.setAnimationClip({tracks: [{name: "Item 1.position", values: [0,1,0,-1], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 1.scale", values: [0,1,0, 0.5], times: [0, 0.1, 0.2, 0.3]}, {name: "Item 2", values: [0,1,0,1], times: [0.1, 0.2, 0.3, 0.8]}, {name: "Item 3.position", values: [0,0,1], times: [0]}, {name: "Item 3.scale", values: [0,1,0], times: [0, 0.1, 0.3]}], duration: 1});
300
+ curvesTimeline.setSelectedItems(["Item 1", "Item 2", "Item 3"]);
289
301
  curvesTimeline.show();
290
302
  curvesTimeline.draw(0);
291
303
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lexgui",
3
- "version": "0.1.36",
3
+ "version": "0.1.37",
4
4
  "description": "JS library to create web graphical user interfaces",
5
5
  "type": "module",
6
6
  "main": "./build/lexgui.js",