lexgui 0.7.10 → 0.7.11
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/timeline.js +73 -99
- package/build/lexgui.js +281 -260
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +305 -284
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +21 -1
- package/examples/editor.html +2 -2
- package/package.json +1 -1
|
@@ -6,6 +6,9 @@ if(!LX) {
|
|
|
6
6
|
|
|
7
7
|
LX.extensions.push( 'Timeline' );
|
|
8
8
|
|
|
9
|
+
LX.registerIcon("TimelineLock", '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path fill="none" d="M7 11V7a4 4 0 0 1 9 0v4 M5,11h13 a2 2 0 0 1 2 2 v7 a2 2 0 0 1 -2 2 h-13 a2 2 0 0 1 -2 -2 v-7 a2 2 0 0 1 2 -2 M12 16 v2"/></svg>' );
|
|
10
|
+
LX.registerIcon("TimelineLockOpen", '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path fill="none" d="M14 11V7a4 4 0 0 1 9 0v2 M3,11h13 a2 2 0 0 1 2 2 v7 a2 2 0 0 1 -2 2 h-13 a2 2 0 0 1 -2 -2 v-7 a2 2 0 0 1 2 -2 M8 17 h3"/></svg>' );
|
|
11
|
+
|
|
9
12
|
/**
|
|
10
13
|
* @class Timeline
|
|
11
14
|
* @description Agnostic timeline, do not impose any timeline content. Renders to a canvas
|
|
@@ -341,22 +344,20 @@ class Timeline {
|
|
|
341
344
|
this.setTrackState( e.node.trackData.trackIdx, e.value );
|
|
342
345
|
}
|
|
343
346
|
break;
|
|
344
|
-
|
|
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);
|
|
347
|
+
}
|
|
356
348
|
|
|
357
|
-
|
|
349
|
+
if ( this.onTrackTreeEvent ){
|
|
350
|
+
this.onTrackTreeEvent(e);
|
|
358
351
|
}
|
|
359
352
|
}});
|
|
353
|
+
|
|
354
|
+
const that = this;
|
|
355
|
+
this.trackTreesComponent.innerTree._refresh = this.trackTreesComponent.innerTree.refresh;
|
|
356
|
+
this.trackTreesComponent.innerTree.refresh = function( newData, selectedId ){
|
|
357
|
+
this._refresh( newData, selectedId );
|
|
358
|
+
that.setTrackHeight( that.trackHeight );
|
|
359
|
+
}
|
|
360
|
+
|
|
360
361
|
// setting a name in the addTree function adds an undesired node
|
|
361
362
|
this.trackTreesComponent.name = "tracksTrees";
|
|
362
363
|
p.components[this.trackTreesComponent.name] = this.trackTreesComponent;
|
|
@@ -382,6 +383,9 @@ class Timeline {
|
|
|
382
383
|
}
|
|
383
384
|
|
|
384
385
|
this.resizeCanvas();
|
|
386
|
+
|
|
387
|
+
this.setScroll( this.currentScroll ); // avoid scroll bugs
|
|
388
|
+
|
|
385
389
|
}
|
|
386
390
|
|
|
387
391
|
setTrackHeight( trackHeight ){
|
|
@@ -1332,25 +1336,12 @@ class Timeline {
|
|
|
1332
1336
|
const track = this.selectedItems[ i ];
|
|
1333
1337
|
treeTracks.push({'trackData': track, 'id': track.id, 'skipVisibility': this.skipVisibility, visible: track.active, 'children':[], actions : this.skipLock ? null : [{
|
|
1334
1338
|
'name':'Lock edition',
|
|
1335
|
-
'icon': (track.locked ? '
|
|
1336
|
-
'swap': (track.locked ? '
|
|
1337
|
-
'callback': (node,
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
if(value) {
|
|
1341
|
-
el.title = 'Lock edition';
|
|
1342
|
-
el.classList.remove('Lock');
|
|
1343
|
-
el.classList.add('LockOpen');
|
|
1344
|
-
}
|
|
1345
|
-
else {
|
|
1346
|
-
el.title = 'Unlock edition';
|
|
1347
|
-
el.classList.remove('LockOpen');
|
|
1348
|
-
el.classList.add('Lock');
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
node.trackData.locked = !value;
|
|
1339
|
+
'icon': (track.locked ? 'TimelineLock' : 'TimelineLockOpen'),
|
|
1340
|
+
'swap': (track.locked ? 'TimelineLockOpen' : 'TimelineLock'),
|
|
1341
|
+
'callback': (node, swapValue, event) => {
|
|
1342
|
+
node.trackData.locked = !node.trackData.locked;
|
|
1352
1343
|
if(this.onLockTrack){
|
|
1353
|
-
this.onLockTrack(
|
|
1344
|
+
this.onLockTrack(node.trackData, node);
|
|
1354
1345
|
}
|
|
1355
1346
|
}
|
|
1356
1347
|
}]});
|
|
@@ -1466,25 +1457,12 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1466
1457
|
const track = itemTracks[j];
|
|
1467
1458
|
nodes.push({'trackData': track, 'id': track.id, 'skipVisibility': this.skipVisibility, visible: track.active, 'children':[], actions : this.skipLock ? null : [{
|
|
1468
1459
|
'name':'Lock edition',
|
|
1469
|
-
'icon': (track.locked ? '
|
|
1470
|
-
'swap': (track.locked ? '
|
|
1471
|
-
'callback': (node,
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
if(value) {
|
|
1475
|
-
el.title = 'Lock edition';
|
|
1476
|
-
el.classList.remove('Lock');
|
|
1477
|
-
el.classList.add('LockOpen');
|
|
1478
|
-
}
|
|
1479
|
-
else {
|
|
1480
|
-
el.title = 'Unlock edition';
|
|
1481
|
-
el.classList.remove('LockOpen');
|
|
1482
|
-
el.classList.add('Lock');
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
node.trackData.locked = !value;
|
|
1460
|
+
'icon': (track.locked ? 'TimelineLock' : 'TimelineLockOpen'),
|
|
1461
|
+
'swap': (track.locked ? 'TimelineLockOpen' : 'TimelineLock'),
|
|
1462
|
+
'callback': (node, swapValue, event) => {
|
|
1463
|
+
node.trackData.locked = !node.trackData.locked;
|
|
1486
1464
|
if(this.onLockTrack){
|
|
1487
|
-
this.onLockTrack(
|
|
1465
|
+
this.onLockTrack(node.trackData, node);
|
|
1488
1466
|
}
|
|
1489
1467
|
}
|
|
1490
1468
|
}]});
|
|
@@ -1675,7 +1653,6 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1675
1653
|
}
|
|
1676
1654
|
}
|
|
1677
1655
|
}
|
|
1678
|
-
|
|
1679
1656
|
|
|
1680
1657
|
this.updateLeftPanel();
|
|
1681
1658
|
|
|
@@ -1799,7 +1776,8 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1799
1776
|
if(e.shiftKey) {
|
|
1800
1777
|
// Manual multiple selection
|
|
1801
1778
|
if(!discard && track) {
|
|
1802
|
-
const
|
|
1779
|
+
const thresholdPixels = this.keyframeSize * 0.5; // radius of circle (curves) or rotated square (keyframes)
|
|
1780
|
+
const keyFrameIdx = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * thresholdPixels );
|
|
1803
1781
|
if ( keyFrameIdx > -1 ){
|
|
1804
1782
|
track.selected[keyFrameIdx] ?
|
|
1805
1783
|
this.deselectKeyFrame(track.trackIdx, keyFrameIdx) :
|
|
@@ -1833,7 +1811,8 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1833
1811
|
this.deselectAllKeyFrames();
|
|
1834
1812
|
}
|
|
1835
1813
|
if (track){
|
|
1836
|
-
const
|
|
1814
|
+
const thresholdPixels = this.keyframeSize * 0.5; // radius of circle (curves) or rotated square (keyframes)
|
|
1815
|
+
const keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * thresholdPixels );
|
|
1837
1816
|
if( keyFrameIndex > -1 ) {
|
|
1838
1817
|
this.processSelectionKeyFrame( track.trackIdx, keyFrameIndex, false ); // Settings this as multiple so time is not being set
|
|
1839
1818
|
}
|
|
@@ -1850,7 +1829,7 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1850
1829
|
let localY = e.localY;
|
|
1851
1830
|
let track = e.track;
|
|
1852
1831
|
|
|
1853
|
-
if(e.ctrlKey && this.lastKeyFramesSelected.length) { // move keyframes
|
|
1832
|
+
if( (e.ctrlKey || e.altKey) && this.lastKeyFramesSelected.length) { // move keyframes
|
|
1854
1833
|
this.movingKeys = true;
|
|
1855
1834
|
this.canvas.style.cursor = "grab";
|
|
1856
1835
|
this.canvas.classList.add('grabbing');
|
|
@@ -1858,31 +1837,28 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1858
1837
|
// Set pre-move state
|
|
1859
1838
|
this.moveKeyMinTime = Infinity;
|
|
1860
1839
|
const tracks = this.animationClip.tracks;
|
|
1861
|
-
|
|
1840
|
+
let lastTrackIdx = -1;
|
|
1841
|
+
for(let selectedKey of this.lastKeyFramesSelected) { // WARNING assumes lasKeyFramesSelected is sorted, so all keyframes of the same track are grouped
|
|
1862
1842
|
let [trackIdx, keyIndex, keyTime] = selectedKey;
|
|
1863
1843
|
const track = tracks[trackIdx];
|
|
1844
|
+
|
|
1845
|
+
selectedKey[2] = track.times[keyIndex]; // update original time just in case
|
|
1864
1846
|
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
let s = 0;
|
|
1869
|
-
for( s = 0; s < state.length; ++s){
|
|
1870
|
-
if ( state[s].trackIdx == track.trackIdx ){ break; }
|
|
1871
|
-
}
|
|
1872
|
-
if( s == state.length ){
|
|
1847
|
+
if ( lastTrackIdx != trackIdx ){
|
|
1848
|
+
// save track states only once
|
|
1849
|
+
if (this.moveKeyMinTime < Infinity){
|
|
1873
1850
|
this.saveState(track.trackIdx, true);
|
|
1851
|
+
}else{
|
|
1852
|
+
this.saveState(track.trackIdx, false);
|
|
1874
1853
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1854
|
+
this.moveKeyMinTime = Math.min( this.moveKeyMinTime, selectedKey[2] );
|
|
1855
|
+
lastTrackIdx = trackIdx;
|
|
1877
1856
|
}
|
|
1878
1857
|
|
|
1879
|
-
selectedKey[2] = track.times[keyIndex]; // update original time just in case
|
|
1880
|
-
this.moveKeyMinTime = Math.min( this.moveKeyMinTime, selectedKey[2] );
|
|
1881
1858
|
}
|
|
1882
1859
|
|
|
1883
1860
|
this.timeBeforeMove = this.xToTime( localX );
|
|
1884
|
-
|
|
1885
|
-
else if( e.altKey ){ // if only altkey, do not grab timeline
|
|
1861
|
+
|
|
1886
1862
|
this.grabbing = false;
|
|
1887
1863
|
this.grabbingTimeBar = false;
|
|
1888
1864
|
}
|
|
@@ -1957,47 +1933,45 @@ class KeyFramesTimeline extends Timeline {
|
|
|
1957
1933
|
}
|
|
1958
1934
|
}
|
|
1959
1935
|
}
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1936
|
+
|
|
1937
|
+
// Track.dim == 1: move keyframes vertically (change values instead of time)
|
|
1938
|
+
// RELIES ON SORTED ARRAY OF lastKeyFramesSelected
|
|
1939
|
+
if ( e.altKey && e.buttons & 0x01 ){
|
|
1940
|
+
const tracks = this.animationClip.tracks;
|
|
1941
|
+
let lastTrackChanged = -1;
|
|
1942
|
+
for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
|
|
1943
|
+
const [trackIdx, keyIndex, originalKeyTime] = this.lastKeyFramesSelected[i];
|
|
1944
|
+
track = tracks[trackIdx];
|
|
1945
|
+
if(track.locked || track.dim != 1 || !track.curves){
|
|
1946
|
+
continue;
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
let value = track.values[keyIndex];
|
|
1950
|
+
let delta = e.deltay * this.keyValuePerPixel * (track.curvesRange[1]-track.curvesRange[0]);
|
|
1951
|
+
track.values[keyIndex] = Math.max(track.curvesRange[0], Math.min(track.curvesRange[1], value - delta)); // invert delta because of screen y
|
|
1952
|
+
track.edited[keyIndex] = true;
|
|
1953
|
+
|
|
1954
|
+
if ( this.onUpdateTrack && track.trackIdx != lastTrackChanged && lastTrackChanged > -1){ // do it only once all keyframes of the same track have been modified
|
|
1955
|
+
this.onUpdateTrack( [track.trackIdx] );
|
|
1956
|
+
}
|
|
1957
|
+
lastTrackChanged = track.trackIdx;
|
|
1975
1958
|
}
|
|
1976
|
-
|
|
1977
|
-
let value = track.values[keyIndex];
|
|
1978
|
-
let delta = e.deltay * this.keyValuePerPixel * (track.curvesRange[1]-track.curvesRange[0]);
|
|
1979
|
-
track.values[keyIndex] = Math.max(track.curvesRange[0], Math.min(track.curvesRange[1], value - delta)); // invert delta because of screen y
|
|
1980
|
-
track.edited[keyIndex] = true;
|
|
1981
|
-
|
|
1982
|
-
if ( this.onUpdateTrack && track.trackIdx != lastTrackChanged && lastTrackChanged > -1){ // do it only once all keyframes of the same track have been modified
|
|
1959
|
+
if( this.onUpdateTrack && lastTrackChanged > -1 ){ // do the last update, once the last track has been processed
|
|
1983
1960
|
this.onUpdateTrack( [track.trackIdx] );
|
|
1984
1961
|
}
|
|
1985
|
-
|
|
1986
|
-
}
|
|
1987
|
-
if( this.onUpdateTrack && lastTrackChanged > -1 ){ // do the last update, once the last track has been processed
|
|
1988
|
-
this.onUpdateTrack( [track.trackIdx] );
|
|
1962
|
+
return;
|
|
1989
1963
|
}
|
|
1990
|
-
return;
|
|
1991
1964
|
}
|
|
1992
1965
|
|
|
1966
|
+
|
|
1993
1967
|
if( this.grabbing && e.button != 2) {
|
|
1994
1968
|
|
|
1995
1969
|
}
|
|
1996
1970
|
else if(track) {
|
|
1997
1971
|
|
|
1998
1972
|
this.unHoverAll();
|
|
1999
|
-
const thresholdPixels =
|
|
2000
|
-
let keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * thresholdPixels
|
|
1973
|
+
const thresholdPixels = this.keyframeSize * 0.5; // radius of circle (curves) or rotated square (keyframes)
|
|
1974
|
+
let keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * thresholdPixels );
|
|
2001
1975
|
if(keyFrameIndex > -1 ) {
|
|
2002
1976
|
if(track && track.locked)
|
|
2003
1977
|
return;
|
|
@@ -2166,8 +2140,8 @@ class KeyFramesTimeline extends Timeline {
|
|
|
2166
2140
|
const keyframes = track.times;
|
|
2167
2141
|
const startTime = this.visualTimeRange[0];
|
|
2168
2142
|
const endTime = this.visualTimeRange[1] + 0.0000001;
|
|
2169
|
-
const defaultPointSize =
|
|
2170
|
-
const hoverPointSize =
|
|
2143
|
+
const defaultPointSize = this.keyframeSize / Math.SQRT2; // pythagoras with equal sides h2 = c2 + c2 = 2 * c2
|
|
2144
|
+
const hoverPointSize = this.keyframeSizeHovered / Math.SQRT2;
|
|
2171
2145
|
|
|
2172
2146
|
for(let j = 0; j < keyframes.length; ++j)
|
|
2173
2147
|
{
|