11use std:: {
22 collections:: HashMap ,
3+ fmt:: Display ,
34 fs:: { self , File } ,
45 io:: Write ,
56 path:: { Path , PathBuf } ,
@@ -8,7 +9,7 @@ use std::{
89 time:: { Duration , Instant } ,
910} ;
1011
11- use clap:: Parser ;
12+ use clap:: { error :: ErrorKind , CommandFactory , Parser , ValueEnum } ;
1213use pbr:: ProgressBar ;
1314use toml_edit:: Document ;
1415use xshell:: { cmd, Shell } ;
@@ -21,6 +22,13 @@ struct Args {
2122
2223 #[ command( subcommand) ]
2324 action : Action ,
25+ #[ arg( long) ]
26+ /// Pagination control - page number. To use with --per-page
27+ page : Option < usize > ,
28+
29+ #[ arg( long) ]
30+ /// Pagination control - number of examples per page. To use with --page
31+ per_page : Option < usize > ,
2432}
2533
2634#[ derive( clap:: Subcommand , Debug ) ]
@@ -44,9 +52,13 @@ enum Action {
4452 #[ arg( long) ]
4553 /// Path to the folder where the content should be created
4654 content_folder : String ,
55+
56+ #[ arg( value_enum, long, default_value_t = WebApi :: Webgl2 ) ]
57+ /// Which API to use for rendering
58+ api : WebApi ,
4759 } ,
48- /// BUild the examples in wasm / WebGPU
49- BuildWebGPUExamples {
60+ /// Build the examples in wasm
61+ BuildWasmExamples {
5062 #[ arg( long) ]
5163 /// Path to the folder where the content should be created
5264 content_folder : String ,
@@ -58,12 +70,40 @@ enum Action {
5870 #[ arg( long) ]
5971 /// Optimize the wasm file for size with wasm-opt
6072 optimize_size : bool ,
73+
74+ #[ arg( value_enum, long) ]
75+ /// Which API to use for rendering
76+ api : WebApi ,
6177 } ,
6278}
6379
80+ #[ derive( Debug , Copy , Clone , ValueEnum ) ]
81+ enum WebApi {
82+ Webgl2 ,
83+ Webgpu ,
84+ }
85+
86+ impl Display for WebApi {
87+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
88+ match self {
89+ WebApi :: Webgl2 => write ! ( f, "webgl2" ) ,
90+ WebApi :: Webgpu => write ! ( f, "webgpu" ) ,
91+ }
92+ }
93+ }
94+
6495fn main ( ) {
6596 let cli = Args :: parse ( ) ;
6697
98+ if cli. page . is_none ( ) != cli. per_page . is_none ( ) {
99+ let mut cmd = Args :: command ( ) ;
100+ cmd. error (
101+ ErrorKind :: MissingRequiredArgument ,
102+ "page and per-page must be used together" ,
103+ )
104+ . exit ( ) ;
105+ }
106+
67107 let profile = cli. profile ;
68108
69109 match cli. action {
@@ -106,7 +146,16 @@ fn main() {
106146 }
107147 }
108148
109- for to_run in examples_to_run {
149+ let work_to_do = || {
150+ examples_to_run
151+ . iter ( )
152+ . skip ( cli. page . unwrap_or ( 0 ) * cli. per_page . unwrap_or ( 0 ) )
153+ . take ( cli. per_page . unwrap_or ( usize:: MAX ) )
154+ } ;
155+
156+ let mut pb = ProgressBar :: new ( work_to_do ( ) . count ( ) as u64 ) ;
157+
158+ for to_run in work_to_do ( ) {
110159 let sh = Shell :: new ( ) . unwrap ( ) ;
111160 let example = & to_run. technical_name ;
112161 let extra_parameters = extra_parameters. clone ( ) ;
@@ -143,7 +192,9 @@ fn main() {
143192 println ! ( "took {duration:?}" ) ;
144193
145194 thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
195+ pb. inc ( ) ;
146196 }
197+ pb. finish_print ( "done" ) ;
147198 if failed_examples. is_empty ( ) {
148199 println ! ( "All examples passed!" ) ;
149200 } else {
@@ -157,27 +208,46 @@ fn main() {
157208 exit ( 1 ) ;
158209 }
159210 }
160- Action :: BuildWebsiteList { content_folder } => {
211+ Action :: BuildWebsiteList {
212+ content_folder,
213+ api,
214+ } => {
161215 let examples_to_run = parse_examples ( ) ;
162216
163217 let root_path = Path :: new ( & content_folder) ;
164218
165219 let _ = fs:: create_dir_all ( root_path) ;
166220
167221 let mut index = File :: create ( root_path. join ( "_index.md" ) ) . unwrap ( ) ;
168- index
169- . write_all (
170- "+++
222+ if matches ! ( api, WebApi :: Webgpu ) {
223+ index
224+ . write_all (
225+ "+++
171226title = \" Bevy Examples in WebGPU\"
172227template = \" examples-webgpu.html\"
173228sort_by = \" weight\"
174229
175230[extra]
176231header_message = \" Examples (WebGPU)\"
177232+++"
178- . as_bytes ( ) ,
179- )
180- . unwrap ( ) ;
233+ . as_bytes ( ) ,
234+ )
235+ . unwrap ( ) ;
236+ } else {
237+ index
238+ . write_all (
239+ "+++
240+ title = \" Bevy Examples in WebGL2\"
241+ template = \" examples.html\"
242+ sort_by = \" weight\"
243+
244+ [extra]
245+ header_message = \" Examples (WebGL2)\"
246+ +++"
247+ . as_bytes ( ) ,
248+ )
249+ . unwrap ( ) ;
250+ }
181251
182252 let mut categories = HashMap :: new ( ) ;
183253 for to_show in examples_to_run {
@@ -217,43 +287,61 @@ weight = {}
217287 format ! (
218288 "+++
219289title = \" {}\"
220- template = \" example-webgpu .html\"
290+ template = \" example{} .html\"
221291weight = {}
222292description = \" {}\"
223293
224294[extra]
225295technical_name = \" {}\"
226- link = \" {}/{}\"
296+ link = \" /examples{}/ {}/{}\"
227297image = \" ../static/screenshots/{}/{}.png\"
228- code_path = \" content/examples-webgpu /{}\"
298+ code_path = \" content/examples{} /{}\"
229299github_code_path = \" {}\"
230- header_message = \" Examples (WebGPU )\"
300+ header_message = \" Examples ({} )\"
231301+++" ,
232302 to_show. name,
303+ match api {
304+ WebApi :: Webgpu => "-webgpu" ,
305+ WebApi :: Webgl2 => "" ,
306+ } ,
233307 categories. get( & to_show. category) . unwrap( ) ,
234308 to_show. description. replace( '"' , "'" ) ,
235309 & to_show. technical_name. replace( '_' , "-" ) ,
310+ match api {
311+ WebApi :: Webgpu => "-webgpu" ,
312+ WebApi :: Webgl2 => "" ,
313+ } ,
236314 & to_show. category,
237315 & to_show. technical_name. replace( '_' , "-" ) ,
238316 & to_show. category,
239317 & to_show. technical_name,
318+ match api {
319+ WebApi :: Webgpu => "-webgpu" ,
320+ WebApi :: Webgl2 => "" ,
321+ } ,
240322 code_path
241323 . components( )
242324 . skip( 1 )
243325 . collect:: <PathBuf >( )
244326 . display( ) ,
245327 & to_show. path,
328+ match api {
329+ WebApi :: Webgpu => "WebGPU" ,
330+ WebApi :: Webgl2 => "WebGL2" ,
331+ } ,
246332 )
247333 . as_bytes ( ) ,
248334 )
249335 . unwrap ( ) ;
250336 }
251337 }
252- Action :: BuildWebGPUExamples {
338+ Action :: BuildWasmExamples {
253339 content_folder,
254340 website_hacks,
255341 optimize_size,
342+ api,
256343 } => {
344+ let api = format ! ( "{}" , api) ;
257345 let examples_to_build = parse_examples ( ) ;
258346
259347 let root_path = Path :: new ( & content_folder) ;
@@ -282,30 +370,29 @@ header_message = \"Examples (WebGPU)\"
282370 cmd ! ( sh, "sed -i.bak 's/asset_folder: \" assets\" /asset_folder: \" \\ /assets\\ /examples\\ /\" /' crates/bevy_asset/src/lib.rs" ) . run ( ) . unwrap ( ) ;
283371 }
284372
285- let mut pb = ProgressBar :: new (
373+ let work_to_do = || {
286374 examples_to_build
287375 . iter ( )
288376 . filter ( |to_build| to_build. wasm )
289- . count ( ) as u64 ,
290- ) ;
291- for to_build in examples_to_build {
292- if !to_build. wasm {
293- continue ;
294- }
377+ . skip ( cli. page . unwrap_or ( 0 ) * cli. per_page . unwrap_or ( 0 ) )
378+ . take ( cli. per_page . unwrap_or ( usize:: MAX ) )
379+ } ;
295380
381+ let mut pb = ProgressBar :: new ( work_to_do ( ) . count ( ) as u64 ) ;
382+ for to_build in work_to_do ( ) {
296383 let sh = Shell :: new ( ) . unwrap ( ) ;
297384 let example = & to_build. technical_name ;
298385 if optimize_size {
299386 cmd ! (
300387 sh,
301- "cargo run -p build-wasm-example -- --api webgpu {example} --optimize-size"
388+ "cargo run -p build-wasm-example -- --api {api} {example} --optimize-size"
302389 )
303390 . run ( )
304391 . unwrap ( ) ;
305392 } else {
306393 cmd ! (
307394 sh,
308- "cargo run -p build-wasm-example -- --api webgpu {example}"
395+ "cargo run -p build-wasm-example -- --api {api} {example}"
309396 )
310397 . run ( )
311398 . unwrap ( ) ;
0 commit comments