#import "modules/std.sx"; #import "modules/opengl.sx"; #import "ui/types.sx"; #import "ui/render.sx"; #import "ui/events.sx"; #import "ui/view.sx"; #import "ui/renderer.sx"; UIPipeline :: struct { renderer: UIRenderer; render_tree: RenderTree; font: FontAtlas; screen_width: f32; screen_height: f32; root: ViewChild; has_root: bool; init :: (self: *UIPipeline, width: f32, height: f32) { self.render_tree = RenderTree.init(); self.renderer.init(); self.screen_width = width; self.screen_height = height; self.has_root = false; } init_font :: (self: *UIPipeline, path: [:0]u8, size: f32) { self.font.init(path, size); upload_font_texture(@self.font); set_global_font(@self.font); } set_root :: (self: *UIPipeline, view: View) { self.root = ViewChild.{ view = view }; self.has_root = true; } resize :: (self: *UIPipeline, width: f32, height: f32) { self.screen_width = width; self.screen_height = height; } // Process a single event through the view tree dispatch_event :: (self: *UIPipeline, event: *Event) -> bool { if self.has_root == false { return false; } self.root.view.handle_event(event, self.root.computed_frame); } // Run one frame: layout → render → commit tick :: (self: *UIPipeline) { if self.has_root == false { return; } screen := Frame.make(0.0, 0.0, self.screen_width, self.screen_height); proposal := ProposedSize.fixed(self.screen_width, self.screen_height); // Layout root_size := self.root.view.size_that_fits(proposal); self.root.computed_frame = Frame.{ origin = Point.zero(), size = root_size }; print("tick: computed_frame=({},{},{},{})\n", self.root.computed_frame.origin.x, self.root.computed_frame.origin.y, self.root.computed_frame.size.width, self.root.computed_frame.size.height); self.root.view.layout(self.root.computed_frame); // Render to tree self.render_tree.clear(); ctx := RenderContext.init(@self.render_tree); self.root.view.render(@ctx, self.root.computed_frame); // Commit to GPU glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); self.renderer.begin(self.screen_width, self.screen_height); self.renderer.process(@self.render_tree); self.renderer.flush(); glDisable(GL_BLEND); } }