lexgui 0.7.9 → 0.7.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.
- package/build/extensions/codeeditor.js +4 -0
- package/build/extensions/timeline.js +72 -19
- package/build/extensions/videoeditor.js +262 -172
- package/build/lexgui.css +33 -5
- package/build/lexgui.js +141 -87
- package/build/lexgui.min.css +2 -2
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +165 -111
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +28 -1
- package/examples/area-tabs.html +1 -1
- package/examples/asset-view.html +27 -1
- package/examples/timeline.html +23 -13
- package/examples/video-editor.html +152 -3
- package/examples/video-editor2.html +5 -5
- package/package.json +1 -1
|
@@ -1299,6 +1299,10 @@ class CodeEditor
|
|
|
1299
1299
|
this.codeArea.root.style.height = `calc(100% - ${ this._fullVerticalOffset }px)`;
|
|
1300
1300
|
}, 50 );
|
|
1301
1301
|
|
|
1302
|
+
if( options.callback )
|
|
1303
|
+
{
|
|
1304
|
+
options.callback.call( this, this );
|
|
1305
|
+
}
|
|
1302
1306
|
});
|
|
1303
1307
|
|
|
1304
1308
|
window.editor = this;
|
|
@@ -64,7 +64,8 @@ class Timeline {
|
|
|
64
64
|
this.pixelsPerSecond = 300;
|
|
65
65
|
this.secondsPerPixel = 1 / this.pixelsPerSecond;
|
|
66
66
|
this.animationClip = this.instantiateAnimationClip();
|
|
67
|
-
|
|
67
|
+
|
|
68
|
+
this.trackHeight = 32;
|
|
68
69
|
this.timeSeparators = [0.01, 0.1, 0.5, 1, 5];
|
|
69
70
|
|
|
70
71
|
this.boxSelection = false;
|
|
@@ -301,7 +302,7 @@ class Timeline {
|
|
|
301
302
|
|
|
302
303
|
const panel = this.leftPanel;
|
|
303
304
|
|
|
304
|
-
panel.sameLine(
|
|
305
|
+
panel.sameLine();
|
|
305
306
|
let titleComponent = panel.addTitle( "Tracks", { style: { background: "none"}, className: "fg-secondary text-lg px-4"} );
|
|
306
307
|
let title = titleComponent.root;
|
|
307
308
|
|
|
@@ -341,6 +342,18 @@ class Timeline {
|
|
|
341
342
|
}
|
|
342
343
|
break;
|
|
343
344
|
case LX.TreeEvent.NODE_CARETCHANGED:
|
|
345
|
+
if ( !this.trackTreesComponent ){ return;}
|
|
346
|
+
/* hack
|
|
347
|
+
On NODE_CARETCHANGED, the html are regenerated. TrackHeight need to be forced on the htmls again.
|
|
348
|
+
This event is called BEFORE the regeneration, so a setTimeout of 1ms is called.
|
|
349
|
+
To avoid a flicker, hide the element while it is changing and show it again afterwards
|
|
350
|
+
*/
|
|
351
|
+
this.trackTreesComponent.root.classList.add("hidden");
|
|
352
|
+
setTimeout( ()=>{
|
|
353
|
+
this.setTrackHeight(this.trackHeight);
|
|
354
|
+
this.trackTreesComponent.root.classList.remove("hidden");
|
|
355
|
+
}, 1);
|
|
356
|
+
|
|
344
357
|
break;
|
|
345
358
|
}
|
|
346
359
|
}});
|
|
@@ -362,6 +375,7 @@ class Timeline {
|
|
|
362
375
|
});
|
|
363
376
|
|
|
364
377
|
this.trackTreesPanel.root.scrollTop = this.currentScrollInPixels;
|
|
378
|
+
this.setTrackHeight( this.trackHeight );
|
|
365
379
|
|
|
366
380
|
if( this.leftPanel.parent.root.classList.contains("hidden") || !this.root.parentElement ){
|
|
367
381
|
return;
|
|
@@ -370,6 +384,23 @@ class Timeline {
|
|
|
370
384
|
this.resizeCanvas();
|
|
371
385
|
}
|
|
372
386
|
|
|
387
|
+
setTrackHeight( trackHeight ){
|
|
388
|
+
// ul list has a "gap" of 0.25rem. Compute pixel count of 0.25 rem
|
|
389
|
+
const gapSize = parseFloat(getComputedStyle(document.documentElement).fontSize) * 0.25;
|
|
390
|
+
|
|
391
|
+
this.trackHeight = trackHeight = Math.max(gapSize, trackHeight);
|
|
392
|
+
|
|
393
|
+
if ( !this.trackTreesComponent ){
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
trackHeight -= gapSize;
|
|
398
|
+
const tracks = this.trackTreesComponent.root.querySelector("ul").children;
|
|
399
|
+
for( let i = 0; i < tracks.length; ++i ){
|
|
400
|
+
tracks[i].style.height = trackHeight + "px";
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
373
404
|
/**
|
|
374
405
|
* @param {object} options options for the new track
|
|
375
406
|
* { id: string, active: bool, locked: bool, }
|
|
@@ -583,11 +614,6 @@ class Timeline {
|
|
|
583
614
|
const scrollableHeight = this.trackTreesComponent.root.scrollHeight;
|
|
584
615
|
// tree has gaps of 0.25rem (4px) inbetween entries but not in the beginning nor ending. Move half gap upwards.
|
|
585
616
|
const treeOffset = this.lastTrackTreesComponentOffset = this.trackTreesComponent.innerTree.domEl.offsetTop - this.canvas.offsetTop -2;
|
|
586
|
-
|
|
587
|
-
if ( this.trackTreesPanel.root.scrollHeight > 0 ){
|
|
588
|
-
const ul = this.trackTreesComponent.innerTree.domEl.children[0];
|
|
589
|
-
this.trackHeight = ul.children.length < 1 ? 25 : ((ul.offsetHeight+4) / ul.children.length);
|
|
590
|
-
}
|
|
591
617
|
|
|
592
618
|
//zoom
|
|
593
619
|
let startTime = this.visualOriginTime; //seconds
|
|
@@ -1418,6 +1444,9 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1418
1444
|
this.defaultCurves = true; // whn a track with dim == 1 has no curves attribute, defaultCurves will be used instead. If true, track is rendered using curves
|
|
1419
1445
|
this.defaultCurvesRange = [0,1]; // whn a track with dim == 1 has no curves attribute, defaultCurves will be used instead. If true, track is rendered using curves
|
|
1420
1446
|
|
|
1447
|
+
this.keyframeSize = this.trackHeight * 0.5; // height of keyframe
|
|
1448
|
+
this.keyframeSizeHovered = this.trackHeight * 0.5 + 5;
|
|
1449
|
+
|
|
1421
1450
|
if(this.animationClip) {
|
|
1422
1451
|
this.setAnimationClip(this.animationClip);
|
|
1423
1452
|
}
|
|
@@ -1751,6 +1780,16 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1751
1780
|
return null;
|
|
1752
1781
|
}
|
|
1753
1782
|
|
|
1783
|
+
/**
|
|
1784
|
+
*
|
|
1785
|
+
* @param {number} size pixels, height of keyframe
|
|
1786
|
+
* @param {number} sizeHovered optional, size in pixels when hovered
|
|
1787
|
+
*/
|
|
1788
|
+
setKeyframeSize( size, sizeHovered = null ){
|
|
1789
|
+
this.keyframeSizeHovered = sizeHovered ?? size;
|
|
1790
|
+
this.keyframeSize = size;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1754
1793
|
onMouseUp( e, time ) {
|
|
1755
1794
|
|
|
1756
1795
|
let track = e.track;
|
|
@@ -1957,7 +1996,8 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1957
1996
|
else if(track) {
|
|
1958
1997
|
|
|
1959
1998
|
this.unHoverAll();
|
|
1960
|
-
|
|
1999
|
+
const thresholdPixels = track.curves? this.keyframeSize : (Math.SQRT2 * this.keyframeSize);
|
|
2000
|
+
let keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * thresholdPixels * 0.5 );
|
|
1961
2001
|
if(keyFrameIndex > -1 ) {
|
|
1962
2002
|
if(track && track.locked)
|
|
1963
2003
|
return;
|
|
@@ -2026,7 +2066,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2026
2066
|
if ( !e.track ){ return; }
|
|
2027
2067
|
const values = new Float32Array( e.track.dim );
|
|
2028
2068
|
values.fill(0);
|
|
2029
|
-
this.addKeyFrames( e.track, values, [this.currentTime] );
|
|
2069
|
+
this.addKeyFrames( e.track.trackIdx, values, [this.currentTime] );
|
|
2030
2070
|
}
|
|
2031
2071
|
}
|
|
2032
2072
|
);
|
|
@@ -2075,9 +2115,21 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2075
2115
|
const visibleElements = this.getVisibleItems();
|
|
2076
2116
|
|
|
2077
2117
|
let offset = scrollY;
|
|
2118
|
+
|
|
2119
|
+
// compute track from which to start rendering (avoid rendering unseen tracks)
|
|
2120
|
+
let startElIdx = 0;
|
|
2121
|
+
if ( offset < -this.lastTrackTreesComponentOffset ){ // offset 0 = (0 of canvas) + track-Tree-Offset. This renders tracks under the time zone
|
|
2122
|
+
startElIdx = Math.floor( -(offset + this.lastTrackTreesComponentOffset) / this.trackHeight ); // how many tracks to skip
|
|
2123
|
+
offset += startElIdx * this.trackHeight;
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2078
2126
|
ctx.translate(0, offset);
|
|
2079
2127
|
|
|
2080
|
-
|
|
2128
|
+
// compute track to end rendering (avoid rendering unseen tracks)
|
|
2129
|
+
let endElIdx = startElIdx + Math.ceil( ( ctx.canvas.height - this.lastTrackTreesComponentOffset - offset ) / this.trackHeight );
|
|
2130
|
+
endElIdx = endElIdx > visibleElements.length ? visibleElements.length : endElIdx;
|
|
2131
|
+
|
|
2132
|
+
for(let t = startElIdx; t < endElIdx; t++) {
|
|
2081
2133
|
const track = visibleElements[t].treeData.trackData;
|
|
2082
2134
|
|
|
2083
2135
|
if (track){
|
|
@@ -2088,7 +2140,6 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2088
2140
|
}
|
|
2089
2141
|
}
|
|
2090
2142
|
|
|
2091
|
-
offset += trackHeight;
|
|
2092
2143
|
ctx.translate(0, trackHeight);
|
|
2093
2144
|
}
|
|
2094
2145
|
|
|
@@ -2115,6 +2166,8 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2115
2166
|
const keyframes = track.times;
|
|
2116
2167
|
const startTime = this.visualTimeRange[0];
|
|
2117
2168
|
const endTime = this.visualTimeRange[1] + 0.0000001;
|
|
2169
|
+
const defaultPointSize = Math.SQRT2 * this.keyframeSize * 0.5; // pythagoras with equal sides h2 = c2 + c2 = 2 * c2
|
|
2170
|
+
const hoverPointSize = Math.SQRT2 * this.keyframeSizeHovered * 0.5;
|
|
2118
2171
|
|
|
2119
2172
|
for(let j = 0; j < keyframes.length; ++j)
|
|
2120
2173
|
{
|
|
@@ -2124,7 +2177,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2124
2177
|
}
|
|
2125
2178
|
|
|
2126
2179
|
let keyframePosX = this.timeToX( time );
|
|
2127
|
-
let size =
|
|
2180
|
+
let size = defaultPointSize;
|
|
2128
2181
|
|
|
2129
2182
|
if(!this.active || track.active == false) {
|
|
2130
2183
|
ctx.fillStyle = Timeline.KEYFRAME_COLOR_INACTIVE;
|
|
@@ -2133,7 +2186,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2133
2186
|
ctx.fillStyle = Timeline.KEYFRAME_COLOR_LOCK;
|
|
2134
2187
|
}
|
|
2135
2188
|
else if(track.hovered[j]) {
|
|
2136
|
-
size =
|
|
2189
|
+
size = hoverPointSize;
|
|
2137
2190
|
ctx.fillStyle = Timeline.KEYFRAME_COLOR_HOVERED;
|
|
2138
2191
|
}
|
|
2139
2192
|
else if(track.selected[j]) {
|
|
@@ -2166,8 +2219,8 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2166
2219
|
ctx.globalAlpha = 1;
|
|
2167
2220
|
const keyframes = track.times;
|
|
2168
2221
|
const values = track.values;
|
|
2169
|
-
const defaultPointSize = 5;
|
|
2170
|
-
const hoverPointSize =
|
|
2222
|
+
const defaultPointSize = this.keyframeSize * 0.5; // radius
|
|
2223
|
+
const hoverPointSize = this.keyframeSizeHovered * 0.5; // radius
|
|
2171
2224
|
const valueRange = track.curvesRange; //[min, max]
|
|
2172
2225
|
const displayRange = trackHeight - defaultPointSize * 2;
|
|
2173
2226
|
const startTime = this.visualTimeRange[0];
|
|
@@ -2179,7 +2232,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2179
2232
|
if ( keyframes.length > 1){
|
|
2180
2233
|
let startPosX = this.timeToX( keyframes[0] );
|
|
2181
2234
|
let startValue = values[0];
|
|
2182
|
-
startValue = ((startValue - valueRange[0]) / (valueRange[1] - valueRange[0])) * (-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2235
|
+
startValue = LX.clamp((startValue - valueRange[0]) / (valueRange[1] - valueRange[0]), 0,1) * (-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2183
2236
|
ctx.moveTo( startPosX, startValue );
|
|
2184
2237
|
|
|
2185
2238
|
for(let j = 1; j < keyframes.length; ++j){
|
|
@@ -2187,7 +2240,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2187
2240
|
let time = keyframes[j];
|
|
2188
2241
|
let keyframePosX = this.timeToX( time );
|
|
2189
2242
|
let value = values[j];
|
|
2190
|
-
value = ((value - valueRange[0]) / (valueRange[1] - valueRange[0])) * (-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2243
|
+
value = LX.clamp((value - valueRange[0]) / (valueRange[1] - valueRange[0]), 0,1) * (-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2191
2244
|
|
|
2192
2245
|
if( time < startTime ){
|
|
2193
2246
|
ctx.moveTo( keyframePosX, value );
|
|
@@ -2199,7 +2252,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2199
2252
|
let dt = keyframePosX - lastKeyframePosX;
|
|
2200
2253
|
if ( dt > 0 ){
|
|
2201
2254
|
let lastValue = values[j-1];
|
|
2202
|
-
lastValue = ((lastValue - valueRange[0]) / (valueRange[1] - valueRange[0])) * (-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2255
|
+
lastValue = LX.clamp((lastValue - valueRange[0]) / (valueRange[1] - valueRange[0]), 0,1) * (-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2203
2256
|
let f = (this.timeToX( endTime ) - lastKeyframePosX) / dt;
|
|
2204
2257
|
ctx.lineTo( lastKeyframePosX + dt * f, lastValue * (1-f) + value * f );
|
|
2205
2258
|
}
|
|
@@ -2239,7 +2292,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2239
2292
|
ctx.fillStyle = Timeline.KEYFRAME_COLOR
|
|
2240
2293
|
|
|
2241
2294
|
let value = values[j];
|
|
2242
|
-
value = ((value - valueRange[0]) / (valueRange[1] - valueRange[0])) *(-displayRange) + (trackHeight - defaultPointSize); // normalize and offset
|
|
2295
|
+
value = LX.clamp((value - valueRange[0]) / (valueRange[1] - valueRange[0]), 0,1) *(-displayRange) + (trackHeight - defaultPointSize); // normalize, clamp and offset
|
|
2243
2296
|
|
|
2244
2297
|
ctx.beginPath();
|
|
2245
2298
|
ctx.arc( keyframePosX, value, size, 0, Math.PI * 2);
|