core: Don't run frame actions when seeking past end of timeline
If you goto past the final loaded frame of a timeline, for example, with gotoAndStop(9999), this seeks to the final frame on the timeline, but it doesn't run the actions on this frame. MovieClip::goto_frame now will not run the final frame actions if the target frame was not reached.
This commit is contained in:
parent
8aae07bbf3
commit
c079cb3bca
|
@ -391,12 +391,7 @@ pub fn goto_frame<'gc>(
|
|||
frame = frame.wrapping_sub(1);
|
||||
frame = frame.wrapping_add(i32::from(scene_offset));
|
||||
if frame >= 0 {
|
||||
let num_frames = movie_clip.total_frames();
|
||||
if frame > i32::from(num_frames) {
|
||||
movie_clip.goto_frame(context, num_frames, stop);
|
||||
} else {
|
||||
movie_clip.goto_frame(context, frame.saturating_add(1) as u16, stop);
|
||||
}
|
||||
movie_clip.goto_frame(context, frame.saturating_add(1) as u16, stop);
|
||||
}
|
||||
}
|
||||
val => {
|
||||
|
|
|
@ -450,8 +450,6 @@ impl<'gc> MovieClipData<'gc> {
|
|||
// Clamp frame number in bounds.
|
||||
if frame < 1 {
|
||||
frame = 1;
|
||||
} else if frame > self.total_frames() {
|
||||
frame = self.total_frames();
|
||||
}
|
||||
|
||||
if frame != self.current_frame() {
|
||||
|
@ -668,7 +666,17 @@ impl<'gc> MovieClipData<'gc> {
|
|||
let mut frame_pos = self.tag_stream_pos;
|
||||
let mut reader = self.reader(context);
|
||||
let mut index = 0;
|
||||
while self.current_frame() < frame {
|
||||
|
||||
let len = self.static_data.tag_stream_len as u64;
|
||||
// Sanity; let's make sure we don't seek way too far.
|
||||
// TODO: This should be self.frames_loaded() when we implement that.
|
||||
let clamped_frame = if frame <= self.total_frames() {
|
||||
frame
|
||||
} else {
|
||||
self.total_frames()
|
||||
};
|
||||
|
||||
while self.current_frame < clamped_frame && frame_pos < len {
|
||||
self.current_frame += 1;
|
||||
frame_pos = reader.get_inner().position();
|
||||
|
||||
|
@ -700,6 +708,7 @@ impl<'gc> MovieClipData<'gc> {
|
|||
};
|
||||
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
|
||||
}
|
||||
let hit_target_frame = self.current_frame == frame;
|
||||
|
||||
// Run the list of goto commands to actually create and update the display objects.
|
||||
let run_goto_command = |clip: &mut MovieClipData<'gc>,
|
||||
|
@ -749,9 +758,15 @@ impl<'gc> MovieClipData<'gc> {
|
|||
|
||||
// Next, run the final frame for the parent clip.
|
||||
// Re-run the final frame without display tags (DoAction, StartSound, etc.)
|
||||
self.current_frame = frame - 1;
|
||||
self.tag_stream_pos = frame_pos;
|
||||
self.run_frame_internal(self_display_object, context, false);
|
||||
// Note that this only happens if the frame exists and is loaded;
|
||||
// e.g. gotoAndStop(9999) displays the final frame, but actions don't run!
|
||||
if hit_target_frame {
|
||||
self.current_frame -= 1;
|
||||
self.tag_stream_pos = frame_pos;
|
||||
self.run_frame_internal(self_display_object, context, false);
|
||||
} else {
|
||||
self.current_frame = clamped_frame;
|
||||
}
|
||||
|
||||
// Finally, run frames for children that are placed on this frame.
|
||||
goto_commands
|
||||
|
|
Loading…
Reference in New Issue