Skip to content

Commit 0303bd6

Browse files
mockersfalice-i-cecileJMS55
authored
disable screenrecording on windows (#22130)
# Objective - Screen Recording is not ready to be exposed, and very hard to build on windows ## Solution - Disable it for now on windows --------- Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: JMS55 <[email protected]>
1 parent 5971710 commit 0303bd6

File tree

3 files changed

+155
-97
lines changed

3 files changed

+155
-97
lines changed

crates/bevy_dev_tools/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ keywords = ["bevy"]
1010

1111
[features]
1212
bevy_ci_testing = ["serde", "ron"]
13-
screenrecording = ["x264"]
13+
screenrecording = ["dep:x264"]
1414
webgl = ["bevy_render/webgl"]
1515
webgpu = ["bevy_render/webgpu"]
1616

@@ -40,6 +40,8 @@ bevy_state = { path = "../bevy_state", version = "0.18.0-dev" }
4040
serde = { version = "1.0", features = ["derive"], optional = true }
4141
ron = { version = "0.12", optional = true }
4242
tracing = { version = "0.1", default-features = false, features = ["std"] }
43+
44+
[target.'cfg(not(target_os = "windows"))'.dependencies]
4345
x264 = { version = "0.5.0", optional = true }
4446

4547
[lints]

crates/bevy_dev_tools/src/easy_screenshot.rs

Lines changed: 150 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
11
#[cfg(feature = "screenrecording")]
22
use core::time::Duration;
33
use std::time::{SystemTime, UNIX_EPOCH};
4-
#[cfg(feature = "screenrecording")]
5-
use std::{fs::File, io::Write, sync::mpsc::channel};
64

75
use bevy_app::{App, Plugin, Update};
86
use bevy_ecs::prelude::*;
9-
#[cfg(feature = "screenrecording")]
10-
use bevy_image::Image;
117
use bevy_input::{common_conditions::input_just_pressed, keyboard::KeyCode};
12-
#[cfg(feature = "screenrecording")]
13-
use bevy_render::view::screenshot::ScreenshotCaptured;
148
use bevy_render::view::screenshot::{save_to_disk, Screenshot};
15-
#[cfg(feature = "screenrecording")]
16-
use bevy_time::Time;
179
use bevy_window::{PrimaryWindow, Window};
18-
#[cfg(feature = "screenrecording")]
19-
use tracing::info;
20-
#[cfg(feature = "screenrecording")]
21-
use x264::{Colorspace, Encoder, Setup};
22-
#[cfg(feature = "screenrecording")]
10+
#[cfg(all(not(target_os = "windows"), feature = "screenrecording"))]
2311
pub use x264::{Preset, Tune};
2412

2513
/// File format the screenshot will be saved in
@@ -82,6 +70,50 @@ impl Plugin for EasyScreenshotPlugin {
8270
}
8371
}
8472

73+
/// Placeholder
74+
#[cfg(all(target_os = "windows", feature = "screenrecording"))]
75+
pub enum Preset {
76+
/// Placeholder
77+
Ultrafast,
78+
/// Placeholder
79+
Superfast,
80+
/// Placeholder
81+
Veryfast,
82+
/// Placeholder
83+
Faster,
84+
/// Placeholder
85+
Fast,
86+
/// Placeholder
87+
Medium,
88+
/// Placeholder
89+
Slow,
90+
/// Placeholder
91+
Slower,
92+
/// Placeholder
93+
Veryslow,
94+
/// Placeholder
95+
Placebo,
96+
}
97+
98+
/// Placeholder
99+
#[cfg(all(target_os = "windows", feature = "screenrecording"))]
100+
pub enum Tune {
101+
/// Placeholder
102+
None,
103+
/// Placeholder
104+
Film,
105+
/// Placeholder
106+
Animation,
107+
/// Placeholder
108+
Grain,
109+
/// Placeholder
110+
StillImage,
111+
/// Placeholder
112+
Psnr,
113+
/// Placeholder
114+
Ssim,
115+
}
116+
85117
#[cfg(feature = "screenrecording")]
86118
/// Add this plugin to your app to enable easy screen recording.
87119
pub struct EasyScreenRecordPlugin {
@@ -107,13 +139,6 @@ impl Default for EasyScreenRecordPlugin {
107139
}
108140
}
109141

