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.
@@ -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
- 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);
347
+ }
356
348
 
357
- break;
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 ? 'Lock' : 'LockOpen'),
1336
- 'swap': (track.locked ? 'LockOpen' : 'Lock'),
1337
- 'callback': (node, el) => {
1338
- let value = el.classList.contains('Lock');
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(el, node.trackData, node)
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 ? 'Lock' : 'LockOpen'),
1470
- 'swap': (track.locked ? 'LockOpen' : 'Lock'),
1471
- 'callback': (node, el) => {
1472
- let value = el.classList.contains('Lock');
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(el, node.trackData, node)
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 keyFrameIdx = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * 5 );
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 keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * 5 );
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
- for(let selectedKey of this.lastKeyFramesSelected) {
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
- // save track states only once
1866
- if (this.moveKeyMinTime < Infinity){
1867
- let state = this.historyUndo[this.historyUndo.length-1];
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
- }else{
1876
- this.saveState(track.trackIdx, false);
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
- if ( !e.altKey || !(e.buttons & 0x01) ){
1961
- return;
1962
- }
1963
- }
1964
-
1965
- // Track.dim == 1: move keyframes vertically (change values instead of time)
1966
- // RELIES ON SORTED ARRAY OF lastKeyFramesSelected
1967
- if ( e.altKey && e.buttons & 0x01 ){
1968
- const tracks = this.animationClip.tracks;
1969
- let lastTrackChanged = -1;
1970
- for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
1971
- const [trackIdx, keyIndex, originalKeyTime] = this.lastKeyFramesSelected[i];
1972
- track = tracks[trackIdx];
1973
- if(track.locked || track.dim != 1 || !track.curves){
1974
- continue;
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
- lastTrackChanged = track.trackIdx;
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 = track.curves? this.keyframeSize : (Math.SQRT2 * this.keyframeSize);
2000
- let keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.secondsPerPixel * thresholdPixels * 0.5 );
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 = Math.SQRT2 * this.keyframeSize * 0.5; // pythagoras with equal sides h2 = c2 + c2 = 2 * c2
2170
- const hoverPointSize = Math.SQRT2 * this.keyframeSizeHovered * 0.5;
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
  {