overflow: hidden/scroll scissor support, remove depth
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::{
|
||||
drawing,
|
||||
layout::Widget,
|
||||
renderer_vk::text::custom_glyph::CustomGlyph,
|
||||
transform_stack::{self, TransformStack},
|
||||
stack::{self, ScissorStack, TransformStack},
|
||||
widget::{self},
|
||||
};
|
||||
|
||||
@@ -37,6 +37,22 @@ impl Boundary {
|
||||
size: Vec2::new(transform.dim.x, transform.dim.y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn top(&self) -> f32 {
|
||||
self.pos.y
|
||||
}
|
||||
|
||||
pub const fn bottom(&self) -> f32 {
|
||||
self.pos.y + self.size.y
|
||||
}
|
||||
|
||||
pub const fn left(&self) -> f32 {
|
||||
self.pos.x
|
||||
}
|
||||
|
||||
pub const fn right(&self) -> f32 {
|
||||
self.pos.x + self.size.x
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@@ -115,7 +131,6 @@ pub struct Rectangle {
|
||||
pub struct PrimitiveExtent {
|
||||
pub(super) boundary: Boundary,
|
||||
pub(super) transform: Mat4,
|
||||
pub(super) depth: f32, // FIXME: remove this
|
||||
}
|
||||
|
||||
pub enum RenderPrimitive {
|
||||
@@ -126,15 +141,39 @@ pub enum RenderPrimitive {
|
||||
ScissorDisable,
|
||||
}
|
||||
|
||||
pub struct DrawParams<'a> {
|
||||
pub layout: &'a Layout,
|
||||
pub debug_draw: bool,
|
||||
}
|
||||
|
||||
fn has_overflow_clip(style: &taffy::Style) -> bool {
|
||||
style.overflow.x != taffy::Overflow::Visible || style.overflow.y != taffy::Overflow::Visible
|
||||
}
|
||||
|
||||
fn primitive_debug_rect(boundary: &Boundary, transform: &Mat4, color: drawing::Color) -> drawing::RenderPrimitive {
|
||||
drawing::RenderPrimitive::Rectangle(
|
||||
PrimitiveExtent {
|
||||
boundary: *boundary,
|
||||
transform: *transform,
|
||||
},
|
||||
Rectangle {
|
||||
border: 1.0,
|
||||
border_color: color,
|
||||
color: Color::new(0.0, 0.0, 0.0, 0.0),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn draw_widget(
|
||||
layout: &Layout,
|
||||
params: &DrawParams,
|
||||
state: &mut DrawState,
|
||||
node_id: taffy::NodeId,
|
||||
style: &taffy::Style,
|
||||
widget: &Widget,
|
||||
parent_transform: &glam::Mat4,
|
||||
) {
|
||||
let Ok(l) = layout.state.tree.layout(node_id) else {
|
||||
let Ok(l) = params.layout.state.tree.layout(node_id) else {
|
||||
debug_assert!(false);
|
||||
return;
|
||||
};
|
||||
@@ -148,16 +187,34 @@ fn draw_widget(
|
||||
None => (Vec2::default(), None),
|
||||
};
|
||||
|
||||
state.transform_stack.push(transform_stack::Transform {
|
||||
state.transform_stack.push(stack::Transform {
|
||||
pos: Vec2::new(l.location.x, l.location.y) - shift,
|
||||
transform,
|
||||
dim: Vec2::new(l.size.width, l.size.height),
|
||||
});
|
||||
|
||||
// FIXME: this is temporary
|
||||
// FIXME: implement scissor stack (do not allow growing!)
|
||||
if info.is_some() {
|
||||
if params.debug_draw {
|
||||
let boundary = drawing::Boundary::construct(state.transform_stack);
|
||||
state.primitives.push(primitive_debug_rect(
|
||||
&boundary,
|
||||
&transform,
|
||||
Color::new(0.0, 1.0, 1.0, 0.5),
|
||||
));
|
||||
}
|
||||
|
||||
let scissor_pushed = info.is_some() && has_overflow_clip(style);
|
||||
|
||||
if scissor_pushed {
|
||||
let boundary = drawing::Boundary::construct(state.transform_stack);
|
||||
state.scissor_stack.push(boundary);
|
||||
if params.debug_draw {
|
||||
state.primitives.push(primitive_debug_rect(
|
||||
&boundary,
|
||||
&transform,
|
||||
Color::new(1.0, 0.0, 1.0, 1.0),
|
||||
));
|
||||
}
|
||||
|
||||
state.primitives.push(drawing::RenderPrimitive::ScissorEnable(boundary));
|
||||
}
|
||||
|
||||
@@ -169,10 +226,11 @@ fn draw_widget(
|
||||
|
||||
widget_state.draw_all(state, &draw_params);
|
||||
|
||||
draw_children(layout, state, node_id, &transform);
|
||||
draw_children(params, state, node_id, &transform);
|
||||
|
||||
if info.is_some() {
|
||||
if scissor_pushed {
|
||||
state.primitives.push(drawing::RenderPrimitive::ScissorDisable);
|
||||
state.scissor_stack.pop();
|
||||
}
|
||||
|
||||
state.transform_stack.pop();
|
||||
@@ -182,7 +240,9 @@ fn draw_widget(
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_children(layout: &Layout, state: &mut DrawState, parent_node_id: taffy::NodeId, model: &glam::Mat4) {
|
||||
fn draw_children(params: &DrawParams, state: &mut DrawState, parent_node_id: taffy::NodeId, model: &glam::Mat4) {
|
||||
let layout = ¶ms.layout;
|
||||
|
||||
for node_id in layout.state.tree.child_ids(parent_node_id) {
|
||||
let Some(widget_id) = layout.state.tree.get_node_context(node_id).copied() else {
|
||||
debug_assert!(false);
|
||||
@@ -199,33 +259,37 @@ fn draw_children(layout: &Layout, state: &mut DrawState, parent_node_id: taffy::
|
||||
continue;
|
||||
};
|
||||
|
||||
state.depth += 0.01;
|
||||
draw_widget(layout, state, node_id, style, widget, model);
|
||||
state.depth -= 0.01;
|
||||
draw_widget(params, state, node_id, style, widget, model);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(layout: &Layout) -> anyhow::Result<Vec<RenderPrimitive>> {
|
||||
pub fn draw(params: &DrawParams) -> anyhow::Result<Vec<RenderPrimitive>> {
|
||||
let mut primitives = Vec::<RenderPrimitive>::new();
|
||||
let mut transform_stack = TransformStack::new();
|
||||
let mut scissor_stack = ScissorStack::new();
|
||||
let model = glam::Mat4::IDENTITY;
|
||||
|
||||
let Some(root_widget) = layout.state.widgets.get(layout.root_widget) else {
|
||||
let Some(root_widget) = params.layout.state.widgets.get(params.layout.root_widget) else {
|
||||
panic!();
|
||||
};
|
||||
|
||||
let Ok(style) = layout.state.tree.style(layout.root_node) else {
|
||||
let Ok(style) = params.layout.state.tree.style(params.layout.root_node) else {
|
||||
panic!();
|
||||
};
|
||||
|
||||
let mut params = DrawState {
|
||||
scissor_stack.push(Boundary {
|
||||
pos: Default::default(),
|
||||
size: Vec2::splat(1.0e12),
|
||||
});
|
||||
|
||||
let mut state = DrawState {
|
||||
primitives: &mut primitives,
|
||||
transform_stack: &mut transform_stack,
|
||||
layout,
|
||||
depth: 0.0,
|
||||
scissor_stack: &mut scissor_stack,
|
||||
layout: params.layout,
|
||||
};
|
||||
|
||||
draw_widget(layout, &mut params, layout.root_node, style, root_widget, &model);
|
||||
draw_widget(params, &mut state, params.layout.root_node, style, root_widget, &model);
|
||||
|
||||
Ok(primitives)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user