1
0
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:
Victor 2017-09-08 19:45:54 +03:00
parent aec580e60c
commit 3adc39f288
3 changed files with 66 additions and 2 deletions

View File

@ -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();
} }

View File

@ -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;
} }
} }

View File

@ -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)));
}
} }