mirror of
https://github.com/danbulant/mangui
synced 2026-06-18 05:41:02 +00:00
improved context
This commit is contained in:
parent
7152108017
commit
68cf25da3f
2 changed files with 58 additions and 32 deletions
33
src/main.rs
33
src/main.rs
|
|
@ -1,10 +1,9 @@
|
|||
use std::num::NonZeroU32;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use femtovg::renderer::OpenGl;
|
||||
use femtovg::{Canvas, Color, Renderer};
|
||||
use femtovg::{Canvas, Color};
|
||||
use glutin::surface::Surface;
|
||||
use glutin::{context::PossiblyCurrentContext, display::Display};
|
||||
use glutin_winit::DisplayBuilder;
|
||||
|
|
@ -23,7 +22,7 @@ use glutin::{
|
|||
};
|
||||
use taffy::Taffy;
|
||||
use weak_table::PtrWeakKeyHashMap;
|
||||
use crate::nodes::{Node, render_recursively};
|
||||
use crate::nodes::{Node, render_recursively, RenderContext};
|
||||
|
||||
mod nodes;
|
||||
|
||||
|
|
@ -32,12 +31,12 @@ type TaffyMap = PtrWeakKeyHashMap<Weak<GNode>, taffy::node::Node>;
|
|||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::new();
|
||||
let (context, gl_display, window, surface) = create_window(&event_loop);
|
||||
let (buffer_context, gl_display, window, surface) = create_window(&event_loop);
|
||||
|
||||
let renderer = unsafe { OpenGl::new_from_function_cstr(|s| gl_display.get_proc_address(s) as *const _) }
|
||||
.expect("Cannot create renderer");
|
||||
|
||||
let mut canvas = Canvas::new(renderer).expect("Cannot create canvas");
|
||||
let canvas = Canvas::new(renderer).expect("Cannot create canvas");
|
||||
|
||||
let mut taffy = Taffy::new();
|
||||
let mut taffy_map = TaffyMap::new();
|
||||
|
|
@ -48,6 +47,10 @@ fn main() {
|
|||
|
||||
taffy_map.insert(root.clone(), root_node);
|
||||
|
||||
let mut context = RenderContext {
|
||||
canvas
|
||||
};
|
||||
|
||||
event_loop.run(move |event, _target, control_flow| match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
// WindowEvent::CursorMoved { position, .. } => {
|
||||
|
|
@ -57,13 +60,13 @@ fn main() {
|
|||
WindowEvent::Resized(size) => {
|
||||
let width: NonZeroU32 = NonZeroU32::new(size.width).unwrap();
|
||||
let height: NonZeroU32 = NonZeroU32::new(size.height).unwrap();
|
||||
surface.resize(&context, width, height);
|
||||
surface.resize(&buffer_context, width, height);
|
||||
window.request_redraw();
|
||||
},
|
||||
_ => {}
|
||||
},
|
||||
Event::RedrawRequested(_) => {
|
||||
render(&context, &surface, &window, &mut canvas, &root, &taffy_map, &taffy);
|
||||
render(&buffer_context, &surface, &window, &mut context, &root, &taffy_map, &taffy);
|
||||
},
|
||||
_ => {}
|
||||
})
|
||||
|
|
@ -108,25 +111,25 @@ fn create_window(event_loop: &EventLoop<()>) -> (PossiblyCurrentContext, Display
|
|||
}
|
||||
|
||||
fn render(
|
||||
context: &PossiblyCurrentContext,
|
||||
buffer_context: &PossiblyCurrentContext,
|
||||
surface: &Surface<WindowSurface>,
|
||||
window: &Window,
|
||||
canvas: &mut Canvas<OpenGl>,
|
||||
context: &mut RenderContext<OpenGl>,
|
||||
root_node: &Arc<GNode>,
|
||||
taffy_map: &TaffyMap,
|
||||
taffy: &Taffy
|
||||
) {
|
||||
// Make sure the canvas has the right size:
|
||||
let size = window.inner_size();
|
||||
canvas.set_size(size.width, size.height, window.scale_factor() as f32);
|
||||
canvas.scale(1., -1.); // layout is bottom to top, canvas is top to bottom, this might make it easier?
|
||||
canvas.clear_rect(0, 0, size.width, size.height, Color::black());
|
||||
context.canvas.set_size(size.width, size.height, window.scale_factor() as f32);
|
||||
context.canvas.scale(1., -1.); // layout is bottom to top, canvas is top to bottom, this might make it easier?
|
||||
context.canvas.clear_rect(0, 0, size.width, size.height, Color::black());
|
||||
|
||||
// Do the render passes here
|
||||
render_recursively(root_node, canvas, taffy_map, taffy);
|
||||
render_recursively(root_node, context, taffy_map, taffy);
|
||||
|
||||
// Tell renderer to execute all drawing commands
|
||||
canvas.flush();
|
||||
context.canvas.flush();
|
||||
// Display what we've just rendered
|
||||
surface.swap_buffers(context).expect("Could not swap buffers");
|
||||
surface.swap_buffers(buffer_context).expect("Could not swap buffers");
|
||||
}
|
||||
|
|
@ -8,7 +8,12 @@ use taffy::style::Style as TaffyStyle;
|
|||
use taffy::Taffy;
|
||||
use crate::{GNode, TaffyMap};
|
||||
|
||||
pub struct RenderContext<T: Renderer> {
|
||||
pub(crate) canvas: Canvas<T>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
#[non_exhaustive]
|
||||
pub enum Overflow {
|
||||
#[default]
|
||||
/// Content is not clipped and may be rendered outside the element's box
|
||||
|
|
@ -25,26 +30,44 @@ pub struct Style {
|
|||
pub overflow: Overflow
|
||||
}
|
||||
|
||||
type NodeChildren<T> = Vec<Arc<dyn Node<T>>>;
|
||||
|
||||
pub trait Node<T: Renderer> {
|
||||
/// Return style. Usually, you just want self.style.
|
||||
fn style(&self) -> &Style;
|
||||
fn children(&self) -> Option<&Vec<Arc<dyn Node<T>>>>;
|
||||
fn render(&self, canvas: &mut Canvas<T>, layout: &Layout, render_children: &dyn Fn(&mut Canvas<T>) -> ());
|
||||
/// Returns the children of the node. If the node has no children, return None (empty Vec also works, None is mainly for nodes without children support).
|
||||
fn children(&self) -> Option<&NodeChildren<T>>;
|
||||
/// Render the node and its children. render_children gets ['children'] and calls this function there as well. When drawing, the canvas is translated to the node's location.
|
||||
/// Canvas considers 0, 0 to be top left corner (for location after layouting happens)
|
||||
fn render(&self, context: &mut RenderContext<T>, layout: &Layout, render_children: &dyn Fn(&mut RenderContext<T>));
|
||||
}
|
||||
|
||||
pub fn render_recursively(selfref: &Arc<GNode>, canvas: &mut Canvas<OpenGl>, taffy_map: &TaffyMap, taffy: &Taffy) {
|
||||
pub fn render_recursively(selfref: &Arc<GNode>, context: &mut RenderContext<OpenGl>, taffy_map: &TaffyMap, taffy: &Taffy) {
|
||||
let styles = selfref.style();
|
||||
let node = taffy_map.get(selfref).unwrap();
|
||||
let layout = taffy.layout(*node).unwrap();
|
||||
let sself = selfref.clone();
|
||||
canvas.save_with(move |mut canvas| {
|
||||
canvas.translate(layout.location.x, layout.location.y);
|
||||
sself.render(&mut canvas, &layout, & (|canvas| {
|
||||
if let Some(children) = sself.children() {
|
||||
for child in children {
|
||||
render_recursively(child, canvas, taffy_map, taffy);
|
||||
}
|
||||
context.canvas.save();
|
||||
context.canvas.translate(layout.location.x, layout.location.y);
|
||||
match styles.overflow {
|
||||
Overflow::Visible => {},
|
||||
Overflow::Hidden => {
|
||||
context.canvas.scissor(
|
||||
layout.location.x,
|
||||
layout.location.y,
|
||||
layout.size.width,
|
||||
layout.size.height,
|
||||
);
|
||||
}
|
||||
}
|
||||
sself.render(context, layout, & (|context| {
|
||||
if let Some(children) = sself.children() {
|
||||
for child in children {
|
||||
render_recursively(child, context, taffy_map, taffy);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
}));
|
||||
context.canvas.restore();
|
||||
}
|
||||
|
||||
pub struct RedBoxDemo {
|
||||
|
|
@ -69,14 +92,14 @@ impl RedBoxDemo {
|
|||
}
|
||||
|
||||
impl<T: Renderer> Node<T> for RedBoxDemo {
|
||||
fn children(&self) -> Option<&Vec<Arc<dyn Node<T>>>> {
|
||||
None
|
||||
}
|
||||
fn style(&self) -> &Style {
|
||||
&self.style
|
||||
}
|
||||
fn render(&self, canvas: &mut Canvas<T>, layout: &Layout, _render_children: &dyn Fn(&mut Canvas<T>)) {
|
||||
canvas.clear_rect(
|
||||
fn children(&self) -> Option<&NodeChildren<T>> {
|
||||
None
|
||||
}
|
||||
fn render<'a>(&self, context: &mut RenderContext<T>, _layout: &Layout, _render_children: &dyn Fn(&mut RenderContext<T>)) {
|
||||
context.canvas.clear_rect(
|
||||
0,
|
||||
0,
|
||||
30,
|
||||
|
|
|
|||
Loading…
Reference in a new issue