lexgui 0.1.40 → 0.1.42

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.
@@ -15,7 +15,7 @@ class Session {
15
15
 
16
16
  constructor() {
17
17
 
18
- this.start_time = - 0.01;
18
+ this.start_time = -0.01;
19
19
  this.left_margin = 0;
20
20
  // this.current_time = 0;
21
21
  // this.last_time = 0;
@@ -62,7 +62,7 @@ class Timeline {
62
62
  this.onBeforeCreateTopBar = options.onBeforeCreateTopBar;
63
63
  this.onAfterCreateTopBar = options.onAfterCreateTopBar;
64
64
  this.onChangePlayMode = options.onChangePlayMode;
65
- this.onConfiguration = options.onConfiguration;
65
+ this.onShowConfiguration = options.onShowConfiguration;
66
66
  this.onBeforeDrawContent = options.onBeforeDrawContent;
67
67
 
68
68
  this.playing = false;
@@ -74,8 +74,8 @@ class Timeline {
74
74
 
75
75
  this.duration = 1;
76
76
  this.speed = 1;
77
- this.position = [0, 0];
78
- this.size = [ options.width ?? 400, options.height ?? 100];
77
+ this.position = [ 0, 0 ];
78
+ this.size = [ options.width ?? 400, options.height ?? 100 ];
79
79
 
80
80
  this.currentScroll = 0; //in percentage
81
81
  this.currentScrollInPixels = 0; //in pixels
@@ -107,17 +107,17 @@ class Timeline {
107
107
  let height = options.height ? options.height - this.header_offset : null;
108
108
 
109
109
  let area = new LX.Area( {id: "bottom-timeline-area", width: width || "calc(100% - 7px)", height: height || "100%"});
110
- area.split({ type: "horizontal", sizes: ["15%", "85%"]});
110
+ area.split({ type: "horizontal", sizes: ["15%", "85%"] });
111
+ area.splitBar.style.zIndex = 1; // for some reason this is needed here
111
112
  this.content_area = area;
112
- let [left, right] = area.sections;
113
+ let [ left, right ] = area.sections;
113
114
 
114
-
115
- right.root.appendChild(this.canvas);
115
+ right.root.appendChild( this.canvas );
116
116
  this.canvasArea = right;
117
117
  this.canvasArea.root.classList.add("lextimelinearea");
118
118
  this.updateHeader();
119
- this.updateLeftPanel(left);
120
- this.root.root.appendChild(area.root);
119
+ this.updateLeftPanel( left );
120
+ this.root.root.appendChild( area.root );
121
121
 
122
122
  if(!options.canvas && this.name != '') {
123
123
  this.root.root.id = this.name;
@@ -151,35 +151,41 @@ class Timeline {
151
151
 
152
152
  updateHeader() {
153
153
 
154
- if(this.header)
154
+ if( this.header )
155
+ {
155
156
  this.header.clear();
156
- else {
157
- this.header = new LX.Panel({id:'lextimelineheader', height: this.header_offset+"px"});
158
- this.root.root.appendChild(this.header.root);
157
+ }
158
+ else
159
+ {
160
+ this.header = new LX.Panel( { id: 'lextimelineheader', height: this.header_offset + "px" } );
161
+ this.root.root.appendChild( this.header.root );
159
162
  }
160
163
 
161
164
  let header = this.header;
162
165
  LX.DEFAULT_NAME_WIDTH = "50%";
163
166
  header.sameLine();
164
167
 
165
- if(this.name) {
166
- header.addTitle(this.name);
168
+ if( this.name )
169
+ {
170
+ header.addTitle(this.name );
167
171
  }
168
172
 
169
173
  header.addButton('', '<i class="fa-solid fa-'+ (this.playing ? 'pause' : 'play') +'"></i>', (value, event) => {
170
174
  this.changeState();
171
- }, {width: "40px", buttonClass: "accept"});
175
+ }, { width: "40px", buttonClass: "accept", title: "Play" });
172
176
 
173
- header.addButton('', '<i class="fa-solid fa-rotate"></i>', (value, event) => {
177
+ header.addButton('', '<i class="fa-solid fa-rotate"></i>', ( value, event ) => {
174
178
  this.loop = !this.loop;
175
- if(this.onChangePlayMode) {
176
- this.onChangePlayMode(this.loop);
179
+ if( this.onChangePlayMode )
180
+ {
181
+ this.onChangePlayMode( this.loop );
177
182
  }
178
-
179
- }, {width: "40px", selectable: true, selected: this.loop});
183
+ }, { width: "40px", selectable: true, selected: this.loop, title: 'Loop' });
180
184
 
181
- if(this.onBeforeCreateTopBar)
182
- this.onBeforeCreateTopBar(header);
185
+ if( this.onBeforeCreateTopBar )
186
+ {
187
+ this.onBeforeCreateTopBar( header );
188
+ }
183
189
 
184
190
  header.addNumber("Current Time", this.currentTime, (value, event) => {
185
191
  this.setTime(value)}, {signal: "@on_set_time_" + this.name, step: 0.01, min: 0, precision: 3, skipSlider: true});
@@ -191,29 +197,35 @@ class Timeline {
191
197
  header.addNumber("Speed", + this.speed.toFixed(3), (value, event) => {
192
198
  this.setSpeed(value)}, {step: 0.01, signal: "@on_set_speed_" + this.name});
193
199
 
194
- if(this.onAfterCreateTopBar)
195
- this.onAfterCreateTopBar(header);
200
+ if( this.onAfterCreateTopBar )
201
+ {
202
+ this.onAfterCreateTopBar( header );
203
+ }
196
204
 
197
- if(this.onShowOptimizeMenu)
198
- header.addButton("", '<i class="fa-solid fa-filter"></i>', (value, event) => {this.onShowOptimizeMenu(event)}, {width: "40px"});
205
+ if( this.onShowOptimizeMenu )
206
+ {
207
+ header.addButton("", '<i class="fa-solid fa-filter"></i>', (value, event) => {this.onShowOptimizeMenu(event)}, { width: "40px", title: "Optimize" });
208
+ }
199
209
 
200
- header.addButton("", '<i class="fa-solid fa-gear"></i>', (value, event) => {
201
- if(this.configurationDialog){
202
- this.configurationDialog.close();
203
- this.configurationDialog = null;
204
- return;
205
- }
206
- this.configurationDialog = new LX.Dialog("Configuration", d => {
207
- if ( this.onConfiguration ){
208
- this.onConfiguration(d);
209
- }
210
- }, {
211
- onclose: (root) => {
212
- root.remove();
210
+ if( this.onShowConfiguration )
211
+ {
212
+ header.addButton("", '<i class="fa-solid fa-gear"></i>', (value, event) => {
213
+ if(this.configurationDialog){
214
+ this.configurationDialog.close();
213
215
  this.configurationDialog = null;
216
+ return;
214
217
  }
215
- })
216
- }, {width: "40px"})
218
+ this.configurationDialog = new LX.Dialog("Configuration", dialog => {
219
+ this.onShowConfiguration(dialog);
220
+ }, {
221
+ onclose: (root) => {
222
+ this.configurationDialog.panel.clear(); // clear signals
223
+ this.configurationDialog = null;
224
+ root.remove();
225
+ }
226
+ })
227
+ }, { width: "40px" })
228
+ }
217
229
 
218
230
  header.endLine();
219
231
  LX.DEFAULT_NAME_WIDTH = "30%";
@@ -223,46 +235,53 @@ class Timeline {
223
235
  * @method updateLeftPanel
224
236
  *
225
237
  */
226
- updateLeftPanel(area) {
227
-
238
+ updateLeftPanel( area ) {
228
239
 
229
240
  let scrollTop = 0;
230
- if(this.leftPanel){
231
- scrollTop = this.leftPanel.root.children[1].scrollTop;
241
+ if( this.leftPanel )
242
+ {
243
+ scrollTop = this.leftPanel.root.children[ 1 ].scrollTop;
232
244
  this.leftPanel.clear();
233
245
  }
234
- else {
235
- this.leftPanel = area.addPanel({className: 'lextimelinepanel', width: "100%", height: "100%"});
246
+ else
247
+ {
248
+ this.leftPanel = area.addPanel( { className: 'lextimelinepanel', width: "100%", height: "100%" } );
236
249
  }
237
250
 
238
251
  let panel = this.leftPanel;
239
- panel.sameLine(2);
240
- let title = panel.addTitle("Tracks");
252
+ panel.sameLine( 2 );
253
+
254
+ let title = panel.addTitle( "Tracks" );
241
255
 
242
- if(!this.disableNewTracks)
256
+ if( !this.disableNewTracks )
243
257
  {
244
258
  panel.addButton('', '<i class = "fa-solid fa-plus"></i>', (value, event) => {
245
259
  this.addNewTrack();
246
260
  }, {width: "40px", height: "40px"});
247
261
  }
262
+
248
263
  panel.endLine();
249
264
 
250
- const styles = window.getComputedStyle(title);
265
+ const styles = window.getComputedStyle( title );
251
266
  const titleHeight = title.clientHeight + parseFloat(styles['marginTop']) + parseFloat(styles['marginBottom']);
252
267
 
253
268
  let p = new LX.Panel({height: "calc(100% - " + titleHeight + "px)"});
254
- if(this.animationClip && this.selectedItems.length) {
255
- let items = {'id': '', 'children': []};
269
+
270
+ if( this.animationClip && this.selectedItems.length )
271
+ {
272
+ let items = { 'id': '', 'children': [] };
256
273
 
257
274
  const tracksPerItem = this.animationClip.tracksPerItem;
258
- for(let i = 0; i < this.selectedItems.length; i++ ) {
259
- let selected = this.selectedItems[i];
275
+ for( let i = 0; i < this.selectedItems.length; i++ )
276
+ {
277
+ let selected = this.selectedItems[ i ];
260
278
  let t = {
261
279
  'id': selected,
262
280
  'skipVisibility': true,
263
281
  'children': []
264
282
  }
265
- for(let j = 0; j < tracksPerItem[selected].length; j++) {
283
+ for( let j = 0; j < tracksPerItem[selected].length; j++ )
284
+ {
266
285
  let track = tracksPerItem[selected][j];
267
286
  let id = track.type ? track.type : track.name;
268
287
 
@@ -299,7 +318,9 @@ class Timeline {
299
318
  }]})
300
319
  // panel.addTitle(track.name + (track.type? '(' + track.type + ')' : ''));
301
320
  }
302
- items.children.push(t);
321
+
322
+ items.children.push( t );
323
+
303
324
  let el = p.addTree(null, t, {filter: false, rename: false, draggable: false, onevent: (e) => {
304
325
  switch(e.type) {
305
326
  case LX.TreeEvent.NODE_SELECTED:
@@ -315,12 +336,14 @@ class Timeline {
315
336
  }
316
337
  break;
317
338
  case LX.TreeEvent.NODE_VISIBILITY:
318
- if (e.node.parent){
319
- const tracksInItem = this.animationClip.tracksPerItem[e.node.parent.id];
339
+ if ( e.node.parent )
340
+ {
341
+ const tracksInItem = this.animationClip.tracksPerItem[ e.node.parent.id ];
320
342
  const type = e.node.id;
321
343
  for(let i = 0; i < tracksInItem.length; i++) {
322
- if(tracksInItem[i].type == type){
323
- this.changeTrackVisibility(tracksInItem[i].clipIdx, e.value);
344
+ if(tracksInItem[i].type == type)
345
+ {
346
+ this.changeTrackVisibility( tracksInItem[ i ].clipIdx, e.value );
324
347
  break;
325
348
  }
326
349
  }
@@ -328,8 +351,9 @@ class Timeline {
328
351
  break;
329
352
  case LX.TreeEvent.NODE_CARETCHANGED:
330
353
  const tracksInItem = this.animationClip.tracksPerItem[e.node.id];
331
- for( let i = 0; i < tracksInItem; ++i ){
332
- this.changeTrackDisplay(tracksInItem[i].clipIdx, e.node.closed);
354
+ for( let i = 0; i < tracksInItem; ++i )
355
+ {
356
+ this.changeTrackDisplay( tracksInItem[ i ].clipIdx, e.node.closed );
333
357
  }
334
358
  break;
335
359
  }
@@ -337,19 +361,23 @@ class Timeline {
337
361
 
338
362
  }
339
363
  }
340
- panel.attach(p.root)
364
+
365
+ panel.attach( p.root )
341
366
  p.root.style.overflowY = "scroll";
342
- p.root.addEventListener("scroll", (e) => {
367
+ p.root.addEventListener("scroll", e => {
343
368
  this.currentScroll = e.currentTarget.scrollTop/(e.currentTarget.scrollHeight - e.currentTarget.clientHeight);
344
- })
369
+ });
345
370
  // for(let i = 0; i < this.animationClip.tracks.length; i++) {
346
371
  // let track = this.animationClip.tracks[i];
347
372
  // panel.addTitle(track.name + (track.type? '(' + track.type + ')' : ''));
348
373
  // }
349
- this.leftPanel.root.children[1].scrollTop = scrollTop;
374
+ this.leftPanel.root.children[ 1 ].scrollTop = scrollTop;
350
375
 
351
- if(this.leftPanel.parent.root.classList.contains("hidden") || !this.root.root.parent)
376
+ if( this.leftPanel.parent.root.classList.contains("hidden") || !this.root.root.parent )
377
+ {
352
378
  return;
379
+ }
380
+
353
381
  this.resizeCanvas([ this.root.root.clientWidth - this.leftPanel.root.clientWidth - 8, this.size[1]]);
354
382
  }
355
383
 
@@ -359,8 +387,10 @@ class Timeline {
359
387
 
360
388
  addNewTrack() {
361
389
 
362
- if(!this.animationClip)
390
+ if( !this.animationClip )
391
+ {
363
392
  this.animationClip = {tracks:[]};
393
+ }
364
394
 
365
395
  let trackInfo = {
366
396
  idx: this.animationClip.tracks.length,
@@ -368,7 +398,7 @@ class Timeline {
368
398
  selected: [], edited: [], hovered: []
369
399
  };
370
400
 
371
- this.animationClip.tracks.push(trackInfo);
401
+ this.animationClip.tracks.push( trackInfo );
372
402
  this.updateLeftPanel();
373
403
  return trackInfo.idx;
374
404
  }
@@ -378,30 +408,36 @@ class Timeline {
378
408
  let tracks = [];
379
409
 
380
410
  // Manage negative selection
381
- if(minY > maxY) {
411
+ if( minY > maxY )
412
+ {
382
413
  let aux = minY;
383
414
  minY = maxY;
384
415
  maxY = aux;
385
416
  }
386
417
 
387
- for(let i = this.tracksDrawn.length - 1; i >= 0; --i) {
388
- let t = this.tracksDrawn[i];
389
- let pos = t[1] - this.topMargin, size = t[2];
418
+ for(let i = this.tracksDrawn.length - 1; i >= 0; --i)
419
+ {
420
+ let t = this.tracksDrawn[ i ];
421
+ let pos = t[ 1 ] - this.topMargin, size = t[ 2 ];
390
422
  if( pos + threshold >= minY && (pos + size - threshold) <= maxY ) {
391
- tracks.push( t[0] );
423
+ tracks.push( t[ 0 ] );
392
424
  }
393
425
  }
394
426
 
395
427
  return tracks;
396
428
  }
397
429
 
398
- getCurrentContent(track, time, threshold) {
430
+ getCurrentContent( track, time, threshold ) {
399
431
 
400
- if(this.getCurrentKeyFrame)
401
- return this.getCurrentKeyFrame(track, time, threshold);
432
+ if( this.getCurrentKeyFrame )
433
+ {
434
+ return this.getCurrentKeyFrame( track, time, threshold );
435
+ }
402
436
 
403
- if(this.getCurrentClip)
404
- return this.getCurrentClip(track, time, threshold);
437
+ if( this.getCurrentClip )
438
+ {
439
+ return this.getCurrentClip( track, time, threshold );
440
+ }
405
441
  }
406
442
 
407
443
  /**
@@ -412,17 +448,21 @@ class Timeline {
412
448
  * [KeyFrameTimeline] - each track should contain an attribute "dim" to indicate the value dimension (e.g. vector3 -> dim=3). Otherwise dimensions will be infered from track's values and times. Default is 1
413
449
  */
414
450
  setAnimationClip( animation, needsToProcess = true ) {
415
- if ( this.unSelectAllKeyFrames ){
451
+
452
+ if ( this.unSelectAllKeyFrames )
453
+ {
416
454
  this.unSelectAllKeyFrames();
417
455
  this.unHoverAll();
418
456
  this.unSelectAllTracks();
419
457
  this.selectedItems = [];
420
458
  }
421
459
 
422
- if(!animation || !animation.tracks || needsToProcess) {
423
- this.processTracks(animation); // generate default animationclip or process the user's one
460
+ if( !animation || !animation.tracks || needsToProcess )
461
+ {
462
+ this.processTracks( animation ); // generate default animationclip or process the user's one
424
463
  }
425
- else{
464
+ else
465
+ {
426
466
  this.animationClip = animation;
427
467
  }
428
468
 
@@ -431,12 +471,13 @@ class Timeline {
431
471
 
432
472
  //this.updateHeader();
433
473
  this.updateLeftPanel();
474
+
434
475
  return this.animationClip;
435
476
  }
436
477
 
437
- drawTimeInfo (w, h = this.topMargin) {
478
+ drawTimeInfo( w, h = this.topMargin ) {
438
479
 
439
- let ctx = this.canvas.getContext("2d");
480
+ let ctx = this.canvas.getContext( "2d" );
440
481
  ctx.font = "11px " + Timeline.FONT;//"11px Calibri";
441
482
  ctx.textAlign = "center";
442
483
 
@@ -449,57 +490,57 @@ class Timeline {
449
490
  ctx.strokeStyle = LX.Timeline.FONT_COLOR;
450
491
 
451
492
  // set tick and sub tick times
452
- let tick_time = 4;
453
- if ( this.secondsToPixels > 900 ){ tick_time = 1; }
454
- else if ( this.secondsToPixels > 100 ){ tick_time = 2; }
455
- else if ( this.secondsToPixels > 50 ){ tick_time = 3; }
493
+ let tickTime = 4;
494
+ if ( this.secondsToPixels > 900 ) { tickTime = 1; }
495
+ else if ( this.secondsToPixels > 100 ) { tickTime = 2; }
496
+ else if ( this.secondsToPixels > 50 ) { tickTime = 3; }
456
497
 
457
- let subtick_time = this.timeSeparators[tick_time - 1];
458
- tick_time = this.timeSeparators[tick_time];
498
+ let subtickTime = this.timeSeparators[tickTime - 1];
499
+ tickTime = this.timeSeparators[tickTime];
459
500
 
460
- // transform times into pixel coords
461
- let tick_x = this.timeToX( this.startTime + tick_time ) - this.timeToX( this.startTime );
462
- let subtick_x = subtick_time * tick_x / tick_time;
501
+ // Transform times into pixel coords
502
+ let tickX = this.timeToX( this.startTime + tickTime ) - this.timeToX( this.startTime );
503
+ let subtickX = subtickTime * tickX / tickTime;
463
504
 
464
- let startx = this.timeToX( Math.floor( this.startTime / tick_time) * tick_time ); // floor because might need to draw previous subticks
505
+ let startx = this.timeToX( Math.floor( this.startTime / tickTime) * tickTime ); // floor because might need to draw previous subticks
465
506
  let endx = this.timeToX( this.endTime ); // draw up to endTime
466
507
 
467
- // begin drawing
508
+ // Begin drawing
468
509
  ctx.beginPath();
469
510
  ctx.fillStyle = Timeline.FONT_COLOR//"#888";
470
511
  ctx.globalAlpha = this.opacity;
471
512
 
472
- for( let x = startx; x <= endx; x += tick_x){
473
-
474
- // draw main line
475
- ctx.moveTo(Math.round(x) + 0.5, h * 0.4 + h * 0.3 );
476
- ctx.lineTo(Math.round(x) + 0.5, h * 0.95 );
477
-
478
- // draw following sub lines
479
- let endsub = x + tick_x - subtick_x*0.5;
480
- for (let sub_x = x; sub_x < endsub && sub_x < endx; sub_x += subtick_x){
481
- ctx.moveTo(Math.round(sub_x) + 0.5, h * 0.4 + h * 0.45 );
482
- ctx.lineTo(Math.round(sub_x) + 0.5, h * 0.95 );
513
+ for( let x = startx; x <= endx; x += tickX )
514
+ {
515
+ // Draw main line
516
+ ctx.moveTo( Math.round( x ) + 0.5, h * 0.4 + h * 0.3 );
517
+ ctx.lineTo( Math.round( x ) + 0.5, h * 0.95 );
518
+
519
+ // Draw following sub lines
520
+ let endsub = x + tickX - subtickX * 0.5;
521
+ for ( let subX = x; subX < endsub && subX < endx; subX += subtickX )
522
+ {
523
+ ctx.moveTo( Math.round( subX ) + 0.5, h * 0.4 + h * 0.45 );
524
+ ctx.lineTo( Math.round( subX ) + 0.5, h * 0.95 );
483
525
  }
484
526
 
485
- // draw time number
527
+ // Draw time number
486
528
  let t = this.xToTime( x );
487
- ctx.fillText( t.toFixed(tick_time < 1? 1 : 0), x, h * 0.6);
529
+ ctx.fillText( t.toFixed( tickTime < 1 ? 1 : 0 ), x, h * 0.6 );
488
530
  }
489
531
 
490
532
  ctx.stroke();
491
-
492
-
493
533
  ctx.restore();
494
534
  }
495
535
 
496
- drawTracksBackground(w, h) {
536
+ drawTracksBackground( w, h ) {
497
537
 
498
538
  let canvas = this.canvas;
499
539
  let ctx = canvas.getContext("2d");
500
540
  let duration = this.duration;
501
541
  ctx.globalAlpha = this.opacity;
502
- //content
542
+
543
+ // Content
503
544
  let margin = this.session.left_margin;
504
545
  let timeline_height = this.topMargin;
505
546
  let line_height = this.trackHeight;
@@ -509,19 +550,14 @@ class Timeline {
509
550
  let max_tracks = Math.ceil( (h - timeline_height + this.currentScrollInPixels) / line_height );
510
551
 
511
552
  ctx.save();
512
- ctx.fillStyle = Timeline.BACKGROUND_COLOR;
513
- for(let i = 0; i <= max_tracks; ++i)
553
+ ctx.fillStyle = "#f0f0f003"//Timeline.TRACK_COLOR_SECONDARY;
554
+ ctx.globalAlpha = 1;
555
+ for(let i = 0; i <= max_tracks; i+=2)
514
556
  {
515
- ctx.fillStyle = i % 2 == 0 ? Timeline.TRACK_COLOR_PRIMARY: Timeline.BACKGROUND_COLOR;
516
557
  ctx.fillRect(0, timeline_height + i * line_height - this.currentScrollInPixels, w, line_height );
517
558
  }
518
-
519
- //black bg
520
- ctx.globalAlpha = 0.7;
521
- ctx.fillStyle = Timeline.BACKGROUND_COLOR;
522
- ctx.fillRect( margin, 0, canvas.width - margin, canvas.height);
523
559
  ctx.globalAlpha = this.opacity;
524
-
560
+
525
561
  //bg lines
526
562
  ctx.strokeStyle = "#444";
527
563
  ctx.beginPath();
@@ -529,6 +565,7 @@ class Timeline {
529
565
  let pos = this.timeToX( 0 );
530
566
  if(pos < margin)
531
567
  pos = margin;
568
+ ctx.lineWidth = 1;
532
569
  ctx.moveTo( pos + 0.5, timeline_height);
533
570
  ctx.lineTo( pos + 0.5, canvas.height);
534
571
  ctx.moveTo( Math.round( this.timeToX( duration ) ) + 0.5, timeline_height);
@@ -704,7 +741,7 @@ class Timeline {
704
741
  * @param {Number} t
705
742
  */
706
743
 
707
- setDuration( t, updateHeader = true ) {
744
+ setDuration( t, updateHeader = true, skipCallback = false ) {
708
745
  let v = this.validateDuration(t);
709
746
  let decimals = t.toString().split('.')[1] ? t.toString().split('.')[1].length : 0;
710
747
  updateHeader = (updateHeader || +v.toFixed(decimals) != t);
@@ -714,7 +751,7 @@ class Timeline {
714
751
  LX.emit( "@on_set_duration_" + this.name, +this.duration.toFixed(3)); // skipcallback = true
715
752
  }
716
753
 
717
- if( this.onSetDuration )
754
+ if( this.onSetDuration && !skipCallback )
718
755
  this.onSetDuration( this.duration );
719
756
  }
720
757
 
@@ -733,19 +770,19 @@ class Timeline {
733
770
  * @param {Number} speed
734
771
  */
735
772
 
736
- setSpeed(speed) {
773
+ setSpeed(speed, skipCallback = false) {
737
774
  this.speed = speed;
738
775
  LX.emit( "@on_set_speed_" + this.name, +this.speed.toFixed(3)); // skipcallback = true
739
776
 
740
- if( this.onSetSpeed )
777
+ if( this.onSetSpeed && !skipCallback)
741
778
  this.onSetSpeed( this.speed );
742
779
  }
743
780
 
744
- setTime(time){
781
+ setTime(time, skipCallback = false ){
745
782
  this.currentTime = Math.max(0,Math.min(time,this.duration));
746
783
  LX.emit( "@on_set_time_" + this.name, +this.currentTime.toFixed(2)); // skipcallback = true
747
784
 
748
- if(this.onSetTime)
785
+ if(this.onSetTime && !skipCallback)
749
786
  this.onSetTime(this.currentTime);
750
787
  }
751
788
 
@@ -832,6 +869,9 @@ class Timeline {
832
869
  this.leftPanel.root.children[1].scrollTop += e.deltaY; // wheel deltaY
833
870
  }
834
871
 
872
+ if ( this.onMouse ){
873
+ this.onMouse(e, time);
874
+ }
835
875
  return;
836
876
  }
837
877
 
@@ -969,8 +1009,8 @@ class Timeline {
969
1009
  return true;
970
1010
  }
971
1011
 
972
- if( this.onMouse && this.onMouse( e, time, this ) )
973
- return;
1012
+ if( this.onMouse )
1013
+ this.onMouse( e, time, this );
974
1014
 
975
1015
  return true;
976
1016
  }
@@ -1159,21 +1199,38 @@ class Timeline {
1159
1199
  * // NOTE: to select a track from outside of the timeline, a this.leftPanelTrackTree.select(item) needs to be called.
1160
1200
  */
1161
1201
  selectTrack( trackIdx ) {
1202
+
1203
+ if( !this.animationClip )
1204
+ {
1205
+ return;
1206
+ }
1207
+
1162
1208
  this.unSelectAllTracks();
1163
1209
 
1164
- let track = this.animationClip.tracks[trackIdx];
1210
+ let track = this.animationClip.tracks[ trackIdx ];
1165
1211
  track.isSelected = true;
1166
1212
 
1167
- if(this.onSelectTrack)
1213
+ if( this.onSelectTrack )
1214
+ {
1168
1215
  this.onSelectTrack(track);
1216
+ }
1169
1217
  }
1170
1218
 
1171
1219
  unSelectAllTracks() {
1172
- for(let i = 0; i < this.selectedItems.length; i++) {
1173
- let item = this.selectedItems[i];
1174
- let tracks = this.animationClip.tracksPerItem[item];
1175
- for(let t = 0; t < tracks.length; t++) {
1176
- tracks[t].isSelected = false;
1220
+
1221
+ if( !this.animationClip )
1222
+ {
1223
+ return;
1224
+ }
1225
+
1226
+ for(let i = 0; i < this.selectedItems.length; i++)
1227
+ {
1228
+ let item = this.selectedItems[ i ];
1229
+ let tracks = this.animationClip.tracksPerItem[ item ];
1230
+
1231
+ for( let t = 0; t < tracks.length; t++ )
1232
+ {
1233
+ tracks[ t ].isSelected = false;
1177
1234
  }
1178
1235
  }
1179
1236
  }
@@ -2572,14 +2629,14 @@ class KeyFramesTimeline extends Timeline {
2572
2629
 
2573
2630
  const currentSelection = this.selectKeyFrame(t, keyFrameIndex, !multiple); // changes time
2574
2631
 
2632
+ if( !multiple ) {
2633
+ this.setTime(this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ]);
2634
+ }
2575
2635
  if( this.onSelectKeyFrame && this.onSelectKeyFrame(e, currentSelection)) {
2576
2636
  // Event handled
2577
2637
  return;
2578
2638
  }
2579
-
2580
- if( !multiple ) {
2581
- this.setTime(this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ]);
2582
- }
2639
+
2583
2640
  }
2584
2641
 
2585
2642
  /**
@@ -2605,7 +2662,6 @@ class KeyFramesTimeline extends Timeline {
2605
2662
  /**
2606
2663
  * @method clearTrack
2607
2664
  */
2608
-
2609
2665
  clearTrack(idx, defaultValue) {
2610
2666
 
2611
2667
  let track = this.animationClip.tracks[idx];
@@ -2615,11 +2671,14 @@ class KeyFramesTimeline extends Timeline {
2615
2671
  return;
2616
2672
  }
2617
2673
 
2674
+ this.unHoverAll();
2675
+ this.unSelectAllKeyFrames();
2676
+
2677
+ this.saveState(track.clipIdx);
2618
2678
  const count = track.times.length;
2619
2679
  for(let i = count - 1; i >= 0; i--)
2620
2680
  {
2621
- this.saveState(track.clipIdx);
2622
- this.#delete(track.clipIdx, i );
2681
+ this.#delete(track.clipIdx, i);
2623
2682
  }
2624
2683
  if(defaultValue != undefined) {
2625
2684
  if(typeof(defaultValue) == 'number') {
@@ -2855,7 +2914,10 @@ class ClipsTimeline extends Timeline {
2855
2914
  onMouseMove( e, time ) {
2856
2915
  // function not called if shift is pressed (boxselection)
2857
2916
 
2858
- if(this.grabbing && e.buttons != 2) {
2917
+ if ( this.grabbingTimeBar || this.grabbingScroll ){
2918
+ return;
2919
+ }
2920
+ else if(this.grabbing && e.buttons != 2) {
2859
2921
  this.unHoverAll();
2860
2922
 
2861
2923
  let delta = time - this.grabTime;
@@ -2879,7 +2941,8 @@ class ClipsTimeline extends Timeline {
2879
2941
  duration = Math.min( track.clips[this.lastClipsSelected[0][1] + 1].start - clip.start - 0.0001, duration );
2880
2942
  }
2881
2943
  clip.duration = duration;
2882
- clip.fadeout = Math.max(Math.min((clip.fadeout || clip.start+clip.duration) + delta, clip.start+clip.duration), clip.start);
2944
+ clip.fadeout = Math.max(Math.min((clip.fadeout ?? (clip.start+clip.duration)) + delta, clip.start+clip.duration), clip.start);
2945
+ clip.fadein = Math.max(Math.min((clip.fadein ?? (clip.start+clip.duration)), (clip.fadeout ?? (clip.start+clip.duration))), clip.start);
2883
2946
  if(this.duration < clip.start + clip.duration){
2884
2947
  this.setDuration(clip.start + clip.duration);
2885
2948
  }
@@ -3258,16 +3321,13 @@ class ClipsTimeline extends Timeline {
3258
3321
  /**
3259
3322
  * @method optimizeTrack
3260
3323
  */
3261
-
3262
3324
  optimizeTrack(trackIdx) {
3263
3325
  }
3264
3326
 
3265
3327
  /**
3266
3328
  * @method optimizeTracks
3267
3329
  */
3268
-
3269
3330
  optimizeTracks() {
3270
- this.addClip()
3271
3331
  }
3272
3332
 
3273
3333
  /**
@@ -5154,14 +5214,14 @@ class CurvesTimeline extends Timeline {
5154
5214
 
5155
5215
  const currentSelection = this.selectKeyFrame(t, keyFrameIndex, !multiple, multiple); // changes time on the first keyframe selected
5156
5216
 
5217
+ if (!multiple){
5218
+ this.setTime(this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ]);
5219
+ }
5220
+
5157
5221
  if( this.onSelectKeyFrame && this.onSelectKeyFrame(e, currentSelection)) {
5158
5222
  // Event handled
5159
5223
  return;
5160
5224
  }
5161
-
5162
- if (!multiple){
5163
- this.setTime(this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ]);
5164
- }
5165
5225
  }
5166
5226
 
5167
5227
  /**
@@ -5195,12 +5255,15 @@ class CurvesTimeline extends Timeline {
5195
5255
  {
5196
5256
  return;
5197
5257
  }
5198
-
5258
+
5259
+ this.unHoverAll();
5260
+ this.unSelectAllKeyFrames();
5261
+
5262
+ this.saveState(track.clipIdx);
5199
5263
  const count = track.times.length;
5200
5264
  for(let i = count - 1; i >= 0; i--)
5201
5265
  {
5202
- this.saveState(track.clipIdx);
5203
- this.#delete(track, i );
5266
+ this.#delete(track.clipIdx, i );
5204
5267
  }
5205
5268
  if(defaultValue != undefined) {
5206
5269
  if(typeof(defaultValue) == 'number') {
@@ -5292,4 +5355,4 @@ LX.UTILS.concatTypedArray = (arrays, ArrayType) => {
5292
5355
  return result;
5293
5356
  }
5294
5357
 
5295
- export { Timeline, KeyFramesTimeline, ClipsTimeline, CurvesTimeline };
5358
+ export { Timeline, KeyFramesTimeline, ClipsTimeline, CurvesTimeline };