110-
#[cfg(feature = "screenrecording")]
111-
enum RecordCommand {
112-
Start(String, Preset, Tune),
113-
Stop,
114-
Frame(Image),
115-
}
116-
117142
#[cfg(feature = "screenrecording")]
118143
/// Controls screen recording
119144
#[derive(Message)]
@@ -126,90 +151,118 @@ pub enum RecordScreen {
126151

127152
#[cfg(feature = "screenrecording")]
128153
impl Plugin for EasyScreenRecordPlugin {
154+
#[cfg_attr(
155+
target_os = "windows",
156+
expect(unused_variables, reason = "not working on windows")
157+
)]
129158
fn build(&self, app: &mut App) {
130-
let (tx, rx) = channel::<RecordCommand>();
159+
#[cfg(target_os = "windows")]
160+
{
161+
tracing::warn!("Screen recording is not currently supported on Windows: see https://github.com/bevyengine/bevy/issues/22132");
162+
}
163+
#[cfg(not(target_os = "windows"))]
164+
{
165+
use bevy_image::Image;
166+
use bevy_render::view::screenshot::ScreenshotCaptured;
167+
use bevy_time::Time;
168+
use std::{fs::File, io::Write, sync::mpsc::channel};
169+
use tracing::info;
170+
use x264::{Colorspace, Encoder, Setup};
131171

132-
let frame_time = self.frame_time;
172+
enum RecordCommand {
173+
Start(String, Preset, Tune),
174+
Stop,
175+
Frame(Image),
176+
}
133177

134-
std::thread::spawn(move || {
135-
let mut encoder: Option<Encoder> = None;
136-
let mut setup = None;
137-
let mut file: Option<File> = None;
138-
let mut frame = 0;
139-
loop {
140-
let Ok(next) = rx.recv() else {
141-
break;
142-
};
143-
match next {
144-
RecordCommand::Start(name, preset, tune) => {
145-
info!("starting recording at {}", name);
146-
file = Some(File::create(name).unwrap());
147-
setup = Some(Setup::preset(preset, tune, false, true).high());
148-
}
149-
RecordCommand::Stop => {
150-
info!("stopping recording");
151-
if let Some(encoder) = encoder.take() {
152-
let mut flush = encoder.flush();
153-
let mut file = file.take().unwrap();
154-
while let Some(result) = flush.next() {
155-
let (data, _) = result.unwrap();
156-
file.write_all(data.entirety()).unwrap();
157-
}
178+
let (tx, rx) = channel::<RecordCommand>();
179+
180+
let frame_time = self.frame_time;
181+
182+
std::thread::spawn(move || {
183+
let mut encoder: Option<Encoder> = None;
184+
let mut setup = None;
185+
let mut file: Option<File> = None;
186+
let mut frame = 0;
187+
loop {
188+
let Ok(next) = rx.recv() else {
189+
break;
190+
};
191+
match next {
192+
RecordCommand::Start(name, preset, tune) => {
193+
info!("starting recording at {}", name);
194+
file = Some(File::create(name).unwrap());
195+
setup = Some(Setup::preset(preset, tune, false, true).high());
158196
}
159-
}
160-
RecordCommand::Frame(image) => {
161-
if let Some(setup) = setup.take() {
162-
let mut new_encoder = setup
163-
.fps((1000 / frame_time.as_millis()) as u32, 1)
164-
.build(Colorspace::RGB, image.width() as i32, image.height() as i32)
165-
.unwrap();
166-
let headers = new_encoder.headers().unwrap();
167-
file.as_mut()
168-
.unwrap()
169-
.write_all(headers.entirety())
170-
.unwrap();
171-
encoder = Some(new_encoder);
197+
RecordCommand::Stop => {
198+
info!("stopping recording");
199+
if let Some(encoder) = encoder.take() {
200+
let mut flush = encoder.flush();
201+
let mut file = file.take().unwrap();
202+
while let Some(result) = flush.next() {
203+
let (data, _) = result.unwrap();
204+
file.write_all(data.entirety()).unwrap();
205+
}
206+
}
172207
}
173-
if let Some(encoder) = encoder.as_mut() {
174-
let pts = (frame_time.as_millis() * frame) as i64;
175-
176-
frame += 1;
177-
let (data, _) = encoder
178-
.encode(
179-
pts,
180-
x264::Image::rgb(
208+
RecordCommand::Frame(image) => {
209+
if let Some(setup) = setup.take() {
210+
let mut new_encoder = setup
211+
.fps((1000 / frame_time.as_millis()) as u32, 1)
212+
.build(
213+
Colorspace::RGB,
181214
image.width() as i32,
182215
image.height() as i32,
183-
&image.try_into_dynamic().unwrap().to_rgb8(),
184-
),
185-
)
186-
.unwrap();
187-
file.as_mut().unwrap().write_all(data.entirety()).unwrap();
216+
)
217+
.unwrap();
218+
let headers = new_encoder.headers().unwrap();
219+
file.as_mut()
220+
.unwrap()
221+
.write_all(headers.entirety())
222+
.unwrap();
223+
encoder = Some(new_encoder);
224+
}
225+
if let Some(encoder) = encoder.as_mut() {
226+
let pts = (frame_time.as_millis() * frame) as i64;
227+
228+
frame += 1;
229+
let (data, _) = encoder
230+
.encode(
231+
pts,
232+
x264::Image::rgb(
233+
image.width() as i32,
234+
image.height() as i32,
235+
&image.try_into_dynamic().unwrap().to_rgb8(),
236+
),
237+
)
238+
.unwrap();
239+
file.as_mut().unwrap().write_all(data.entirety()).unwrap();
240+
}
188241
}
189242
}
190243
}
191-
}
192-
});
244+
});
193245

194-
let frame_time = self.frame_time;
246+
let frame_time = self.frame_time;
195247

196-
app.add_message::<RecordScreen>().add_systems(
197-
Update,
198-
(
199-
(move |mut messages: MessageWriter<RecordScreen>, mut recording: Local<bool>| {
200-
*recording = !*recording;
201-
if *recording {
202-
messages.write(RecordScreen::Start);
203-
} else {
204-
messages.write(RecordScreen::Stop);
205-
}
206-
})
207-
.run_if(input_just_pressed(self.toggle)),
208-
{
209-
let tx = tx.clone();
210-
let preset = self.preset;
211-
let tune = self.tune;
212-
move |mut commands: Commands,
248+
app.add_message::<RecordScreen>().add_systems(
249+
Update,
250+
(
251+
(move |mut messages: MessageWriter<RecordScreen>,
252+
mut recording: Local<bool>| {
253+
*recording = !*recording;
254+
if *recording {
255+
messages.write(RecordScreen::Start);
256+
} else {
257+
messages.write(RecordScreen::Stop);
258+
}
259+
})
260+
.run_if(input_just_pressed(self.toggle)),
261+
{
262+
let tx = tx.clone();
263+
let preset = self.preset;
264+
let tune = self.tune;
265+
move |mut commands: Commands,
213266
mut recording: Local<bool>,
214267
mut messages: MessageReader<RecordScreen>,
215268
window: Single<&Window, With<PrimaryWindow>>,
@@ -251,9 +304,10 @@ impl Plugin for EasyScreenRecordPlugin {
251304
);
252305
}
253306
}
254-
},
255-
)
256-
.chain(),
257-
);
307+
},
308+
)
309+
.chain(),
310+
);
311+
}
258312
}
259313
}

release-content/release-notes/easy_marketing_material.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ pull_requests: [21235, 21237]
77
Bevy can take a screenshot of what's rendered since 0.11. This is now easier to setup to help you create marketing material, so that you can take screenshot with consistent formatting with the new `EasyScreenshotPlugin`. With its default settings, once you add this plugin to your application, a PNG screenshot will be taken when you press the `PrintScreen` key. You can change the trigger key, or the screenshot format between PNG, JPEG or BMP.
88

99
It is now possible to record a movie from Bevy, with the new `EasyScreenRecordPlugin`. This plugins add a toggle key, space bar by default, that will toggle screen recording. Recording can also be started and stopped programmatically with the `RecordScreen` messages.
10+
11+
Screen recording is not working for now on Windows.

0 commit comments

Comments
 (0)