Skip to content

Commit dc88115

Browse files
authored
Cinematic: fix initialization and serialization events
1 parent a0ac32d commit dc88115

1 file changed

Lines changed: 77 additions & 39 deletions

File tree

jme3-core/src/main/java/com/jme3/cinematic/Cinematic.java

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -54,46 +54,50 @@
5454
import java.util.logging.Logger;
5555

5656
/**
57-
* An appstate for composing and playing cutscenes in a game. The cinematic
58-
* schedules CinematicEvents over a timeline. Once the Cinematic created it has
59-
* to be attached to the stateManager.
57+
* An AppState for composing and playing cutscenes in a game.
6058
*
61-
* You can add various CinematicEvents to a Cinematic, see package
62-
* com.jme3.cinematic.events
59+
* <p>A cinematic schedules and plays {@link CinematicEvent}s over a timeline.
60+
* Once a Cinematic is created, you must attach it to the `AppStateManager` to
61+
* run it. You can add various `CinematicEvent`s, see the `com.jme3.cinematic.events`
62+
* package for built-in event types.
6363
*
64-
* Two main methods can be used to add an event :
64+
* <p>Events can be added in two main ways:
65+
* <ul>
66+
* <li>{@link Cinematic#addCinematicEvent(float, CinematicEvent)} adds an event
67+
* at a specific time from the cinematic's start.</li>
68+
* <li>{@link Cinematic#enqueueCinematicEvent(CinematicEvent)} adds events
69+
* one after another, with each starting at the end of the previous one.</li>
70+
* </ul>
6571
*
66-
* @see Cinematic#addCinematicEvent(float,
67-
* com.jme3.cinematic.events.CinematicEvent) , that adds an event at the given
68-
* time form the cinematic start.
72+
* <p>Playback can be controlled with methods like:
73+
* <ul>
74+
* <li>{@link Cinematic#play()}</li>
75+
* <li>{@link Cinematic#pause()}</li>
76+
* <li>{@link Cinematic#stop()}</li>
77+
* </ul>
6978
*
70-
* @see
71-
* Cinematic#enqueueCinematicEvent(com.jme3.cinematic.events.CinematicEvent)
72-
* that enqueue events one after the other according to their initialDuration
79+
* <p>Since `Cinematic` itself extends `CinematicEvent`, you can nest cinematics
80+
* within each other. Nested cinematics should not be attached to the `AppStateManager`.
7381
*
74-
* A Cinematic has convenient methods to manage playback:
75-
* @see Cinematic#play()
76-
* @see Cinematic#pause()
77-
* @see Cinematic#stop()
78-
*
79-
* A Cinematic is itself a CinematicEvent, meaning you can embed several
80-
* cinematics. Embedded cinematics must not be added to the stateManager though.
81-
*
82-
* Cinematic can handle several points of view by creating camera nodes
83-
* and activating them on schedule.
84-
* @see Cinematic#bindCamera(java.lang.String, com.jme3.renderer.Camera)
85-
* @see Cinematic#activateCamera(float, java.lang.String)
86-
* @see Cinematic#setActiveCamera(java.lang.String)
82+
* <p>This class also handles multiple camera points of view by creating and
83+
* activating camera nodes on a schedule.
84+
* <ul>
85+
* <li>{@link Cinematic#bindCamera(java.lang.String, com.jme3.renderer.Camera)}</li>
86+
* <li>{@link Cinematic#activateCamera(float, java.lang.String)}</li>
87+
* <li>{@link Cinematic#setActiveCamera(java.lang.String)}</li>
88+
* </ul>
8789
*
8890
* @author Nehon
8991
*/
9092
public class Cinematic extends AbstractCinematicEvent implements AppState {
9193

9294
private static final Logger logger = Logger.getLogger(Cinematic.class.getName());
95+
96+
private Application app;
9397
private Node scene;
9498
protected TimeLine timeLine = new TimeLine();
9599
private int lastFetchedKeyFrame = -1;
96-
private final List<CinematicEvent> cinematicEvents = new ArrayList<>();
100+
private List<CinematicEvent> cinematicEvents = new ArrayList<>();
97101
private Map<String, CameraNode> cameras = new HashMap<>();
98102
private CameraNode currentCam;
99103
private boolean initialized = false;
@@ -109,14 +113,30 @@ protected Cinematic() {
109113
super();
110114
}
111115

116+
/**
117+
* Creates a cinematic with a specific duration.
118+
*
119+
* @param initialDuration The total duration of the cinematic in seconds.
120+
*/
112121
public Cinematic(float initialDuration) {
113122
super(initialDuration);
114123
}
115124

125+
/**
126+
* Creates a cinematic that loops based on the provided loop mode.
127+
*
128+
* @param loopMode The loop mode. See {@link LoopMode}.
129+
*/
116130
public Cinematic(LoopMode loopMode) {
117131
super(loopMode);
118132
}
119133

134+
/**
135+
* Creates a cinematic with a specific duration and loop mode.
136+
*
137+
* @param initialDuration The total duration of the cinematic in seconds.
138+
* @param loopMode The loop mode. See {@link LoopMode}.
139+
*/
120140
public Cinematic(float initialDuration, LoopMode loopMode) {
121141
super(initialDuration, loopMode);
122142
}
@@ -221,10 +241,9 @@ public void onPause() {
221241
public void write(JmeExporter ex) throws IOException {
222242
super.write(ex);
223243
OutputCapsule oc = ex.getCapsule(this);
224-
oc.write(cinematicEvents.toArray(new CinematicEvent[cinematicEvents.size()]), "cinematicEvents", null);
244+
oc.writeSavableArrayList((ArrayList) cinematicEvents, "cinematicEvents", null);
225245
oc.writeStringSavableMap(cameras, "cameras", null);
226246
oc.write(timeLine, "timeLine", null);
227-
228247
}
229248

230249
/**
@@ -238,12 +257,7 @@ public void write(JmeExporter ex) throws IOException {
238257
public void read(JmeImporter im) throws IOException {
239258
super.read(im);
240259
InputCapsule ic = im.getCapsule(this);
241-
242-
Savable[] events = ic.readSavableArray("cinematicEvents", null);
243-
for (Savable c : events) {
244-
// addCinematicEvent(((CinematicEvent) c).getTime(), (CinematicEvent) c)
245-
cinematicEvents.add((CinematicEvent) c);
246-
}
260+
cinematicEvents = ic.readSavableArrayList("cinematicEvents", null);
247261
cameras = (Map<String, CameraNode>) ic.readStringSavableMap("cameras", null);
248262
timeLine = (TimeLine) ic.readSavable("timeLine", null);
249263
}
@@ -273,6 +287,7 @@ public void setSpeed(float speed) {
273287
*/
274288
@Override
275289
public void initialize(AppStateManager stateManager, Application app) {
290+
this.app = app;
276291
initEvent(app, this);
277292
for (CinematicEvent cinematicEvent : cinematicEvents) {
278293
cinematicEvent.initEvent(app, this);
@@ -443,7 +458,7 @@ public KeyFrame addCinematicEvent(float timeStamp, CinematicEvent cinematicEvent
443458
keyFrame.cinematicEvents.add(cinematicEvent);
444459
cinematicEvents.add(cinematicEvent);
445460
if (isInitialized()) {
446-
cinematicEvent.initEvent(null, this);
461+
cinematicEvent.initEvent(app, this);
447462
}
448463
return keyFrame;
449464
}
@@ -488,7 +503,6 @@ public boolean removeCinematicEvent(CinematicEvent cinematicEvent) {
488503
* @return true if the element has been removed
489504
*/
490505
public boolean removeCinematicEvent(float timeStamp, CinematicEvent cinematicEvent) {
491-
cinematicEvent.dispose();
492506
KeyFrame keyFrame = timeLine.getKeyFrameAtTime(timeStamp);
493507
return removeCinematicEvent(keyFrame, cinematicEvent);
494508
}
@@ -536,6 +550,9 @@ public void postRender() {
536550
*/
537551
@Override
538552
public void cleanup() {
553+
initialized = false;
554+
clear();
555+
clearCameras();
539556
}
540557

541558
/**
@@ -591,9 +608,9 @@ public CameraNode getCamera(String cameraName) {
591608
}
592609

593610
/**
594-
* enable/disable the camera control of the cameraNode of the current cam
611+
* Enables or disables the camera control of the cameraNode of the current cam.
595612
*
596-
* @param enabled
613+
* @param enabled `true` to enable, `false` to disable.
597614
*/
598615
private void setEnableCurrentCam(boolean enabled) {
599616
if (currentCam != null) {
@@ -713,6 +730,15 @@ public Node getScene() {
713730
return scene;
714731
}
715732

733+
/**
734+
* Gets the application instance associated with this cinematic.
735+
*
736+
* @return The application.
737+
*/
738+
public Application getApplication() {
739+
return app;
740+
}
741+
716742
/**
717743
* Remove all events from the Cinematic.
718744
*/
@@ -725,6 +751,18 @@ public void clear() {
725751
}
726752
}
727753

754+
/**
755+
* Clears all camera nodes bound to the cinematic from the scene node.
756+
* This method removes all previously bound CameraNodes and clears the
757+
* internal camera map, effectively detaching all cameras from the scene.
758+
*/
759+
public void clearCameras() {
760+
for (CameraNode cameraNode : cameras.values()) {
761+
scene.detachChild(cameraNode);
762+
}
763+
cameras.clear();
764+
}
765+
728766
/**
729767
* used internally to clean up the cinematic. Called when the clear() method
730768
* is called

0 commit comments

Comments
 (0)