Skip to content

Commit 4e6b841

Browse files
authored
exporter: Update --frames to accept "all" to export all frames
Co-authored-by: AeroXuk <[email protected]>
1 parent a60f831 commit 4e6b841

File tree

1 file changed

+62
-17
lines changed

1 file changed

+62
-17
lines changed

exporter/src/lib.rs

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ use ruffle_render_wgpu::wgpu;
1515
use std::any::Any;
1616
use std::fs::create_dir_all;
1717
use std::io::{self, Write};
18+
use std::num::NonZeroUsize;
1819
use std::panic::catch_unwind;
1920
use std::path::{Path, PathBuf};
21+
use std::str::FromStr;
2022
use std::sync::Arc;
2123
use std::sync::Mutex;
2224
use walkdir::{DirEntry, WalkDir};
@@ -36,6 +38,29 @@ pub struct SizeOpt {
3638
height: Option<u32>,
3739
}
3840

41+
#[derive(Debug, Clone, Copy)]
42+
enum FrameSelection {
43+
All,
44+
Count(NonZeroUsize),
45+
}
46+
47+
impl FromStr for FrameSelection {
48+
type Err = String;
49+
50+
fn from_str(s: &str) -> Result<Self, Self::Err> {
51+
let s_lower = s.to_ascii_lowercase();
52+
if s_lower == "all" {
53+
Ok(FrameSelection::All)
54+
} else if let Ok(n) = s.parse::<u32>() {
55+
let non_zero = NonZeroUsize::new(n as usize)
56+
.ok_or_else(|| "Frame count must be greater than 0".to_string())?;
57+
Ok(FrameSelection::Count(non_zero))
58+
} else {
59+
Err(format!("Invalid value for --frames: {s}"))
60+
}
61+
}
62+
}
63+
3964
#[derive(Parser, Debug)]
4065
#[clap(name = "Ruffle Exporter", author, version)]
4166
pub struct Opt {
@@ -51,9 +76,9 @@ pub struct Opt {
5176
#[clap(name = "output")]
5277
output_path: Option<PathBuf>,
5378

54-
/// Number of frames to capture per file
79+
/// Number of frames to capture per file. Use 'all' to capture all frames.
5580
#[clap(short = 'f', long = "frames", default_value = "1")]
56-
frames: u32,
81+
frames: FrameSelection,
5782

5883
/// Number of frames to skip
5984
#[clap(long = "skipframes", default_value = "0")]
@@ -91,7 +116,7 @@ pub struct Opt {
91116
fn take_screenshot(
92117
descriptors: Arc<Descriptors>,
93118
swf_path: &Path,
94-
frames: u32,
119+
frames: FrameSelection, // TODO Figure out a way to get framecount before calling take_screenshot, so that we can have accurate progress bars when using --frames all
95120
skipframes: u32,
96121
progress: &Option<ProgressBar>,
97122
size: SizeOpt,
@@ -122,7 +147,15 @@ fn take_screenshot(
122147
.build();
123148

124149
let mut result = Vec::new();
125-
let totalframes = frames + skipframes;
150+
let totalframes = match frames {
151+
FrameSelection::All => player.lock().unwrap().mutate_with_update_context(|ctx| {
152+
ctx.stage
153+
.root_clip()
154+
.and_then(|root_clip| root_clip.as_movie_clip())
155+
.map_or(1, |movie_clip| movie_clip.total_frames() as u32)
156+
}),
157+
FrameSelection::Count(n) => n.get() as u32 + skipframes,
158+
};
126159

127160
for i in 0..totalframes {
128161
if let Some(progress) = &progress {
@@ -164,8 +197,10 @@ fn take_screenshot(
164197
}
165198
}
166199

167-
if let Some(progress) = &progress {
168-
progress.inc(1);
200+
if !matches!(frames, FrameSelection::All) {
201+
if let Some(progress) = &progress {
202+
progress.inc(1);
203+
}
169204
}
170205
}
171206
Ok(result)
@@ -225,18 +260,21 @@ fn capture_single_swf(descriptors: Arc<Descriptors>, opt: &Opt) -> Result<()> {
225260
let output = opt.output_path.clone().unwrap_or_else(|| {
226261
let mut result = PathBuf::new();
227262
result.set_file_name(opt.swf.file_stem().unwrap());
228-
if opt.frames == 1 {
263+
if matches!(opt.frames, FrameSelection::Count(n) if n.get() == 1) {
229264
result.set_extension("png");
230265
}
231266
result
232267
});
233268

234-
if opt.frames > 1 {
269+
if !matches!(opt.frames, FrameSelection::Count(n) if n.get() == 1) {
235270
let _ = create_dir_all(&output);
236271
}
237272

238273
let progress = if !opt.silent {
239-
let progress = ProgressBar::new(opt.frames as u64);
274+
let progress = match opt.frames {
275+
FrameSelection::Count(n) => ProgressBar::new(n.get() as u64),
276+
_ => ProgressBar::new_spinner(), // TODO Once we figure out a way to get framecount before calling take_screenshot, then this can be changed back to a progress bar when using --frames all
277+
};
240278
progress.set_style(
241279
ProgressStyle::with_template(
242280
"[{elapsed_precise}] {bar:40.cyan/blue} [{eta_precise}] {pos:>7}/{len:7} {msg}",
@@ -320,7 +358,10 @@ fn capture_multiple_swfs(descriptors: Arc<Descriptors>, opt: &Opt) -> Result<()>
320358
let files = find_files(&opt.swf, !opt.silent);
321359

322360
let progress = if !opt.silent {
323-
let progress = ProgressBar::new((files.len() as u64) * (opt.frames as u64));
361+
let progress = match opt.frames {
362+
FrameSelection::Count(n) => ProgressBar::new((files.len() as u64) * (n.get() as u64)),
363+
_ => ProgressBar::new(files.len() as u64),
364+
};
324365
progress.set_style(
325366
ProgressStyle::with_template(
326367
"[{elapsed_precise}] {bar:40.cyan/blue} [{eta_precise}] {pos:>7}/{len:7} {msg}",
@@ -383,19 +424,23 @@ fn capture_multiple_swfs(descriptors: Arc<Descriptors>, opt: &Opt) -> Result<()>
383424
Ok(())
384425
})?;
385426

386-
let message = if opt.frames == 1 {
387-
format!(
427+
let message = match opt.frames {
428+
FrameSelection::Count(n) if n.get() == 1 => format!(
388429
"Saved first frame of {} files to {}",
389430
files.len(),
390431
output.to_string_lossy()
391-
)
392-
} else {
393-
format!(
432+
),
433+
FrameSelection::All => format!(
434+
"Saved all frames of {} files to {}",
435+
files.len(),
436+
output.to_string_lossy()
437+
),
438+
FrameSelection::Count(n) => format!(
394439
"Saved first {} frames of {} files to {}",
395-
opt.frames,
440+
n,
396441
files.len(),
397442
output.to_string_lossy()
398-
)
443+
),
399444
};
400445

401446
if let Some(progress) = progress {

0 commit comments

Comments
 (0)