lexgui 0.1.37 → 0.1.39

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/README.md CHANGED
@@ -91,11 +91,6 @@ Look at this [examples](https://jxarco.github.io/lexgui.js/examples/) to see how
91
91
  </tr>
92
92
  </table>
93
93
 
94
- ## Contributors
95
-
96
- * Alex Rodríguez @jxarco
97
- * Eva Valls @evallsg
98
-
99
94
  ## Feedback/Issues
100
95
 
101
- You can use the [repository issues section](https://github.com/jxarco/lexgui.js/issues) or simply write any feedback to alexroco.30@gmail.com.
96
+ You can use the [repository issues section](https://github.com/jxarco/lexgui.js/issues) or simply write any feedback to alexroco.30@gmail.com.
@@ -6,11 +6,6 @@ if(!LX) {
6
6
 
7
7
  LX.components.push( 'Audio' );
8
8
 
9
- function remapRange(oldValue, oldMin, oldMax, newMin, newMax)
10
- {
11
- return (((oldValue - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin;
12
- }
13
-
14
9
  /**
15
10
  * @method addKnob
16
11
  * @param {String} name Widget name
@@ -76,12 +71,12 @@ Panel.prototype.addKnob = function( name, value, min, max, callback, options = {
76
71
 
77
72
  let innerSetValue = function( v ) {
78
73
  // Convert val between (-135 and 135)
79
- const angle = remapRange( v, innerKnobCircle.min, innerKnobCircle.max, -135.0, 135.0 );
74
+ const angle = LX.remapRange( v, innerKnobCircle.min, innerKnobCircle.max, -135.0, 135.0 );
80
75
  innerKnobCircle.style.rotate = angle + 'deg';
81
76
  innerKnobCircle.value = v;
82
77
  }
83
78
 
84
- const angle = remapRange( value, min, max, -135.0, 135.0 );
79
+ const angle = LX.remapRange( value, min, max, -135.0, 135.0 );
85
80
  innerKnobCircle.style.rotate = angle + 'deg';
86
81
 
87
82
  if( options.disabled )
@@ -34,7 +34,7 @@ class Session {
34
34
  class Timeline {
35
35
 
36
36
  /**
37
- * @param {string} name
37
+ * @param {string} name = string unique id
38
38
  * @param {object} options = {animationClip, selectedItems, position = [0,0], width, height, canvas, trackHeight, skipLock, skipVisibility}
39
39
  */
40
40
  constructor( name, options = {} ) {
@@ -182,25 +182,14 @@ class Timeline {
182
182
  this.onBeforeCreateTopBar(header);
183
183
 
184
184
  header.addNumber("Current Time", this.currentTime, (value, event) => {
185
- if(value > this.duration) {
186
- value = this.duration;
187
- if(event.constructor != CustomEvent) {
188
- LX.emit( "@on_current_time_" + this.constructor.name, value);
189
- }
190
- }
191
-
192
- this.currentTime = value;
193
- if(this.onSetTime)
194
- this.onSetTime(this.currentTime);
195
-
196
- }, {signal: "@on_current_time_" + this.constructor.name, step: 0.01, min: 0, precision: 3, skipSlider: true});
185
+ this.setTime(value)}, {signal: "@on_set_time_" + this.name, step: 0.01, min: 0, precision: 3, skipSlider: true});
197
186
 
198
- header.addNumber("Duration", +this.duration.toFixed(3), (value, event) => {
199
- this.setDuration(value, false)}, {step: 0.01, min: 0, signal: "@on_set_duration"
187
+ header.addNumber("Duration", + this.duration.toFixed(3), (value, event) => {
188
+ this.setDuration(value, false)}, {step: 0.01, min: 0, signal: "@on_set_duration_" + this.name
200
189
  });
201
190
 
202
- header.addNumber("Speed", +this.speed.toFixed(3), (value, event) => {
203
- this.setSpeed(value)}, {step: 0.01});
191
+ header.addNumber("Speed", + this.speed.toFixed(3), (value, event) => {
192
+ this.setSpeed(value)}, {step: 0.01, signal: "@on_set_speed_" + this.name});
204
193
 
205
194
  if(this.onAfterCreateTopBar)
206
195
  this.onAfterCreateTopBar(header);
@@ -722,11 +711,11 @@ class Timeline {
722
711
  this.duration = this.animationClip.duration = v;
723
712
 
724
713
  if(updateHeader) {
725
- LX.emit( "@on_set_duration", +v.toFixed(3));
714
+ LX.emit( "@on_set_duration_" + this.name, +this.duration.toFixed(3)); // skipcallback = true
726
715
  }
727
716
 
728
717
  if( this.onSetDuration )
729
- this.onSetDuration( v );
718
+ this.onSetDuration( this.duration );
730
719
  }
731
720
 
732
721
  /**
@@ -746,11 +735,18 @@ class Timeline {
746
735
 
747
736
  setSpeed(speed) {
748
737
  this.speed = speed;
749
- LX.emit( "@on_set_speed", +speed.toFixed(3));
738
+ LX.emit( "@on_set_speed_" + this.name, +this.speed.toFixed(3)); // skipcallback = true
750
739
 
751
-
752
740
  if( this.onSetSpeed )
753
- this.onSetSpeed( speed );
741
+ this.onSetSpeed( this.speed );
742
+ }
743
+
744
+ setTime(time){
745
+ this.currentTime = Math.max(0,Math.min(time,this.duration));
746
+ LX.emit( "@on_set_time_" + this.name, +this.currentTime.toFixed(2)); // skipcallback = true
747
+
748
+ if(this.onSetTime)
749
+ this.onSetTime(this.currentTime);
754
750
  }
755
751
 
756
752
  // Converts distance in pixels to time
@@ -905,8 +901,7 @@ class Timeline {
905
901
  else if( e.localY < this.topMargin ){
906
902
  this.grabbing = true;
907
903
  this.grabbingTimeBar = true;
908
- this.currentTime = Math.min(this.duration, time);
909
- LX.emit( "@on_current_time_" + this.constructor.name, this.currentTime );
904
+ this.setTime(time);
910
905
  }
911
906
  else if( h < this.scrollableHeight && x > w - 10 ) { // grabbing scroll bar
912
907
  this.grabbing = true;
@@ -932,8 +927,7 @@ class Timeline {
932
927
  this.canvas.style.cursor = "grabbing";
933
928
  if(this.grabbingTimeBar && this.active)
934
929
  {
935
- this.currentTime = Math.min(this.duration, time);
936
- LX.emit( "@on_current_time_" + this.constructor.name, this.currentTime );
930
+ this.setTime(time);
937
931
  }
938
932
  else if(this.grabbingScroll)
939
933
  {
@@ -1325,16 +1319,19 @@ class KeyFramesTimeline extends Timeline {
1325
1319
  }
1326
1320
  }
1327
1321
  }
1328
- else if( !this.movingKeys && !discard ){ // if not moving moving timeline (just a click)
1322
+ else if( !this.movingKeys && !discard ){ // if not moving timeline and not adding keyframes through e.shiftkey (just a click)
1323
+
1324
+ if ( this.lastKeyFramesSelected.length ){
1325
+ if (this.onUnselectKeyFrames){
1326
+ this.onUnselectKeyFrames( this.lastKeyFramesSelected );
1327
+ }
1328
+ this.unSelectAllKeyFrames();
1329
+ }
1329
1330
  if (track){
1330
1331
  const keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.pixelsToSeconds * 5 );
1331
1332
  if( keyFrameIndex > -1 ) {
1332
1333
  this.processCurrentKeyFrame( e, keyFrameIndex, track, null, e.multipleSelection ); // Settings this as multiple so time is not being set
1333
- }else{
1334
- this.unSelectAllKeyFrames();
1335
1334
  }
1336
- }else{
1337
- this.unSelectAllKeyFrames();
1338
1335
  }
1339
1336
  }
1340
1337
 
@@ -1436,7 +1433,19 @@ class KeyFramesTimeline extends Timeline {
1436
1433
  }
1437
1434
  }
1438
1435
  this.lastKeyFramesSelected[idx][2] = k; // update keyframe index
1436
+ this.lastKeyFramesSelected[idx][4] = times[k]; // update keyframe time
1437
+ }
1438
+
1439
+ if ( this.onContentMoved ){
1440
+ for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
1441
+ const [name, localTrackIdx, keyIndex, trackIdx, originalKeyTime] = this.lastKeyFramesSelected[i];
1442
+ track = this.animationClip.tracks[trackIdx];
1443
+ if(track && track.locked)
1444
+ continue;
1445
+ this.onContentMoved(trackIdx, keyIndex);
1446
+ }
1439
1447
  }
1448
+
1440
1449
  return;
1441
1450
  }
1442
1451
 
@@ -1744,6 +1753,8 @@ class KeyFramesTimeline extends Timeline {
1744
1753
  let lastSavedIndex = 0;
1745
1754
  const lastIndex = times.length-1;
1746
1755
 
1756
+ this.saveState(track.clipIdx);
1757
+
1747
1758
  for ( let i = 1; i < lastIndex; ++ i ) {
1748
1759
 
1749
1760
  let keep = false;
@@ -1815,11 +1826,27 @@ class KeyFramesTimeline extends Timeline {
1815
1826
  if(!this.animationClip)
1816
1827
  return;
1817
1828
 
1829
+ // save all states into a single entry
1830
+ if ( this.trackStateSaveEnabler ){
1831
+ for( let i = 0; i < this.animationClip.tracks.length; ++i ) {
1832
+ this.saveState(i, i!=0);
1833
+ }
1834
+ }
1835
+
1836
+ // disable state saving
1837
+ const oldStateEnabler = this.trackStateSaveEnabler;
1838
+ this.trackStateSaveEnabler = false;
1839
+
1840
+ // optimize
1818
1841
  for( let i = 0; i < this.animationClip.tracks.length; ++i ) {
1819
1842
  const track = this.animationClip.tracks[i];
1820
1843
  this.optimizeTrack( track.clipIdx, onlyEqualTime, false );
1821
1844
  }
1822
1845
 
1846
+ // restore enabler status
1847
+ this.trackStateSaveEnabler = oldStateEnabler;
1848
+
1849
+ // callback
1823
1850
  if(this.onOptimizeTracks )
1824
1851
  this.onOptimizeTracks(-1); // signal as "all tracks"
1825
1852
  }
@@ -2082,9 +2109,6 @@ class KeyFramesTimeline extends Timeline {
2082
2109
  this.animationClip.tracks[ track.clipIdx ].values[i] = clipboardInfo.values[j];
2083
2110
  ++j;
2084
2111
  }
2085
- LX.emit( "@on_current_time_" + this.constructor.name, this.currentTime);
2086
- // if(this.onSetTime)
2087
- // this.onSetTime(this.currentTime);
2088
2112
 
2089
2113
  track.edited[ index ] = true;
2090
2114
  }
@@ -2327,8 +2351,8 @@ class KeyFramesTimeline extends Timeline {
2327
2351
  }
2328
2352
 
2329
2353
  getTrack( trackInfo ) {
2330
- const [name, trackIndex] = trackInfo;
2331
- return this.animationClip.tracksPerItem[ name ][trackIndex];
2354
+ const [name, localTrackIndex] = trackInfo;
2355
+ return this.animationClip.tracksPerItem[ name ][localTrackIndex];
2332
2356
  }
2333
2357
 
2334
2358
  getTrackName( uglyName ) {
@@ -2490,7 +2514,7 @@ class KeyFramesTimeline extends Timeline {
2490
2514
  let selection = [track.name, track.idx, frameIdx, track.clipIdx, track.times[frameIdx]];
2491
2515
  const trackIdx = track.clipIdx;
2492
2516
 
2493
- // sort lastkeyframeselected ascending order
2517
+ // sort lastkeyframeselected ascending order (track and frame)
2494
2518
  let i = 0;
2495
2519
  for( ; i < this.lastKeyFramesSelected.length; ++i){
2496
2520
  let s = this.lastKeyFramesSelected[i];
@@ -2554,8 +2578,7 @@ class KeyFramesTimeline extends Timeline {
2554
2578
  }
2555
2579
 
2556
2580
  if( !multiple ) {
2557
- this.currentTime = this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ];
2558
- LX.emit( "@on_current_time_" + this.constructor.name, track.times[ keyFrameIndex ]);
2581
+ this.setTime(this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ]);
2559
2582
  }
2560
2583
  }
2561
2584
 
@@ -3832,7 +3855,7 @@ class CurvesTimeline extends Timeline {
3832
3855
 
3833
3856
  super(name, options);
3834
3857
 
3835
- this.valueBeforeMove = 0;
3858
+ this.keyValuePerPixel = 1/200; // used onMouseMove, vertical move
3836
3859
  this.range = options.range || [0, 1];
3837
3860
 
3838
3861
  if(this.animationClip && this.animationClip.tracks.length)
@@ -3874,16 +3897,19 @@ class CurvesTimeline extends Timeline {
3874
3897
  }
3875
3898
  }
3876
3899
  }
3877
- else if( !this.movingKeys && !discard ){ // if not moving moving timeline (just a click)
3900
+ else if( !this.movingKeys && !discard ){ // if not moving timeline and not adding keyframes through e.shiftkey (just a click)
3901
+
3902
+ if ( this.lastKeyFramesSelected.length ){
3903
+ if (this.onUnselectKeyFrames){
3904
+ this.onUnselectKeyFrames( this.lastKeyFramesSelected );
3905
+ }
3906
+ this.unSelectAllKeyFrames();
3907
+ }
3878
3908
  if (track){
3879
3909
  const keyFrameIndex = this.getCurrentKeyFrame( track, this.xToTime( localX ), this.pixelsToSeconds * 5 );
3880
3910
  if( keyFrameIndex > -1 ) {
3881
3911
  this.processCurrentKeyFrame( e, keyFrameIndex, track, null, e.multipleSelection ); // Settings this as multiple so time is not being set
3882
- }else{
3883
- this.unSelectAllKeyFrames();
3884
3912
  }
3885
- }else{
3886
- this.unSelectAllKeyFrames();
3887
3913
  }
3888
3914
  }
3889
3915
 
@@ -3897,7 +3923,7 @@ class CurvesTimeline extends Timeline {
3897
3923
  let localY = e.localY;
3898
3924
  let track = e.track;
3899
3925
 
3900
- if(e.ctrlKey && this.lastKeyFramesSelected.length) { // move keyframes
3926
+ if( (e.ctrlKey || e.altKey) && this.lastKeyFramesSelected.length) { // move keyframes
3901
3927
  this.movingKeys = true;
3902
3928
  this.canvas.style.cursor = "grab";
3903
3929
  this.canvas.classList.add('grabbing');
@@ -3940,52 +3966,87 @@ class CurvesTimeline extends Timeline {
3940
3966
 
3941
3967
  if(this.movingKeys) { // move keyframes
3942
3968
 
3969
+ // update where is mouse
3943
3970
  let newTime = this.xToTime( localX );
3944
3971
  let deltaTime = newTime - this.timeBeforeMove;
3945
3972
  if ( deltaTime + this.moveKeyMinTime < 0 ){
3946
3973
  deltaTime = -this.moveKeyMinTime;
3947
3974
  }
3948
3975
  this.timeBeforeMove = this.timeBeforeMove + deltaTime;
3949
- this.moveKeyMinTime += deltaTime;
3950
3976
 
3951
- for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
3952
- let idx = i;
3953
- if ( deltaTime > 0 ){
3954
- idx = this.lastKeyFramesSelected.length - 1 - i;
3955
- }
3956
-
3957
- const [name, localTrackIdx, keyIndex, trackIdx, originalKeyTime] = this.lastKeyFramesSelected[idx];
3958
- track = this.animationClip.tracksPerItem[name][localTrackIdx];
3959
- if(track && track.locked)
3960
- continue;
3977
+ // move keyframes horizontally (change time)
3978
+ if ( e.ctrlKey ){
3979
+ this.moveKeyMinTime += deltaTime;
3980
+ const tracksPerItem = this.animationClip.tracksPerItem;
3981
+ for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
3982
+ let idx = i;
3983
+ if ( deltaTime > 0 ){
3984
+ idx = this.lastKeyFramesSelected.length - 1 - i;
3985
+ }
3986
+
3987
+ const [name, localTrackIdx, keyIndex, trackIdx, originalKeyTime] = this.lastKeyFramesSelected[idx];
3988
+ track = tracksPerItem[name][localTrackIdx];
3989
+ if(track && track.locked)
3990
+ continue;
3961
3991
 
3962
- this.canvas.style.cursor = "grabbing";
3992
+ this.canvas.style.cursor = "grabbing";
3963
3993
 
3964
- const times = this.animationClip.tracks[ track.clipIdx ].times;
3965
- times[ keyIndex ] = Math.max(0,times[keyIndex] + deltaTime);
3966
- if (times[ keyIndex ] > this.duration){
3967
- this.setDuration(times[ keyIndex ]);
3968
- }
3994
+ const times = this.animationClip.tracks[ track.clipIdx ].times;
3995
+ times[ keyIndex ] = Math.max(0,times[keyIndex] + deltaTime);
3996
+ if (times[ keyIndex ] > this.duration){
3997
+ this.setDuration(times[ keyIndex ]);
3998
+ }
3969
3999
 
3970
- // sort keyframe
3971
- let k = keyIndex;
3972
- if ( deltaTime > 0 ){
3973
- for( ; k < times.length-1; ++k ){
3974
- if ( times[k] < times[k+1] ){
3975
- break;
4000
+ // sort keyframe
4001
+ let k = keyIndex;
4002
+ if ( deltaTime > 0 ){
4003
+ for( ; k < times.length-1; ++k ){
4004
+ if ( times[k] < times[k+1] ){
4005
+ break;
4006
+ }
4007
+ this.swapKeyFrames(track, k+1, k);
3976
4008
  }
3977
- this.swapKeyFrames(track, k+1, k);
3978
- }
3979
- }else{
3980
- for( ; k > 0; --k ){
3981
- if ( times[k-1] < times[k] ){
3982
- break;
4009
+ }else{
4010
+ for( ; k > 0; --k ){
4011
+ if ( times[k-1] < times[k] ){
4012
+ break;
4013
+ }
4014
+ this.swapKeyFrames(track, k-1, k);
3983
4015
  }
3984
- this.swapKeyFrames(track, k-1, k);
4016
+ }
4017
+ this.lastKeyFramesSelected[idx][2] = k; // update keyframe index
4018
+ this.lastKeyFramesSelected[idx][4] = times[k]; // update keyframe time
4019
+ }
4020
+
4021
+ if ( this.onContentMoved ){
4022
+ for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
4023
+ const [name, localTrackIdx, keyIndex, trackIdx, originalKeyTime] = this.lastKeyFramesSelected[i];
4024
+ track = this.animationClip.tracks[trackIdx];
4025
+ if(track && track.locked)
4026
+ continue;
4027
+ this.onContentMoved(trackIdx, keyIndex);
4028
+ }
4029
+ }
4030
+ }
4031
+
4032
+ // move keyframes vertically (change values instead of time)
4033
+ if ( e.altKey ){
4034
+ for( let i = 0; i < this.lastKeyFramesSelected.length; ++i ){
4035
+ const [name, localTrackIdx, keyIndex, trackIdx, originalKeyTime] = this.lastKeyFramesSelected[i];
4036
+ track = this.animationClip.tracks[trackIdx];
4037
+ if(track && track.locked)
4038
+ continue;
4039
+ let value = track.values[keyIndex];
4040
+ let delta = e.deltay * this.keyValuePerPixel * (this.range[1]-this.range[0]);
4041
+ track.values[keyIndex] = Math.max(this.range[0], Math.min(this.range[1], value - delta)); // invert delta because of screen y
4042
+ track.edited[keyIndex] = true;
4043
+
4044
+ if ( this.onUpdateTrack ){
4045
+ this.onUpdateTrack( track.clipIdx );
3985
4046
  }
3986
4047
  }
3987
- this.lastKeyFramesSelected[idx][2] = k; // update keyframe index
3988
4048
  }
4049
+
3989
4050
  return;
3990
4051
  }
3991
4052
 
@@ -4563,7 +4624,7 @@ class CurvesTimeline extends Timeline {
4563
4624
  if(!this.clipboard)
4564
4625
  this.clipboard = {};
4565
4626
 
4566
- this.clipboard = {
4627
+ this.clipboard.value = {
4567
4628
  type: track.type,
4568
4629
  values: values
4569
4630
  };
@@ -4640,10 +4701,6 @@ class CurvesTimeline extends Timeline {
4640
4701
  ++j;
4641
4702
  }
4642
4703
 
4643
- LX.emit( "@on_current_time_" + this.constructor.name, this.currentTime);
4644
- // if(this.onSetTime)
4645
- // this.onSetTime(this.currentTime);
4646
-
4647
4704
  track.edited[ index ] = true;
4648
4705
  }
4649
4706
 
@@ -4875,8 +4932,8 @@ class CurvesTimeline extends Timeline {
4875
4932
  }
4876
4933
 
4877
4934
  getTrack( trackInfo ) {
4878
- const [name, trackIndex] = trackInfo;
4879
- return this.animationClip.tracksPerItem[ name ][trackIndex];
4935
+ const [name, localTrackIndex] = trackInfo;
4936
+ return this.animationClip.tracksPerItem[ name ][localTrackIndex];
4880
4937
  }
4881
4938
 
4882
4939
  getTrackName( uglyName ) {
@@ -5103,8 +5160,7 @@ class CurvesTimeline extends Timeline {
5103
5160
  }
5104
5161
 
5105
5162
  if (!multiple){
5106
- this.currentTime = this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ];
5107
- LX.emit( "@on_current_time_" + this.constructor.name, this.currentTime );
5163
+ this.setTime(this.animationClip.tracks[t.clipIdx].times[ keyFrameIndex ]);
5108
5164
  }
5109
5165
  }
5110
5166
 
@@ -5236,4 +5292,4 @@ LX.UTILS.concatTypedArray = (arrays, ArrayType) => {
5236
5292
  return result;
5237
5293
  }
5238
5294
 
5239
- export { Timeline, KeyFramesTimeline, ClipsTimeline, CurvesTimeline };
5295
+ export { Timeline, KeyFramesTimeline, ClipsTimeline, CurvesTimeline };
package/build/lexgui.css CHANGED
@@ -1351,6 +1351,40 @@ input[type="range"] {
1351
1351
  right: 0.8em;
1352
1352
  }
1353
1353
 
1354
+ .lexwidget .lexunit {
1355
+ -webkit-user-select: none; /* Safari 3.1+ */
1356
+ -moz-user-select: none; /* Firefox 2+ */
1357
+ -ms-user-select: none; /* IE 10+ */
1358
+ user-select: none; /* Standard syntax */
1359
+ }
1360
+
1361
+ /* Size Widget */
1362
+
1363
+ .lexwidget .lexsizecross {
1364
+ color: var(--global-selected);
1365
+ font-weight: 800;
1366
+ }
1367
+
1368
+ /* Pad Widget */
1369
+
1370
+ .lexwidget .lexpad {
1371
+ place-items: center;
1372
+ }
1373
+
1374
+ .lexwidget .lexpad .lexinnerpad {
1375
+ border-radius: 4px;
1376
+ background-color: var(--global-dark-background);
1377
+ }
1378
+
1379
+ .lexwidget .lexpad .lexinnerpad .lexpadthumb {
1380
+ background-color: var(--global-selected-light);
1381
+ width: 10%;
1382
+ height: 10%;
1383
+ border-radius: 2px;
1384
+ transform: translate(0px, 0px);
1385
+ }
1386
+
1387
+
1354
1388
  /* Tabs Widget */
1355
1389
 
1356
1390
  .lextabscontainer {