mirror of
https://github.com/aNNiMON/HotaruFX.git
synced 2024-09-19 14:14:21 +03:00
Ability to pause and seek animation
This commit is contained in:
parent
aec580e60c
commit
3adc39f288
@ -34,6 +34,7 @@ import javafx.scene.control.TitledPane;
|
|||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import javafx.util.Duration;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.fxmisc.richtext.CodeArea;
|
import org.fxmisc.richtext.CodeArea;
|
||||||
import org.fxmisc.richtext.LineNumberFactory;
|
import org.fxmisc.richtext.LineNumberFactory;
|
||||||
@ -157,7 +158,17 @@ public class EditorController implements Initializable, DocumentListener {
|
|||||||
stage.initOwner(primaryStage);
|
stage.initOwner(primaryStage);
|
||||||
stage.initModality(Modality.WINDOW_MODAL);
|
stage.initModality(Modality.WINDOW_MODAL);
|
||||||
stage.setScene(composition.produceAnimationScene());
|
stage.setScene(composition.produceAnimationScene());
|
||||||
composition.getTimeline().getFxTimeline().play();
|
val timeline = composition.getTimeline();
|
||||||
|
timeline.getFxTimeline().currentTimeProperty().addListener((o, oldValue, d) -> {
|
||||||
|
val min = (int) d.toMinutes();
|
||||||
|
val durationSec = d.subtract(Duration.minutes(min));
|
||||||
|
val sec = (int) durationSec.toSeconds();
|
||||||
|
val durationMs = durationSec.subtract(Duration.seconds(sec));
|
||||||
|
val frame = (int) (durationMs.toMillis() * timeline.getFrameRate() / 1000d);
|
||||||
|
val allFrame = (int) (d.toMillis() * timeline.getFrameRate() / 1000d);
|
||||||
|
stage.setTitle(String.format("%02d:%02d.%02d %d", min, sec, frame, allFrame));
|
||||||
|
});
|
||||||
|
stage.setOnShown(e -> timeline.getFxTimeline().play());
|
||||||
stage.show();
|
stage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package com.annimon.hotarufx.visual;
|
|||||||
|
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -62,6 +63,30 @@ public class Composition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Scene produceAnimationScene() {
|
public Scene produceAnimationScene() {
|
||||||
return new Scene(scene.getGroup(), sceneWidth, sceneHeight, background);
|
val fxScene = new Scene(scene.getGroup(), sceneWidth, sceneHeight, background);
|
||||||
|
fxScene.setOnKeyPressed(e -> {
|
||||||
|
switch (e.getCode()) {
|
||||||
|
case SPACE:
|
||||||
|
timeline.togglePause();
|
||||||
|
break;
|
||||||
|
case BACK_SPACE:
|
||||||
|
timeline.getFxTimeline().playFromStart();
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
case RIGHT:
|
||||||
|
int sign = e.getCode() == KeyCode.LEFT ? -1 : 1;
|
||||||
|
if (e.isShiftDown()) {
|
||||||
|
timeline.seek(sign);
|
||||||
|
} else if (e.isControlDown()) {
|
||||||
|
timeline.seek(10 * sign);
|
||||||
|
} else if (e.isAltDown()) {
|
||||||
|
timeline.seek(30 * sign);
|
||||||
|
} else {
|
||||||
|
timeline.seekFrame(sign);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fxScene;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import javafx.animation.KeyValue;
|
|||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
public class TimeLine {
|
public class TimeLine {
|
||||||
|
|
||||||
@ -26,4 +27,31 @@ public class TimeLine {
|
|||||||
private Duration duration(KeyFrame keyFrame) {
|
private Duration duration(KeyFrame keyFrame) {
|
||||||
return Duration.millis(1000d * keyFrame.getFrame() / frameRate);
|
return Duration.millis(1000d * keyFrame.getFrame() / frameRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void togglePause() {
|
||||||
|
switch (fxTimeline.getStatus()) {
|
||||||
|
case PAUSED:
|
||||||
|
fxTimeline.play();
|
||||||
|
break;
|
||||||
|
case RUNNING:
|
||||||
|
fxTimeline.pause();
|
||||||
|
break;
|
||||||
|
case STOPPED:
|
||||||
|
fxTimeline.playFromStart();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seekFrame(final int value) {
|
||||||
|
fxTimeline.pause();
|
||||||
|
val offset = Duration.millis(1000d * Math.abs(value) / frameRate);
|
||||||
|
val now = fxTimeline.getCurrentTime();
|
||||||
|
val newDuration = value > 0 ? now.add(offset) : now.subtract(offset);
|
||||||
|
fxTimeline.jumpTo(newDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seek(final int sec) {
|
||||||
|
val now = fxTimeline.getCurrentTime();
|
||||||
|
fxTimeline.jumpTo(now.add(Duration.seconds(sec)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user