lexgui 0.1.41 → 0.1.43
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/build/components/codeeditor.js +451 -271
- package/build/components/timeline.js +165 -109
- package/build/lexgui.css +142 -71
- package/build/lexgui.js +1162 -835
- package/build/lexgui.module.js +979 -647
- package/changelog.md +35 -3
- package/demo.js +16 -12
- package/examples/asset_view.html +3 -2
- package/examples/code_editor.html +11 -6
- package/examples/previews/side_bar.png +0 -0
- package/examples/previews/timeline.png +0 -0
- package/examples/side_bar.html +2 -2
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ class Session {
|
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
17
|
|
|
18
|
-
this.start_time = -
|
|
18
|
+
this.start_time = -0.01;
|
|
19
19
|
this.left_margin = 0;
|
|
20
20
|
// this.current_time = 0;
|
|
21
21
|
// this.last_time = 0;
|
|
@@ -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
|
|
@@ -108,17 +108,16 @@ class Timeline {
|
|
|
108
108
|
|
|
109
109
|
let area = new LX.Area( {id: "bottom-timeline-area", width: width || "calc(100% - 7px)", height: height || "100%"});
|
|
110
110
|
area.split({ type: "horizontal", sizes: ["15%", "85%"] });
|
|
111
|
-
area.
|
|
111
|
+
area.splitBar.style.zIndex = 1; // for some reason this is needed here
|
|
112
112
|
this.content_area = area;
|
|
113
|
-
let [left, right] = area.sections;
|
|
113
|
+
let [ left, right ] = area.sections;
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
right.root.appendChild(this.canvas);
|
|
115
|
+
right.root.appendChild( this.canvas );
|
|
117
116
|
this.canvasArea = right;
|
|
118
117
|
this.canvasArea.root.classList.add("lextimelinearea");
|
|
119
118
|
this.updateHeader();
|
|
120
|
-
this.updateLeftPanel(left);
|
|
121
|
-
this.root.root.appendChild(area.root);
|
|
119
|
+
this.updateLeftPanel( left );
|
|
120
|
+
this.root.root.appendChild( area.root );
|
|
122
121
|
|
|
123
122
|
if(!options.canvas && this.name != '') {
|
|
124
123
|
this.root.root.id = this.name;
|
|
@@ -152,35 +151,41 @@ class Timeline {
|
|
|
152
151
|
|
|
153
152
|
updateHeader() {
|
|
154
153
|
|
|
155
|
-
if(this.header)
|
|
154
|
+
if( this.header )
|
|
155
|
+
{
|
|
156
156
|
this.header.clear();
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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 );
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
let header = this.header;
|
|
163
165
|
LX.DEFAULT_NAME_WIDTH = "50%";
|
|
164
166
|
header.sameLine();
|
|
165
167
|
|
|
166
|
-
if(this.name)
|
|
167
|
-
|
|
168
|
+
if( this.name )
|
|
169
|
+
{
|
|
170
|
+
header.addTitle(this.name );
|
|
168
171
|
}
|
|
169
172
|
|
|
170
173
|
header.addButton('', '<i class="fa-solid fa-'+ (this.playing ? 'pause' : 'play') +'"></i>', (value, event) => {
|
|
171
174
|
this.changeState();
|
|
172
|
-
}, {width: "40px", buttonClass: "accept"});
|
|
175
|
+
}, { width: "40px", buttonClass: "accept", title: "Play" });
|
|
173
176
|
|
|
174
|
-
header.addButton('', '<i class="fa-solid fa-rotate"></i>', (value, event) => {
|
|
177
|
+
header.addButton('', '<i class="fa-solid fa-rotate"></i>', ( value, event ) => {
|
|
175
178
|
this.loop = !this.loop;
|
|
176
|
-
if(this.onChangePlayMode)
|
|
177
|
-
|
|
179
|
+
if( this.onChangePlayMode )
|
|
180
|
+
{
|
|
181
|
+
this.onChangePlayMode( this.loop );
|
|
178
182
|
}
|
|
179
|
-
|
|
180
|
-
}, {width: "40px", selectable: true, selected: this.loop});
|
|
183
|
+
}, { width: "40px", selectable: true, selected: this.loop, title: 'Loop' });
|
|
181
184
|
|
|
182
|
-
if(this.onBeforeCreateTopBar)
|
|
183
|
-
|
|
185
|
+
if( this.onBeforeCreateTopBar )
|
|
186
|
+
{
|
|
187
|
+
this.onBeforeCreateTopBar( header );
|
|
188
|
+
}
|
|
184
189
|
|
|
185
190
|
header.addNumber("Current Time", this.currentTime, (value, event) => {
|
|
186
191
|
this.setTime(value)}, {signal: "@on_set_time_" + this.name, step: 0.01, min: 0, precision: 3, skipSlider: true});
|
|
@@ -192,13 +197,18 @@ class Timeline {
|
|
|
192
197
|
header.addNumber("Speed", + this.speed.toFixed(3), (value, event) => {
|
|
193
198
|
this.setSpeed(value)}, {step: 0.01, signal: "@on_set_speed_" + this.name});
|
|
194
199
|
|
|
195
|
-
if(this.onAfterCreateTopBar)
|
|
196
|
-
|
|
200
|
+
if( this.onAfterCreateTopBar )
|
|
201
|
+
{
|
|
202
|
+
this.onAfterCreateTopBar( header );
|
|
203
|
+
}
|
|
197
204
|
|
|
198
|
-
if(this.onShowOptimizeMenu)
|
|
199
|
-
|
|
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
|
+
}
|
|
200
209
|
|
|
201
|
-
if(this.onShowConfiguration)
|
|
210
|
+
if( this.onShowConfiguration )
|
|
211
|
+
{
|
|
202
212
|
header.addButton("", '<i class="fa-solid fa-gear"></i>', (value, event) => {
|
|
203
213
|
if(this.configurationDialog){
|
|
204
214
|
this.configurationDialog.close();
|
|
@@ -214,7 +224,7 @@ class Timeline {
|
|
|
214
224
|
root.remove();
|
|
215
225
|
}
|
|
216
226
|
})
|
|
217
|
-
}, {width: "40px"})
|
|
227
|
+
}, { width: "40px" })
|
|
218
228
|
}
|
|
219
229
|
|
|
220
230
|
header.endLine();
|
|
@@ -225,46 +235,53 @@ class Timeline {
|
|
|
225
235
|
* @method updateLeftPanel
|
|
226
236
|
*
|
|
227
237
|
*/
|
|
228
|
-
updateLeftPanel(area) {
|
|
229
|
-
|
|
238
|
+
updateLeftPanel( area ) {
|
|
230
239
|
|
|
231
240
|
let scrollTop = 0;
|
|
232
|
-
if(this.leftPanel)
|
|
233
|
-
|
|
241
|
+
if( this.leftPanel )
|
|
242
|
+
{
|
|
243
|
+
scrollTop = this.leftPanel.root.children[ 1 ].scrollTop;
|
|
234
244
|
this.leftPanel.clear();
|
|
235
245
|
}
|
|
236
|
-
else
|
|
237
|
-
|
|
246
|
+
else
|
|
247
|
+
{
|
|
248
|
+
this.leftPanel = area.addPanel( { className: 'lextimelinepanel', width: "100%", height: "100%" } );
|
|
238
249
|
}
|
|
239
250
|
|
|
240
251
|
let panel = this.leftPanel;
|
|
241
|
-
panel.sameLine(2);
|
|
242
|
-
|
|
252
|
+
panel.sameLine( 2 );
|
|
253
|
+
|
|
254
|
+
let title = panel.addTitle( "Tracks" );
|
|
243
255
|
|
|
244
|
-
if(!this.disableNewTracks)
|
|
256
|
+
if( !this.disableNewTracks )
|
|
245
257
|
{
|
|
246
258
|
panel.addButton('', '<i class = "fa-solid fa-plus"></i>', (value, event) => {
|
|
247
259
|
this.addNewTrack();
|
|
248
260
|
}, {width: "40px", height: "40px"});
|
|
249
261
|
}
|
|
262
|
+
|
|
250
263
|
panel.endLine();
|
|
251
264
|
|
|
252
|
-
const styles = window.getComputedStyle(title);
|
|
265
|
+
const styles = window.getComputedStyle( title );
|
|
253
266
|
const titleHeight = title.clientHeight + parseFloat(styles['marginTop']) + parseFloat(styles['marginBottom']);
|
|
254
267
|
|
|
255
268
|
let p = new LX.Panel({height: "calc(100% - " + titleHeight + "px)"});
|
|
256
|
-
|
|
257
|
-
|
|
269
|
+
|
|
270
|
+
if( this.animationClip && this.selectedItems.length )
|
|
271
|
+
{
|
|
272
|
+
let items = { 'id': '', 'children': [] };
|
|
258
273
|
|
|
259
274
|
const tracksPerItem = this.animationClip.tracksPerItem;
|
|
260
|
-
for(let i = 0; i < this.selectedItems.length; i++ )
|
|
261
|
-
|
|
275
|
+
for( let i = 0; i < this.selectedItems.length; i++ )
|
|
276
|
+
{
|
|
277
|
+
let selected = this.selectedItems[ i ];
|
|
262
278
|
let t = {
|
|
263
279
|
'id': selected,
|
|
264
280
|
'skipVisibility': true,
|
|
265
281
|
'children': []
|
|
266
282
|
}
|
|
267
|
-
for(let j = 0; j < tracksPerItem[selected].length; j++)
|
|
283
|
+
for( let j = 0; j < tracksPerItem[selected].length; j++ )
|
|
284
|
+
{
|
|
268
285
|
let track = tracksPerItem[selected][j];
|
|
269
286
|
let id = track.type ? track.type : track.name;
|
|
270
287
|
|
|
@@ -301,7 +318,9 @@ class Timeline {
|
|
|
301
318
|
}]})
|
|
302
319
|
// panel.addTitle(track.name + (track.type? '(' + track.type + ')' : ''));
|
|
303
320
|
}
|
|
304
|
-
|
|
321
|
+
|
|
322
|
+
items.children.push( t );
|
|
323
|
+
|
|
305
324
|
let el = p.addTree(null, t, {filter: false, rename: false, draggable: false, onevent: (e) => {
|
|
306
325
|
switch(e.type) {
|
|
307
326
|
case LX.TreeEvent.NODE_SELECTED:
|
|
@@ -317,12 +336,14 @@ class Timeline {
|
|
|
317
336
|
}
|
|
318
337
|
break;
|
|
319
338
|
case LX.TreeEvent.NODE_VISIBILITY:
|
|
320
|
-
if (e.node.parent)
|
|
321
|
-
|
|
339
|
+
if ( e.node.parent )
|
|
340
|
+
{
|
|
341
|
+
const tracksInItem = this.animationClip.tracksPerItem[ e.node.parent.id ];
|
|
322
342
|
const type = e.node.id;
|
|
323
343
|
for(let i = 0; i < tracksInItem.length; i++) {
|
|
324
|
-
if(tracksInItem[i].type == type)
|
|
325
|
-
|
|
344
|
+
if(tracksInItem[i].type == type)
|
|
345
|
+
{
|
|
346
|
+
this.changeTrackVisibility( tracksInItem[ i ].clipIdx, e.value );
|
|
326
347
|
break;
|
|
327
348
|
}
|
|
328
349
|
}
|
|
@@ -330,8 +351,9 @@ class Timeline {
|
|
|
330
351
|
break;
|
|
331
352
|
case LX.TreeEvent.NODE_CARETCHANGED:
|
|
332
353
|
const tracksInItem = this.animationClip.tracksPerItem[e.node.id];
|
|
333
|
-
for( let i = 0; i < tracksInItem; ++i )
|
|
334
|
-
|
|
354
|
+
for( let i = 0; i < tracksInItem; ++i )
|
|
355
|
+
{
|
|
356
|
+
this.changeTrackDisplay( tracksInItem[ i ].clipIdx, e.node.closed );
|
|
335
357
|
}
|
|
336
358
|
break;
|
|
337
359
|
}
|
|
@@ -339,19 +361,23 @@ class Timeline {
|
|
|
339
361
|
|
|
340
362
|
}
|
|
341
363
|
}
|
|
342
|
-
|
|
364
|
+
|
|
365
|
+
panel.attach( p.root )
|
|
343
366
|
p.root.style.overflowY = "scroll";
|
|
344
|
-
p.root.addEventListener("scroll",
|
|
367
|
+
p.root.addEventListener("scroll", e => {
|
|
345
368
|
this.currentScroll = e.currentTarget.scrollTop/(e.currentTarget.scrollHeight - e.currentTarget.clientHeight);
|
|
346
|
-
|
|
369
|
+
});
|
|
347
370
|
// for(let i = 0; i < this.animationClip.tracks.length; i++) {
|
|
348
371
|
// let track = this.animationClip.tracks[i];
|
|
349
372
|
// panel.addTitle(track.name + (track.type? '(' + track.type + ')' : ''));
|
|
350
373
|
// }
|
|
351
|
-
this.leftPanel.root.children[1].scrollTop = scrollTop;
|
|
374
|
+
this.leftPanel.root.children[ 1 ].scrollTop = scrollTop;
|
|
352
375
|
|
|
353
|
-
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
|
+
{
|
|
354
378
|
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
355
381
|
this.resizeCanvas([ this.root.root.clientWidth - this.leftPanel.root.clientWidth - 8, this.size[1]]);
|
|
356
382
|
}
|
|
357
383
|
|
|
@@ -361,8 +387,10 @@ class Timeline {
|
|
|
361
387
|
|
|
362
388
|
addNewTrack() {
|
|
363
389
|
|
|
364
|
-
if(!this.animationClip)
|
|
390
|
+
if( !this.animationClip )
|
|
391
|
+
{
|
|
365
392
|
this.animationClip = {tracks:[]};
|
|
393
|
+
}
|
|
366
394
|
|
|
367
395
|
let trackInfo = {
|
|
368
396
|
idx: this.animationClip.tracks.length,
|
|
@@ -370,7 +398,7 @@ class Timeline {
|
|
|
370
398
|
selected: [], edited: [], hovered: []
|
|
371
399
|
};
|
|
372
400
|
|
|
373
|
-
this.animationClip.tracks.push(trackInfo);
|
|
401
|
+
this.animationClip.tracks.push( trackInfo );
|
|
374
402
|
this.updateLeftPanel();
|
|
375
403
|
return trackInfo.idx;
|
|
376
404
|
}
|
|
@@ -380,30 +408,36 @@ class Timeline {
|
|
|
380
408
|
let tracks = [];
|
|
381
409
|
|
|
382
410
|
// Manage negative selection
|
|
383
|
-
if(minY > maxY)
|
|
411
|
+
if( minY > maxY )
|
|
412
|
+
{
|
|
384
413
|
let aux = minY;
|
|
385
414
|
minY = maxY;
|
|
386
415
|
maxY = aux;
|
|
387
416
|
}
|
|
388
417
|
|
|
389
|
-
for(let i = this.tracksDrawn.length - 1; i >= 0; --i)
|
|
390
|
-
|
|
391
|
-
let
|
|
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 ];
|
|
392
422
|
if( pos + threshold >= minY && (pos + size - threshold) <= maxY ) {
|
|
393
|
-
tracks.push( t[0] );
|
|
423
|
+
tracks.push( t[ 0 ] );
|
|
394
424
|
}
|
|
395
425
|
}
|
|
396
426
|
|
|
397
427
|
return tracks;
|
|
398
428
|
}
|
|
399
429
|
|
|
400
|
-
getCurrentContent(track, time, threshold) {
|
|
430
|
+
getCurrentContent( track, time, threshold ) {
|
|
401
431
|
|
|
402
|
-
if(this.getCurrentKeyFrame)
|
|
403
|
-
|
|
432
|
+
if( this.getCurrentKeyFrame )
|
|
433
|
+
{
|
|
434
|
+
return this.getCurrentKeyFrame( track, time, threshold );
|
|
435
|
+
}
|
|
404
436
|
|
|
405
|
-
if(this.getCurrentClip)
|
|
406
|
-
|
|
437
|
+
if( this.getCurrentClip )
|
|
438
|
+
{
|
|
439
|
+
return this.getCurrentClip( track, time, threshold );
|
|
440
|
+
}
|
|
407
441
|
}
|
|
408
442
|
|
|
409
443
|
/**
|
|
@@ -414,17 +448,21 @@ class Timeline {
|
|
|
414
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
|
|
415
449
|
*/
|
|
416
450
|
setAnimationClip( animation, needsToProcess = true ) {
|
|
417
|
-
|
|
451
|
+
|
|
452
|
+
if ( this.unSelectAllKeyFrames )
|
|
453
|
+
{
|
|
418
454
|
this.unSelectAllKeyFrames();
|
|
419
455
|
this.unHoverAll();
|
|
420
456
|
this.unSelectAllTracks();
|
|
421
457
|
this.selectedItems = [];
|
|
422
458
|
}
|
|
423
459
|
|
|
424
|
-
if(!animation || !animation.tracks || needsToProcess)
|
|
425
|
-
|
|
460
|
+
if( !animation || !animation.tracks || needsToProcess )
|
|
461
|
+
{
|
|
462
|
+
this.processTracks( animation ); // generate default animationclip or process the user's one
|
|
426
463
|
}
|
|
427
|
-
else
|
|
464
|
+
else
|
|
465
|
+
{
|
|
428
466
|
this.animationClip = animation;
|
|
429
467
|
}
|
|
430
468
|
|
|
@@ -433,12 +471,13 @@ class Timeline {
|
|
|
433
471
|
|
|
434
472
|
//this.updateHeader();
|
|
435
473
|
this.updateLeftPanel();
|
|
474
|
+
|
|
436
475
|
return this.animationClip;
|
|
437
476
|
}
|
|
438
477
|
|
|
439
|
-
drawTimeInfo
|
|
478
|
+
drawTimeInfo( w, h = this.topMargin ) {
|
|
440
479
|
|
|
441
|
-
let ctx = this.canvas.getContext("2d");
|
|
480
|
+
let ctx = this.canvas.getContext( "2d" );
|
|
442
481
|
ctx.font = "11px " + Timeline.FONT;//"11px Calibri";
|
|
443
482
|
ctx.textAlign = "center";
|
|
444
483
|
|
|
@@ -451,57 +490,57 @@ class Timeline {
|
|
|
451
490
|
ctx.strokeStyle = LX.Timeline.FONT_COLOR;
|
|
452
491
|
|
|
453
492
|
// set tick and sub tick times
|
|
454
|
-
let
|
|
455
|
-
if ( this.secondsToPixels > 900 ){
|
|
456
|
-
else if ( this.secondsToPixels > 100 ){
|
|
457
|
-
else if ( this.secondsToPixels > 50 ){
|
|
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; }
|
|
458
497
|
|
|
459
|
-
let
|
|
460
|
-
|
|
498
|
+
let subtickTime = this.timeSeparators[tickTime - 1];
|
|
499
|
+
tickTime = this.timeSeparators[tickTime];
|
|
461
500
|
|
|
462
|
-
//
|
|
463
|
-
let
|
|
464
|
-
let
|
|
501
|
+
// Transform times into pixel coords
|
|
502
|
+
let tickX = this.timeToX( this.startTime + tickTime ) - this.timeToX( this.startTime );
|
|
503
|
+
let subtickX = subtickTime * tickX / tickTime;
|
|
465
504
|
|
|
466
|
-
let startx = this.timeToX( Math.floor( this.startTime /
|
|
505
|
+
let startx = this.timeToX( Math.floor( this.startTime / tickTime) * tickTime ); // floor because might need to draw previous subticks
|
|
467
506
|
let endx = this.timeToX( this.endTime ); // draw up to endTime
|
|
468
507
|
|
|
469
|
-
//
|
|
508
|
+
// Begin drawing
|
|
470
509
|
ctx.beginPath();
|
|
471
510
|
ctx.fillStyle = Timeline.FONT_COLOR//"#888";
|
|
472
511
|
ctx.globalAlpha = this.opacity;
|
|
473
512
|
|
|
474
|
-
for( let x = startx; x <= endx; x +=
|
|
475
|
-
|
|
476
|
-
//
|
|
477
|
-
ctx.moveTo(Math.round(x) + 0.5, h * 0.4 + h * 0.3 );
|
|
478
|
-
ctx.lineTo(Math.round(x) + 0.5, h * 0.95 );
|
|
479
|
-
|
|
480
|
-
//
|
|
481
|
-
let endsub = x +
|
|
482
|
-
for (let
|
|
483
|
-
|
|
484
|
-
ctx.
|
|
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 );
|
|
485
525
|
}
|
|
486
526
|
|
|
487
|
-
//
|
|
527
|
+
// Draw time number
|
|
488
528
|
let t = this.xToTime( x );
|
|
489
|
-
ctx.fillText( t.toFixed(
|
|
529
|
+
ctx.fillText( t.toFixed( tickTime < 1 ? 1 : 0 ), x, h * 0.6 );
|
|
490
530
|
}
|
|
491
531
|
|
|
492
532
|
ctx.stroke();
|
|
493
|
-
|
|
494
|
-
|
|
495
533
|
ctx.restore();
|
|
496
534
|
}
|
|
497
535
|
|
|
498
|
-
drawTracksBackground(w, h) {
|
|
536
|
+
drawTracksBackground( w, h ) {
|
|
499
537
|
|
|
500
538
|
let canvas = this.canvas;
|
|
501
539
|
let ctx = canvas.getContext("2d");
|
|
502
540
|
let duration = this.duration;
|
|
503
541
|
ctx.globalAlpha = this.opacity;
|
|
504
|
-
|
|
542
|
+
|
|
543
|
+
// Content
|
|
505
544
|
let margin = this.session.left_margin;
|
|
506
545
|
let timeline_height = this.topMargin;
|
|
507
546
|
let line_height = this.trackHeight;
|
|
@@ -1160,21 +1199,38 @@ class Timeline {
|
|
|
1160
1199
|
* // NOTE: to select a track from outside of the timeline, a this.leftPanelTrackTree.select(item) needs to be called.
|
|
1161
1200
|
*/
|
|
1162
1201
|
selectTrack( trackIdx ) {
|
|
1202
|
+
|
|
1203
|
+
if( !this.animationClip )
|
|
1204
|
+
{
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1163
1208
|
this.unSelectAllTracks();
|
|
1164
1209
|
|
|
1165
|
-
let track = this.animationClip.tracks[trackIdx];
|
|
1210
|
+
let track = this.animationClip.tracks[ trackIdx ];
|
|
1166
1211
|
track.isSelected = true;
|
|
1167
1212
|
|
|
1168
|
-
if(this.onSelectTrack)
|
|
1213
|
+
if( this.onSelectTrack )
|
|
1214
|
+
{
|
|
1169
1215
|
this.onSelectTrack(track);
|
|
1216
|
+
}
|
|
1170
1217
|
}
|
|
1171
1218
|
|
|
1172
1219
|
unSelectAllTracks() {
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
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;
|
|
1178
1234
|
}
|
|
1179
1235
|
}
|
|
1180
1236
|
}
|