pub fn create_drawing_window_from_stream<'a, DrawStream: 'static+Send+Unpin+Stream<Item=Vec<Draw>>, TProperties: 'a+FloWindowProperties>(canvas_stream: DrawStream, window_properties: TProperties) -> impl Clone+Send+Stream<Item=DrawEvent> {
    // Create a static copy of the window properties bindings
    let window_properties               = WindowProperties::from(&window_properties);

    // Create a render window
    let (render_actions, render_events) = create_render_window(window_properties);

    // Create a canvas renderer
    let renderer                        = CanvasRenderer::new();
    let renderer                        = RendererState { renderer: renderer, window_transform: None, scale: 1.0, width: 1.0, height: 1.0 };
    let renderer                        = Arc::new(Desync::new(renderer));
    let mut render_events               = render_events;

    // We republish the events, so we can add our own canvas events
    let mut canvas_events               = Publisher::new(1000);
    let window_events                   = canvas_events.subscribe();

    // Run the main canvas event loop as a process on the glutin thread
    glutin_thread().send_event(GlutinThreadEvent::RunProcess(Box::new(move || async move {
        // Handle events until the first 'redraw' event arrives (or stop if closed)
        loop {
            if let Some(event) = render_events.next().await {
                canvas_events.publish(event.clone()).await;

                if let DrawEvent::Redraw = event {
                    // Begin the main event loop
                    // We've read nothing from the canvas yet so we can drop this event as the first canvas read will trigger a redraw anyway
                    break;
                }

                if let DrawEvent::Closed = event {
                    // Stop if the window is closed
                    return;
                }

                // Handle the next event (until the first 'redraw', we're receiving things like the window size in preparation for the next event)
                let mut event_actions = render_actions.republish();
                renderer.future_sync(move |state| async move { 
                    handle_window_event(state, event, &mut |actions| event_actions.publish(actions)).await; 
                }.boxed()).await.ok();
            } else {
                // Ran out of events
                return;
            }
        }

        // For the main event loop, we're always processing the window events, but alternate between reading from the canvas 
        // and waiting for the frame to render. We stop once there are no more events.
        let render_events       = render_events.ready_chunks(1000);
        let mut canvas_updates  = CanvasUpdateStream {
            draw_stream:            Some(canvas_stream),
            event_stream:           render_events,
            waiting_frame_count:    0
        };

        // The window transform is used to track pointer events: it's invalidated when the size changes or the canvas is updated
        let mut window_transform            = None;
        let mut window_transform_invalid    = false;

        loop {
            // Retrieve the next canvas update
            match canvas_updates.next().await {
                Some(CanvasUpdate::DrawEvents(events)) => {
                    // Update the window transform if it is invalidated
                    if window_transform_invalid {
                        window_transform            = renderer.future_sync(|state| async move { state.window_transform }.boxed()).await.unwrap();
                        window_transform_invalid    = false;
                    }

                    // Process the events
                    for evt in events.iter() {
                        // Republish the event (adding the location on the canvas if necessary)
                        match evt {
                            DrawEvent::Pointer(action, pointer_id, pointer_state) => {
                                let mut pointer_state = pointer_state.clone();
                                
                                if let Some(window_transform) = &window_transform {
                                    let (x, y)                          = pointer_state.location_in_window;
                                    let (x, y)                          = (x as _, y as _);
                                    let (cx, cy)                        = window_transform.transform_point(x, y);
                                    pointer_state.location_in_canvas    = Some((cx as _, cy as _));
                                }

                                canvas_events.publish(DrawEvent::Pointer(*action, *pointer_id, pointer_state)).await;
                            }

                            _ => { canvas_events.publish(evt.clone()).await; }
                        }

                        // Closing the window immediately terminates the event loop, a new frame event reduces the waiting frame count
                        match evt {
                            DrawEvent::Closed       => { return; }
                            DrawEvent::NewFrame     => { if canvas_updates.waiting_frame_count > 0 { canvas_updates.waiting_frame_count -= 1; } },
                            DrawEvent::Redraw       => { window_transform_invalid = true; }
                            DrawEvent::Resize(_, _) => { window_transform_invalid = true; }
                            _                       => { }
                        }
                    }

                    // Handle the events on the renderer thread
                    let mut event_actions   = render_actions.republish();
                    let new_events          = renderer.future_sync(move |state| async move { 
                        let mut new_events = vec![];

                        for event in events.into_iter() {
                            // Handle the event
                            new_events.extend(handle_window_event(state, event, &mut |actions| event_actions.publish(actions)).await);
                        }

                        new_events
                    }.boxed()).await.unwrap_or_else(|_| vec![]);

                    // Send any new events to the canvas events publisher
                    for new_event in new_events.into_iter() {
                        canvas_events.publish(new_event).await;
                    }
                }

                Some(CanvasUpdate::Drawing(drawing)) => {
                     // Received some drawing commands to forward to the canvas (which has rendered its previous frame)
                    let mut event_actions   = render_actions.republish();
                    let mut canvas_events   = canvas_events.republish();

                    renderer.future_desync(move |state| async move {
                        // Wait for any pending render actions to clear the queue before trying to generate new ones
                        event_actions.when_empty().await;

                        // Ask the renderer to process the drawing instructions into render instructions
                        let render_actions = state.renderer.draw(drawing.into_iter()).collect::<Vec<_>>().await;

                        // Send an update that the canvas transform has changed
                        let window_transform    = state.update_window_transform();
                        canvas_events.publish(DrawEvent::CanvasTransform(window_transform)).await;

                        // Send the render actions to the window once they're ready
                        event_actions.publish(render_actions).await;
                    }.boxed());

                    window_transform_invalid = true;
                    
                    // Don't read any more from the canvas until the frame has finished rendering
                    canvas_updates.waiting_frame_count += 1;
                }

                None => {
                    // The main event loop has finished: stop processing events
                    return;
                }
            }
        }
    }.boxed_local())));

    // Return the events
    window_events
}
///
/// Creates a drawing window that will render a stream of drawing instructions
///
Creates a drawing window that will render a stream of drawing instructions
Creates a drawing window that will render a stream of drawing instructions
pub fn create_drawing_window_from_stream<'a, DrawStream: 'static+Send+Unpin+Stream<Item=Vec<Draw>>, TProperties: 'a+FloWindowProperties>(canvas_stream: DrawStream, window_properties: TProperties) -> impl Clone+Send+Stream<Item=DrawEvent> {
    // Create a static copy of the window properties bindings
    let window_properties               = WindowProperties::from(&window_properties);
    // Create a render window
    let (render_actions, render_events) = create_render_window(window_properties);
    // Create a canvas renderer
    let renderer                        = CanvasRenderer::new();
    let renderer                        = RendererState { renderer: renderer, window_transform: None, scale: 1.0, width: 1.0, height: 1.0 };
    let renderer                        = Arc::new(Desync::new(renderer));
    let mut render_events               = render_events;
    // We republish the events, so we can add our own canvas events
    let mut canvas_events               = Publisher::new(1000);
    let window_events                   = canvas_events.subscribe();
    // Run the main canvas event loop as a process on the glutin thread
    glutin_thread().send_event(GlutinThreadEvent::RunProcess(Box::new(move || async move {
        // Handle events until the first 'redraw' event arrives (or stop if closed)
        loop {
            if let Some(event) = render_events.next().await {
                canvas_events.publish(event.clone()).await;
                if let DrawEvent::Redraw = event {
                    // Begin the main event loop
                    // We've read nothing from the canvas yet so we can drop this event as the first canvas read will trigger a redraw anyway
                    break;
                }
                if let DrawEvent::Closed = event {
                    // Stop if the window is closed
                    return;
                }
                // Handle the next event (until the first 'redraw', we're receiving things like the window size in preparation for the next event)
                let mut event_actions = render_actions.republish();
                renderer.future_sync(move |state| async move { 
                    handle_window_event(state, event, &mut |actions| event_actions.publish(actions)).await; 
                }.boxed()).await.ok();
            } else {
                // Ran out of events
                return;
            }
        }
        // For the main event loop, we're always processing the window events, but alternate between reading from the canvas 
        // and waiting for the frame to render. We stop once there are no more events.
        let render_events       = render_events.ready_chunks(1000);
        let mut canvas_updates  = CanvasUpdateStream {
            draw_stream:            Some(canvas_stream),
            event_stream:           render_events,
            waiting_frame_count:    0
        };
        // The window transform is used to track pointer events: it's invalidated when the size changes or the canvas is updated
        let mut window_transform            = None;
        let mut window_transform_invalid    = false;
        loop {
            // Retrieve the next canvas update
            match canvas_updates.next().await {
                Some(CanvasUpdate::DrawEvents(events)) => {
                    // Update the window transform if it is invalidated
                    if window_transform_invalid {
                        window_transform            = renderer.future_sync(|state| async move { state.window_transform }.boxed()).await.unwrap();
                        window_transform_invalid    = false;
                    }
                    // Process the events
                    for evt in events.iter() {
                        // Republish the event (adding the location on the canvas if necessary)
                        match evt {
                            DrawEvent::Pointer(action, pointer_id, pointer_state) => {
                                let mut pointer_state = pointer_state.clone();
                                if let Some(window_transform) = &window_transform {
                                    let (x, y)                          = pointer_state.location_in_window;
                                    let (x, y)                          = (x as _, y as _);
                                    let (cx, cy)                        = window_transform.transform_point(x, y);
                                    pointer_state.location_in_canvas    = Some((cx as _, cy as _));
                                }
                                canvas_events.publish(DrawEvent::Pointer(*action, *pointer_id, pointer_state)).await;
                            }
                            _ => { canvas_events.publish(evt.clone()).await; }
                        }
                        // Closing the window immediately terminates the event loop, a new frame event reduces the waiting frame count
                        match evt {
                            DrawEvent::Closed       => { return; }
                            DrawEvent::NewFrame     => { if canvas_updates.waiting_frame_count > 0 { canvas_updates.waiting_frame_count -= 1; } },
                            DrawEvent::Redraw       => { window_transform_invalid = true; }
                            DrawEvent::Resize(_, _) => { window_transform_invalid = true; }
                            _                       => { }
                        }
                    }
                    // Handle the events on the renderer thread
                    let mut event_actions   = render_actions.republish();
                    let new_events          = renderer.future_sync(move |state| async move { 
                        let mut new_events = vec![];
                        for event in events.into_iter() {
                            // Handle the event
                            new_events.extend(handle_window_event(state, event, &mut |actions| event_actions.publish(actions)).await);
                        }
                        new_events
                    }.boxed()).await.unwrap_or_else(|_| vec![]);
                    // Send any new events to the canvas events publisher
                    for new_event in new_events.into_iter() {
                        canvas_events.publish(new_event).await;
                    }
                }
                Some(CanvasUpdate::Drawing(drawing)) => {
                     // Received some drawing commands to forward to the canvas (which has rendered its previous frame)
                    let mut event_actions   = render_actions.republish();
                    let mut canvas_events   = canvas_events.republish();
                    renderer.future_desync(move |state| async move {
                        // Wait for any pending render actions to clear the queue before trying to generate new ones
                        event_actions.when_empty().await;
                        // Ask the renderer to process the drawing instructions into render instructions
                        let render_actions = state.renderer.draw(drawing.into_iter()).collect::<Vec<_>>().await;
                        // Send an update that the canvas transform has changed
                        let window_transform    = state.update_window_transform();
                        canvas_events.publish(DrawEvent::CanvasTransform(window_transform)).await;
                        // Send the render actions to the window once they're ready
                        event_actions.publish(render_actions).await;
                    }.boxed());
                    window_transform_invalid = true;
                    // Don't read any more from the canvas until the frame has finished rendering
                    canvas_updates.waiting_frame_count += 1;
                }
                None => {
                    // The main event loop has finished: stop processing events
                    return;
                }
            }
        }
    }.boxed_local())));
    // Return the events
    window_events
}
pub fn create_drawing_window_from_stream < ' a , DrawStream : ' static + Send + Unpin + Stream < Item = Vec < Draw > > , TProperties : ' a + FloWindowProperties > ( canvas_stream : DrawStream , window_properties : TProperties ) -> impl Clone + Send + Stream < Item = DrawEvent > { // Create a static copy of the window properties bindings let window_properties = WindowProperties :: from ( & window_properties ) ; // Create a render window let ( render_actions , render_events ) = create_render_window ( window_properties ) ; // Create a canvas renderer let renderer = CanvasRenderer :: new ( ) ; let renderer = RendererState { renderer : renderer , window_transform : None , scale : 1.0 , width : 1.0 , height : 1.0 } ; let renderer = Arc :: new ( Desync :: new ( renderer ) ) ; let mut render_events = render_events ; // We republish the events, so we can add our own canvas events let mut canvas_events = Publisher :: new ( 1000 ) ; let window_events = canvas_events . subscribe ( ) ; // Run the main canvas event loop as a process on the glutin thread glutin_thread ( ) . send_event ( GlutinThreadEvent :: RunProcess ( Box :: new ( move | | async move { // Handle events until the first 'redraw' event arrives (or stop if closed) loop { if let Some ( event ) = render_events . next ( ) . await { canvas_events . publish ( event . clone ( ) ) . await ; if let DrawEvent :: Redraw = event { // Begin the main event loop // We've read nothing from the canvas yet so we can drop this event as the first canvas read will trigger a redraw anyway break ; } if let DrawEvent :: Closed = event { // Stop if the window is closed return ; } // Handle the next event (until the first 'redraw', we're receiving things like the window size in preparation for the next event) let mut event_actions = render_actions . republish ( ) ; renderer . future_sync ( move | state | async move { handle_window_event ( state , event , & mut | actions | event_actions . publish ( actions ) ) . await ; } . boxed ( ) ) . await . ok ( ) ; } else { // Ran out of events return ; } } // For the main event loop, we're always processing the window events, but alternate between reading from the canvas  // and waiting for the frame to render. We stop once there are no more events. let render_events = render_events . ready_chunks ( 1000 ) ; let mut canvas_updates = CanvasUpdateStream { draw_stream : Some ( canvas_stream ) , event_stream : render_events , waiting_frame_count : 0 } ; // The window transform is used to track pointer events: it's invalidated when the size changes or the canvas is updated let mut window_transform = None ; let mut window_transform_invalid = false ; loop { // Retrieve the next canvas update match canvas_updates . next ( ) . await { Some ( CanvasUpdate :: DrawEvents ( events ) ) => { // Update the window transform if it is invalidated if window_transform_invalid { window_transform = renderer . future_sync ( | state | async move { state . window_transform } . boxed ( ) ) . await . unwrap ( ) ; window_transform_invalid = false ; } // Process the events for evt in events . iter ( ) { // Republish the event (adding the location on the canvas if necessary) match evt { DrawEvent :: Pointer ( action , pointer_id , pointer_state ) => { let mut pointer_state = pointer_state . clone ( ) ; if let Some ( window_transform ) = & window_transform { let ( x , y ) = pointer_state . location_in_window ; let ( x , y ) = ( x as _ , y as _ ) ; let ( cx , cy ) = window_transform . transform_point ( x , y ) ; pointer_state . location_in_canvas = Some ( ( cx as _ , cy as _ ) ) ; } canvas_events . publish ( DrawEvent :: Pointer ( * action , * pointer_id , pointer_state ) ) . await ; } _ => { canvas_events . publish ( evt . clone ( ) ) . await ; } } // Closing the window immediately terminates the event loop, a new frame event reduces the waiting frame count match evt { DrawEvent :: Closed => { return ; } DrawEvent :: NewFrame => { if canvas_updates . waiting_frame_count > 0 { canvas_updates . waiting_frame_count -= 1 ; } } , DrawEvent :: Redraw => { window_transform_invalid = true ; } DrawEvent :: Resize ( _ , _ ) => { window_transform_invalid = true ; } _ => { } } } // Handle the events on the renderer thread let mut event_actions = render_actions . republish ( ) ; let new_events = renderer . future_sync ( move | state | async move { let mut new_events = vec ! [ ] ; for event in events . into_iter ( ) { // Handle the event new_events . extend ( handle_window_event ( state , event , & mut | actions | event_actions . publish ( actions ) ) . await ) ; } new_events } . boxed ( ) ) . await . unwrap_or_else ( | _ | vec ! [ ] ) ; // Send any new events to the canvas events publisher for new_event in new_events . into_iter ( ) { canvas_events . publish ( new_event ) . await ; } } Some ( CanvasUpdate :: Drawing ( drawing ) ) => { // Received some drawing commands to forward to the canvas (which has rendered its previous frame) let mut event_actions = render_actions . republish ( ) ; let mut canvas_events = canvas_events . republish ( ) ; renderer . future_desync ( move | state | async move { // Wait for any pending render actions to clear the queue before trying to generate new ones event_actions . when_empty ( ) . await ; // Ask the renderer to process the drawing instructions into render instructions let render_actions = state . renderer . draw ( drawing . into_iter ( ) ) . collect :: < Vec < _ > > ( ) . await ; // Send an update that the canvas transform has changed let window_transform = state . update_window_transform ( ) ; canvas_events . publish ( DrawEvent :: CanvasTransform ( window_transform ) ) . await ; // Send the render actions to the window once they're ready event_actions . publish ( render_actions ) . await ; } . boxed ( ) ) ; window_transform_invalid = true ; // Don't read any more from the canvas until the frame has finished rendering canvas_updates . waiting_frame_count += 1 ; } None => { // The main event loop has finished: stop processing events return ; } } } } . boxed_local ( ) ) ) ) ; // Return the events window_events }
Creates a drawing window that will render a stream of drawing instructions
Creates a drawing window that will render a stream of drawing instructions
canvas_stream
DrawStream
window_properties
TProperties