@@ -2,6 +2,9 @@ use crate::CustomEvent;
22use crate :: WindowSize ;
33use crate :: render:: GraphicsState ;
44use crate :: render:: WgpuContext ;
5+ use graph_craft:: wasm_application_io:: WasmApplicationIo ;
6+ use graphite_editor:: application:: Editor ;
7+ use graphite_editor:: messages:: prelude:: * ;
58use std:: sync:: Arc ;
69use std:: sync:: mpsc:: Sender ;
710use std:: time:: Duration ;
@@ -21,11 +24,13 @@ pub(crate) struct WinitApp {
2124 pub ( crate ) cef_context : cef:: Context < cef:: Initialized > ,
2225 pub ( crate ) window : Option < Arc < Window > > ,
2326 cef_schedule : Option < Instant > ,
27+ // Cached frame buffer from CEF, used to check if mouse is on a transparent pixel
2428 _ui_frame_buffer : Option < wgpu:: Texture > ,
2529 window_size_sender : Sender < WindowSize > ,
2630 _viewport_frame_buffer : Option < wgpu:: Texture > ,
2731 graphics_state : Option < GraphicsState > ,
2832 wgpu_context : WgpuContext ,
33+ pub ( crate ) editor : Editor ,
2934}
3035
3136impl WinitApp {
@@ -39,8 +44,25 @@ impl WinitApp {
3944 graphics_state : None ,
4045 window_size_sender,
4146 wgpu_context,
47+ editor : Editor :: new ( ) ,
4248 }
4349 }
50+
51+ fn dispatch_message ( & mut self , message : Message ) {
52+ let responses = self . editor . handle_message ( message) ;
53+ self . send_messages_to_editor ( responses) ;
54+ }
55+
56+ fn send_messages_to_editor ( & mut self , responses : Vec < FrontendMessage > ) {
57+ if responses. is_empty ( ) {
58+ return ;
59+ }
60+ let Ok ( message) = ron:: to_string ( & responses) else {
61+ tracing:: error!( "Failed to serialize Messages" ) ;
62+ return ;
63+ } ;
64+ self . cef_context . send_web_message ( message. as_bytes ( ) ) ;
65+ }
4466}
4567
4668impl ApplicationHandler < CustomEvent > for WinitApp {
@@ -49,16 +71,41 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
4971 let timeout = Instant :: now ( ) + Duration :: from_millis ( 10 ) ;
5072 let wait_until = timeout. min ( self . cef_schedule . unwrap_or ( timeout) ) ;
5173 self . cef_context . work ( ) ;
74+
75+ let ( _has_run, texture) = futures:: executor:: block_on ( graphite_editor:: node_graph_executor:: run_node_graph ( ) ) ;
76+ if _has_run {
77+ let mut responses = VecDeque :: new ( ) ;
78+ let err = self . editor . poll_node_graph_evaluation ( & mut responses) ;
79+ if let Err ( e) = err {
80+ tracing:: error!( "Error poling node graph: {}" , e) ;
81+ }
82+ let frontend_messages = responses
83+ . into_iter ( )
84+ . flat_map ( |response| if let Message :: Frontend ( frontend) = response { Some ( frontend) } else { None } )
85+ . collect ( ) ;
86+ self . send_messages_to_editor ( frontend_messages) ;
87+ }
88+ if let Some ( texture) = texture
89+ && let Some ( graphics_state) = & mut self . graphics_state
90+ {
91+ graphics_state. bind_viewport_texture ( texture. texture . as_ref ( ) ) ;
92+ }
93+
5294 event_loop. set_control_flow ( ControlFlow :: WaitUntil ( wait_until) ) ;
5395 }
5496
55- fn new_events ( & mut self , _event_loop : & ActiveEventLoop , _cause : StartCause ) {
97+ fn new_events ( & mut self , _event_loop : & ActiveEventLoop , cause : StartCause ) {
5698 if let Some ( schedule) = self . cef_schedule
5799 && schedule < Instant :: now ( )
58100 {
59101 self . cef_schedule = None ;
60102 self . cef_context . work ( ) ;
61103 }
104+ if let StartCause :: ResumeTimeReached { .. } = cause {
105+ if let Some ( window) = & self . window {
106+ window. request_redraw ( ) ;
107+ }
108+ }
62109 }
63110
64111 fn resumed ( & mut self , event_loop : & ActiveEventLoop ) {
@@ -71,12 +118,67 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
71118 )
72119 . unwrap ( ) ,
73120 ) ;
74- let graphics_state = GraphicsState :: new ( window. clone ( ) , self . wgpu_context . clone ( ) ) ;
121+ let mut graphics_state = GraphicsState :: new ( window. clone ( ) , self . wgpu_context . clone ( ) ) ;
122+
123+ let mut test_data = vec ! [ 0u8 ; 800 * 600 * 4 ] ;
124+
125+ for y in 0 ..600 {
126+ for x in 0 ..800 {
127+ let idx = ( y * 800 + x) * 4 ;
128+ test_data[ idx + 1 ] = ( x * 255 / 800 ) as u8 ; // Blue
129+ test_data[ idx + 2 ] = ( y * 255 / 600 ) as u8 ; // Green
130+ test_data[ idx] = 255 ; // Red
131+ test_data[ idx + 3 ] = 255 ; // Alpha
132+ }
133+ }
134+
135+ let texture = self . wgpu_context . device . create_texture ( & wgpu:: TextureDescriptor {
136+ label : Some ( "Viewport Texture" ) ,
137+ size : wgpu:: Extent3d {
138+ width : 800 ,
139+ height : 600 ,
140+ depth_or_array_layers : 1 ,
141+ } ,
142+ mip_level_count : 1 ,
143+ sample_count : 1 ,
144+ dimension : wgpu:: TextureDimension :: D2 ,
145+ format : wgpu:: TextureFormat :: Bgra8UnormSrgb ,
146+ usage : wgpu:: TextureUsages :: TEXTURE_BINDING | wgpu:: TextureUsages :: COPY_DST ,
147+ view_formats : & [ ] ,
148+ } ) ;
149+
150+ self . wgpu_context . queue . write_texture (
151+ wgpu:: TexelCopyTextureInfo {
152+ texture : & texture,
153+ mip_level : 0 ,
154+ origin : wgpu:: Origin3d :: ZERO ,
155+ aspect : wgpu:: TextureAspect :: All ,
156+ } ,
157+ test_data. as_slice ( ) ,
158+ wgpu:: TexelCopyBufferLayout {
159+ offset : 0 ,
160+ bytes_per_row : Some ( 4 * 800 ) ,
161+ rows_per_image : Some ( 600 ) ,
162+ } ,
163+ wgpu:: Extent3d {
164+ width : 800 ,
165+ height : 600 ,
166+ depth_or_array_layers : 1 ,
167+ } ,
168+ ) ;
169+
170+ graphics_state. bind_viewport_texture ( & texture) ;
75171
76172 self . window = Some ( window) ;
77173 self . graphics_state = Some ( graphics_state) ;
78174
79175 tracing:: info!( "Winit window created and ready" ) ;
176+
177+ graphite_editor:: application:: set_uuid_seed ( 42 ) ;
178+
179+ let application_io = WasmApplicationIo :: new_with_context ( self . wgpu_context . clone ( ) ) ;
180+
181+ futures:: executor:: block_on ( graphite_editor:: node_graph_executor:: replace_application_io ( application_io) ) ;
80182 }
81183
82184 fn user_event ( & mut self , _: & ActiveEventLoop , event : CustomEvent ) {
@@ -97,6 +199,32 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
97199 self . cef_schedule = Some ( instant) ;
98200 }
99201 }
202+ CustomEvent :: MessageReceived { message } => {
203+ if let Message :: InputPreprocessor ( ipp_message) = & message {
204+ if let Some ( window) = & self . window {
205+ window. request_redraw ( ) ;
206+ }
207+ if let InputPreprocessorMessage :: CurrentTime { .. } | InputPreprocessorMessage :: PointerMove { .. } = & ipp_message {
208+ } else {
209+ // println!("got ipp message: {:?}", &ipp_message.to_discriminant());
210+ }
211+ }
212+ if let Message :: InputPreprocessor ( InputPreprocessorMessage :: BoundsOfViewports { bounds_of_viewports } ) = & message {
213+ if let Some ( graphic_state) = & mut self . graphics_state {
214+ let window_size = self . window . as_ref ( ) . unwrap ( ) . inner_size ( ) ;
215+ let window_size = glam:: Vec2 :: new ( window_size. width as f32 , window_size. height as f32 ) ;
216+ let top_left = bounds_of_viewports[ 0 ] . top_left . as_vec2 ( ) / window_size;
217+ let bottom_right = bounds_of_viewports[ 0 ] . bottom_right . as_vec2 ( ) / window_size;
218+ let offset = top_left. to_array ( ) ;
219+ let scale = ( bottom_right - top_left) . recip ( ) ;
220+ graphic_state. set_viewport_offset ( offset) ;
221+ graphic_state. set_viewport_scale ( scale. to_array ( ) ) ;
222+ } else {
223+ panic ! ( "graphics state not intialized, viewport offset might be lost" ) ;
224+ }
225+ }
226+ self . dispatch_message ( message) ;
227+ }
100228 }
101229 }
102230
0 commit comments