fn show_mandelbrot(canvas: &DrawingTarget, layer: LayerId, texture: TextureId, width: BindRef<u32>, height: BindRef<u32>, bounds: BindRef<(Complex<f64>, Complex<f64>)>, crossfade: BindRef<f32>, update_num: BindRef<u64>) {
    let canvas = canvas.clone();

    thread::Builder::new()
        .name("Mandelbrot thread".into())
        .spawn(move || {
            enum Event {
                RenderBounds((u32, u32, (Complex<f64>, Complex<f64>))),
                CrossFade(f32)
            }

            let alpha           = computed(move || f32::min(f32::max(crossfade.get()-1.0, 0.0),1.0));
            let alpha           = BindRef::from(alpha);
            let mut texture_w   = width.get();
            let mut texture_h   = height.get();

            // The render bounds are used to determine when we start to re-render the mandelbrot set
            let render_bounds   = computed(move || (width.get(), height.get(), bounds.get()));

            // Events either start rendering a new frame or changing the crossfade
            let render_bounds   = follow(render_bounds).map(|bounds| Event::RenderBounds(bounds)).boxed();
            let crossfade       = follow(alpha.clone()).map(|xfade| Event::CrossFade(xfade)).boxed();

            let events          = stream::select_all(vec![render_bounds, crossfade]);

            // Wait for events and render the mandelbrot set as they arrive
            executor::block_on(async move {
                let mut events = events;

                while let Some(evt) = events.next().await {
                    match evt {
                        Event::RenderBounds((new_width, new_height, new_bounds)) => {
                            texture_w = new_width;
                            texture_h = new_height;

                            // Create the texture for this width and height
                            canvas.draw(|gc| {
                                gc.layer(layer);
                                gc.create_texture(texture, texture_w, texture_h, TextureFormat::Rgba);
                                gc.set_texture_fill_alpha(texture, alpha.get());
                            });

                            // Fill it in with the current bounds
                            draw_mandelbrot(&canvas, layer, texture, new_bounds, texture_w, texture_h, &alpha, &update_num);
                        }

                        Event::CrossFade(new_alpha) => {
                            // Redraw the texture with the new alpha
                            canvas.draw(|gc| {
                                gc.layer(layer);
                                gc.clear_layer();
                                gc.set_texture_fill_alpha(texture, new_alpha);

                                gc.canvas_height(texture_h as _);
                                gc.center_region(0.0, 0.0, texture_w as _, texture_h as _);

                                gc.new_path();
                                gc.rect(0.0, 0.0, texture_w as _, texture_h as _);
                                gc.fill_texture(texture, 0.0, 0.0, texture_w as _, texture_h as _);
                                gc.fill();
                            });
                        }
                    }
                }
            });
        })
        .unwrap();
}
///
/// Runs a thread that renders the mandelbrot set whenever the bindings change 
///
Runs a thread that renders the mandelbrot set whenever the bindings change
Runs a thread that renders the mandelbrot set whenever the bindings change
fn show_mandelbrot(canvas: &DrawingTarget, layer: LayerId, texture: TextureId, width: BindRef<u32>, height: BindRef<u32>, bounds: BindRef<(Complex<f64>, Complex<f64>)>, crossfade: BindRef<f32>, update_num: BindRef<u64>) {
    let canvas = canvas.clone();
    thread::Builder::new()
        .name("Mandelbrot thread".into())
        .spawn(move || {
            enum Event {
                RenderBounds((u32, u32, (Complex<f64>, Complex<f64>))),
                CrossFade(f32)
            }
            let alpha           = computed(move || f32::min(f32::max(crossfade.get()-1.0, 0.0),1.0));
            let alpha           = BindRef::from(alpha);
            let mut texture_w   = width.get();
            let mut texture_h   = height.get();
            // The render bounds are used to determine when we start to re-render the mandelbrot set
            let render_bounds   = computed(move || (width.get(), height.get(), bounds.get()));
            // Events either start rendering a new frame or changing the crossfade
            let render_bounds   = follow(render_bounds).map(|bounds| Event::RenderBounds(bounds)).boxed();
            let crossfade       = follow(alpha.clone()).map(|xfade| Event::CrossFade(xfade)).boxed();
            let events          = stream::select_all(vec![render_bounds, crossfade]);
            // Wait for events and render the mandelbrot set as they arrive
            executor::block_on(async move {
                let mut events = events;
                while let Some(evt) = events.next().await {
                    match evt {
                        Event::RenderBounds((new_width, new_height, new_bounds)) => {
                            texture_w = new_width;
                            texture_h = new_height;
                            // Create the texture for this width and height
                            canvas.draw(|gc| {
                                gc.layer(layer);
                                gc.create_texture(texture, texture_w, texture_h, TextureFormat::Rgba);
                                gc.set_texture_fill_alpha(texture, alpha.get());
                            });
                            // Fill it in with the current bounds
                            draw_mandelbrot(&canvas, layer, texture, new_bounds, texture_w, texture_h, &alpha, &update_num);
                        }
                        Event::CrossFade(new_alpha) => {
                            // Redraw the texture with the new alpha
                            canvas.draw(|gc| {
                                gc.layer(layer);
                                gc.clear_layer();
                                gc.set_texture_fill_alpha(texture, new_alpha);
                                gc.canvas_height(texture_h as _);
                                gc.center_region(0.0, 0.0, texture_w as _, texture_h as _);
                                gc.new_path();
                                gc.rect(0.0, 0.0, texture_w as _, texture_h as _);
                                gc.fill_texture(texture, 0.0, 0.0, texture_w as _, texture_h as _);
                                gc.fill();
                            });
                        }
                    }
                }
            });
        })
        .unwrap();
}
fn show_mandelbrot ( canvas : & DrawingTarget , layer : LayerId , texture : TextureId , width : BindRef < u32 > , height : BindRef < u32 > , bounds : BindRef < ( Complex < f64 > , Complex < f64 > ) > , crossfade : BindRef < f32 > , update_num : BindRef < u64 > ) { let canvas = canvas . clone ( ) ; thread :: Builder :: new ( ) . name ( " " . into ( ) ) . spawn ( move | | { enum Event { RenderBounds ( ( u32 , u32 , ( Complex < f64 > , Complex < f64 > ) ) ) , CrossFade ( f32 ) } let alpha = computed ( move | | f32 :: min ( f32 :: max ( crossfade . get ( ) - 1.0 , 0.0 ) , 1.0 ) ) ; let alpha = BindRef :: from ( alpha ) ; let mut texture_w = width . get ( ) ; let mut texture_h = height . get ( ) ; // The render bounds are used to determine when we start to re-render the mandelbrot set let render_bounds = computed ( move | | ( width . get ( ) , height . get ( ) , bounds . get ( ) ) ) ; // Events either start rendering a new frame or changing the crossfade let render_bounds = follow ( render_bounds ) . map ( | bounds | Event :: RenderBounds ( bounds ) ) . boxed ( ) ; let crossfade = follow ( alpha . clone ( ) ) . map ( | xfade | Event :: CrossFade ( xfade ) ) . boxed ( ) ; let events = stream :: select_all ( vec ! [ render_bounds crossfade ] ) ; // Wait for events and render the mandelbrot set as they arrive executor :: block_on ( async move { let mut events = events ; while let Some ( evt ) = events . next ( ) . await { match evt { Event :: RenderBounds ( ( new_width , new_height , new_bounds ) ) => { texture_w = new_width ; texture_h = new_height ; // Create the texture for this width and height canvas . draw ( | gc | { gc . layer ( layer ) ; gc . create_texture ( texture , texture_w , texture_h , TextureFormat :: Rgba ) ; gc . set_texture_fill_alpha ( texture , alpha . get ( ) ) ; } ) ; // Fill it in with the current bounds draw_mandelbrot ( & canvas , layer , texture , new_bounds , texture_w , texture_h , & alpha , & update_num ) ; } Event :: CrossFade ( new_alpha ) => { // Redraw the texture with the new alpha canvas . draw ( | gc | { gc . layer ( layer ) ; gc . clear_layer ( ) ; gc . set_texture_fill_alpha ( texture , new_alpha ) ; gc . canvas_height ( texture_h as _ ) ; gc . center_region ( 0.0 , 0.0 , texture_w as _ , texture_h as _ ) ; gc . new_path ( ) ; gc . rect ( 0.0 , 0.0 , texture_w as _ , texture_h as _ ) ; gc . fill_texture ( texture , 0.0 , 0.0 , texture_w as _ , texture_h as _ ) ; gc . fill ( ) ; } ) ; } } } } ) ; } ) . unwrap ( ) ; }
Runs a thread that renders the mandelbrot set whenever the bindings change
Runs a thread that renders the mandelbrot set whenever the bindings change
canvas
&DrawingTarget
layer
LayerId
texture
TextureId
width
BindRef<u32>
height
BindRef<u32>
bounds
BindRef<(Complex<f64>, Complex<f64>)>
crossfade
BindRef<f32>
update_num
BindRef<u64>