iris: fold render state into Ui
This commit is contained in:
1 parent
44a5da378b
commit
9b4c690916
25 files changed
+421
-390
No files matched your search
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
ActiveData, WidgetId,
|
||||
UiRenderState, WidgetId,
|
||||
util::{HashMap, HashSet},
|
||||
};
|
||||
use std::any::{Any, TypeId};
|
||||
@@ -56,7 +56,6 @@ pub trait Controller<Rsc>: ControllerValue {
|
||||
|
||||
pub struct ControllerManager<Rsc> {
|
||||
by_widget: HashMap<WidgetId, HashMap<TypeId, Box<dyn Controller<Rsc>>>>,
|
||||
parents: HashMap<WidgetId, Option<WidgetId>>,
|
||||
borrowed: HashSet<ControllerId>,
|
||||
removed_while_borrowed: HashSet<WidgetId>,
|
||||
command_target: Option<ControllerId>,
|
||||
@@ -68,7 +67,6 @@ impl<Rsc> Default for ControllerManager<Rsc> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
by_widget: Default::default(),
|
||||
parents: Default::default(),
|
||||
borrowed: Default::default(),
|
||||
removed_while_borrowed: Default::default(),
|
||||
command_target: None,
|
||||
@@ -111,7 +109,11 @@ impl<Rsc: 'static> ControllerManager<Rsc> {
|
||||
.then_some(ControllerId { host, kind })
|
||||
}
|
||||
|
||||
pub fn nearest_id<C: Controller<Rsc>>(&self, mut origin: WidgetId) -> Option<ControllerId> {
|
||||
pub fn nearest_id<C: Controller<Rsc>>(
|
||||
&self,
|
||||
mut origin: WidgetId,
|
||||
render_state: &UiRenderState,
|
||||
) -> Option<ControllerId> {
|
||||
let kind = TypeId::of::<C>();
|
||||
loop {
|
||||
let candidate = ControllerId { host: origin, kind };
|
||||
@@ -122,13 +124,14 @@ impl<Rsc: 'static> ControllerManager<Rsc> {
|
||||
if let Some(id) = self.id::<C>(origin) {
|
||||
return Some(id);
|
||||
}
|
||||
origin = self.parents.get(&origin).copied().flatten()?;
|
||||
origin = render_state.active.get(&origin)?.parent?;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_to<C: Controller<Rsc>>(
|
||||
&self,
|
||||
mut origin: WidgetId,
|
||||
render_state: &UiRenderState,
|
||||
) -> Option<(ControllerId, Vec<WidgetId>)> {
|
||||
let mut path = Vec::new();
|
||||
loop {
|
||||
@@ -136,18 +139,10 @@ impl<Rsc: 'static> ControllerManager<Rsc> {
|
||||
if let Some(id) = self.id::<C>(origin) {
|
||||
return Some((id, path));
|
||||
}
|
||||
origin = self.parents.get(&origin).copied().flatten()?;
|
||||
origin = render_state.active.get(&origin)?.parent?;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, active: &ActiveData) {
|
||||
self.parents.insert(active.id, active.parent);
|
||||
}
|
||||
|
||||
pub fn undraw(&mut self, active: &ActiveData) {
|
||||
self.parents.remove(&active.id);
|
||||
}
|
||||
|
||||
pub fn take<C: Controller<Rsc>>(&mut self, id: ControllerId) -> Option<C> {
|
||||
if id.kind != TypeId::of::<C>() {
|
||||
return None;
|
||||
@@ -232,9 +227,18 @@ impl<Rsc: 'static> ControllerManager<Rsc> {
|
||||
self.command_boundary
|
||||
}
|
||||
|
||||
pub(crate) fn is_below(&self, mut widget: WidgetId, ancestor: WidgetId) -> bool {
|
||||
pub(crate) fn is_below(
|
||||
&self,
|
||||
mut widget: WidgetId,
|
||||
ancestor: WidgetId,
|
||||
render_state: &UiRenderState,
|
||||
) -> bool {
|
||||
loop {
|
||||
let Some(parent) = self.parents.get(&widget).copied().flatten() else {
|
||||
let Some(parent) = render_state
|
||||
.active
|
||||
.get(&widget)
|
||||
.and_then(|active| active.parent)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if parent == ancestor {
|
||||
@@ -250,7 +254,6 @@ impl<Rsc: 'static> ControllerManager<Rsc> {
|
||||
|
||||
pub fn remove(&mut self, host: WidgetId) {
|
||||
self.by_widget.remove(&host);
|
||||
self.parents.remove(&host);
|
||||
if self.borrowed.iter().any(|id| id.host == host) {
|
||||
self.removed_while_borrowed.insert(host);
|
||||
}
|
||||
|
||||
@@ -60,14 +60,12 @@ impl<Rsc: HasEvents + 'static> EventsLike for EventManager<Rsc> {
|
||||
}
|
||||
|
||||
fn draw(&mut self, active: &ActiveData) {
|
||||
self.controllers.draw(active);
|
||||
for t in self.widget_to_types.get(&active.id).into_flat_iter() {
|
||||
self.types.get_mut(t).unwrap().draw(active);
|
||||
}
|
||||
}
|
||||
|
||||
fn undraw(&mut self, active: &ActiveData) {
|
||||
self.controllers.undraw(active);
|
||||
for t in self.widget_to_types.get(&active.id).into_flat_iter() {
|
||||
self.types.get_mut(t).unwrap().undraw(active);
|
||||
}
|
||||
|
||||
+27
-9
@@ -44,7 +44,11 @@ pub trait HasEvents: Sized + UiRsc + HasState {
|
||||
origin: impl IdLike,
|
||||
f: impl FnOnce(ControllerId, &mut C, &mut Self) -> T,
|
||||
) -> Option<T> {
|
||||
let id = self.events().controllers.nearest_id::<C>(origin.id())?;
|
||||
let render_handle = self.ui().render_state();
|
||||
let id = self
|
||||
.events()
|
||||
.controllers
|
||||
.nearest_id::<C>(origin.id(), &render_handle.get())?;
|
||||
self.with_controller(id, |controller, rsc| f(id, controller, rsc))
|
||||
}
|
||||
|
||||
@@ -54,14 +58,22 @@ pub trait HasEvents: Sized + UiRsc + HasState {
|
||||
|
||||
fn run_command(&mut self, command: Command) -> CommandResult {
|
||||
let revision = self.events().controllers.command_target_revision();
|
||||
if let Some(boundary) = self.events().controllers.command_boundary()
|
||||
&& self
|
||||
.events()
|
||||
.controllers
|
||||
.command_target()
|
||||
.is_none_or(|target| !self.events().controllers.is_below(target.host(), boundary))
|
||||
{
|
||||
return CommandResult::Unused;
|
||||
if let Some(boundary) = self.events().controllers.command_boundary() {
|
||||
let render_handle = self.ui().render_state();
|
||||
let outside_boundary =
|
||||
self.events()
|
||||
.controllers
|
||||
.command_target()
|
||||
.is_none_or(|target| {
|
||||
!self.events().controllers.is_below(
|
||||
target.host(),
|
||||
boundary,
|
||||
&render_handle.get(),
|
||||
)
|
||||
});
|
||||
if outside_boundary {
|
||||
return CommandResult::Unused;
|
||||
}
|
||||
}
|
||||
let Some((id, mut controller)) = self.events_mut().controllers.take_command_target() else {
|
||||
return CommandResult::Unused;
|
||||
@@ -96,6 +108,12 @@ pub trait RunEvents: HasEvents {
|
||||
data: <E::Event as Event>::Data<'_>,
|
||||
state: &mut Self::State,
|
||||
) {
|
||||
// Keep the last completed frame read-locked for the whole callback.
|
||||
// Rsc methods may take further shared reads through `render_state`,
|
||||
// while any attempt to start a render from an event fails at the
|
||||
// mutable-borrow boundary instead of exposing an in-progress tree.
|
||||
let render_handle = self.ui().render_state();
|
||||
let _render_state = render_handle.get();
|
||||
let f = self.events_mut().get_type::<E>().run_fn(id);
|
||||
f(EventCtx { state, data }, self)
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
UiData, UiRenderState,
|
||||
Ui, UiData,
|
||||
render::{
|
||||
data::{PrimitiveInstance, instance_slot_layout},
|
||||
texture::GpuTextures,
|
||||
@@ -180,13 +180,11 @@ impl UiRenderNode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
ui: &mut UiData,
|
||||
ui_render: &mut UiRenderState,
|
||||
) -> FrameUpdateStats {
|
||||
pub fn update(&mut self, device: &Device, queue: &Queue, ui: &mut Ui) -> FrameUpdateStats {
|
||||
let render_handle = ui.render_state.clone();
|
||||
let mut render_guard = render_handle.get_mut();
|
||||
let ui_render = &mut *render_guard;
|
||||
let ui_data: &mut UiData = ui;
|
||||
self.active.clear();
|
||||
for (i, order) in ui_render.layers.iter_mut() {
|
||||
self.active.push(i);
|
||||
@@ -233,11 +231,11 @@ impl UiRenderNode {
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let (entries, dirty) = ui.masks.for_upload();
|
||||
let (entries, dirty) = ui_data.masks.for_upload();
|
||||
let masks_resized = self.masks.update(device, queue, entries, dirty);
|
||||
let (entries, dirty) = ui.move_offsets.for_upload();
|
||||
let (entries, dirty) = ui_data.move_offsets.for_upload();
|
||||
let moves_resized = self.move_offsets.update(device, queue, entries, dirty);
|
||||
let (entries, dirty) = ui.paints.for_upload();
|
||||
let (entries, dirty) = ui_data.paints.for_upload();
|
||||
let paints_resized = self.paints.update(device, queue, entries, dirty);
|
||||
if masks_resized || moves_resized || instances_resized || paints_resized {
|
||||
self.masks_group = Self::masks_group(
|
||||
@@ -249,7 +247,9 @@ impl UiRenderNode {
|
||||
&self.paints,
|
||||
);
|
||||
}
|
||||
let rebuild_main = self.textures.update(&mut ui.textures, &self.rsc_layout);
|
||||
let rebuild_main = self
|
||||
.textures
|
||||
.update(&mut ui_data.textures, &self.rsc_layout);
|
||||
if rebuild_main {
|
||||
self.rsc_group = Self::rsc_group(device, &self.rsc_layout, &self.textures);
|
||||
}
|
||||
|
||||
+84
-2
@@ -1,6 +1,11 @@
|
||||
use crate::{
|
||||
Mask, MoveOffset, Paints, TextData, Textures, WeakWidget, WidgetId, Widgets, util::TrackedArena,
|
||||
};
|
||||
use std::{
|
||||
cell::{Ref, RefCell, RefMut},
|
||||
ops::{Deref, DerefMut},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
mod access;
|
||||
mod active;
|
||||
@@ -23,6 +28,75 @@ pub struct UiData {
|
||||
animating: Vec<WidgetId>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RenderHandle {
|
||||
pub(crate) render_state: Rc<RefCell<UiRenderState>>,
|
||||
}
|
||||
|
||||
impl RenderHandle {
|
||||
/// The retained result of the last completed frame. The framework holds
|
||||
/// the corresponding mutable borrow for the whole of a render update, so
|
||||
/// a read attempted while that state is incomplete fails at the boundary
|
||||
/// instead of observing half a frame.
|
||||
pub fn get(&self) -> Ref<'_, UiRenderState> {
|
||||
self.render_state
|
||||
.try_borrow()
|
||||
.expect("render state cannot be read while a frame is being rendered")
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut(&self) -> RefMut<'_, UiRenderState> {
|
||||
self.render_state
|
||||
.try_borrow_mut()
|
||||
.expect("render state cannot be mutated while it is being read")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RenderHandle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
render_state: Rc::new(RefCell::new(UiRenderState::new())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Ui {
|
||||
data: UiData,
|
||||
pub(crate) render_state: RenderHandle,
|
||||
}
|
||||
|
||||
impl Ui {
|
||||
/// A read-only handle to the retained result of the last completed frame.
|
||||
/// The handle is owned so a caller may keep its read guard while mutating
|
||||
/// unrelated resources on the `Rsc` that owns this `Ui`.
|
||||
pub fn render_state(&self) -> RenderHandle {
|
||||
self.render_state.clone()
|
||||
}
|
||||
|
||||
pub fn resize(&self, size: impl Into<crate::util::Vec2>) {
|
||||
self.render_state.get_mut().resize(size);
|
||||
}
|
||||
|
||||
pub fn set_density(&mut self, density: f32) {
|
||||
self.data.text.density = density;
|
||||
self.render_state.get_mut().set_density(density);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Ui {
|
||||
type Target = UiData;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Ui {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl UiData {
|
||||
/// Ask for `id`'s [`crate::Widget::tick`] to run every frame until it
|
||||
/// says it is done. Idempotent -- registering an already-animating
|
||||
@@ -48,8 +122,16 @@ impl UiData {
|
||||
}
|
||||
|
||||
pub trait UiRsc {
|
||||
fn ui(&self) -> &UiData;
|
||||
fn ui_mut(&mut self) -> &mut UiData;
|
||||
fn ui(&self) -> &Ui;
|
||||
fn ui_mut(&mut self) -> &mut Ui;
|
||||
|
||||
fn draw<'a>(&mut self, root: impl Into<Option<&'a crate::StrongWidget>>)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let render_state = self.ui().render_state.clone();
|
||||
render_state.get_mut().update(root, self);
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn on_add(&mut self, id: WeakWidget) {}
|
||||
|
||||
+28
-25
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
Axis, Len, MoveOffset, PaintId, RegionAlign, RenderedText, Size, StrongWidget, TextAttrs,
|
||||
TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2,
|
||||
TextBuffer, TextData, TextureHandle, UiData, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2,
|
||||
WidgetId,
|
||||
render::{
|
||||
Drawn, GlyphPrimitive, IMAGE_BINDING, Mask, MaskIdx, MoveIdx, NOT_DRAWN, Primitive,
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
};
|
||||
|
||||
pub struct Painter<'a> {
|
||||
pub(super) state: &'a mut UiRenderState,
|
||||
pub(super) render_state: &'a mut UiRenderState,
|
||||
pub(super) rsc: &'a mut dyn UiRsc,
|
||||
|
||||
pub(super) region: UiRegion,
|
||||
@@ -46,7 +46,7 @@ impl DrawResult<'_, '_> {
|
||||
if !self.painter.size_dependencies.contains(&self.child) {
|
||||
self.painter.size_dependencies.push(self.child);
|
||||
}
|
||||
self.painter.state.active[&self.child].size
|
||||
self.painter.render_state.active[&self.child].size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ impl<'a> Painter<'a> {
|
||||
};
|
||||
let h = match self.take_recycled(P::BINDING, drawn) {
|
||||
Some(h) => {
|
||||
self.state.primitives.recycle(&h, inst);
|
||||
self.render_state.primitives.recycle(&h, inst);
|
||||
h
|
||||
}
|
||||
None => self.state.write_primitive(self.layer, drawn, inst),
|
||||
None => self.render_state.write_primitive(self.layer, drawn, inst),
|
||||
};
|
||||
if self.mask != MaskIdx::NONE {
|
||||
self.rsc.ui_mut().masks.push_ref(self.mask);
|
||||
@@ -109,7 +109,7 @@ impl<'a> Painter<'a> {
|
||||
|
||||
/// Take ownership of a handle this widget just wrote.
|
||||
fn own(&mut self, h: PrimitiveHandle) {
|
||||
self.state
|
||||
self.render_state
|
||||
.primitives
|
||||
.set_handle_index(h.slot, self.primitives.len() as u32);
|
||||
self.primitives.push(h);
|
||||
@@ -156,7 +156,7 @@ impl<'a> Painter<'a> {
|
||||
/// with no radius argument anywhere that could fall out of step with
|
||||
/// the one being drawn.
|
||||
pub fn set_mask_to_widget<W: ?Sized>(&mut self, shape: &StrongWidget<W>) {
|
||||
let slot = self.state.first_primitive(shape.id()).unwrap_or_else(|| {
|
||||
let slot = self.render_state.first_primitive(shape.id()).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"'{}' was given as a mask's shape but drew no primitive, so there is nothing to \
|
||||
clip to",
|
||||
@@ -172,7 +172,7 @@ impl<'a> Painter<'a> {
|
||||
"set_mask called twice while drawing one widget: the second would replace the first \
|
||||
rather than nest inside it",
|
||||
);
|
||||
let binding = self.state.primitives.instance(shape).binding;
|
||||
let binding = self.render_state.primitives.instance(shape).binding;
|
||||
assert_eq!(
|
||||
binding,
|
||||
RectPrimitive::BINDING,
|
||||
@@ -248,7 +248,7 @@ impl<'a> Painter<'a> {
|
||||
let next = [offset.x, offset.y];
|
||||
if self.rsc.ui().move_offsets[slot.idx()].delta != next {
|
||||
self.rsc.ui_mut().move_offsets.get_mut(slot).delta = next;
|
||||
self.state.note_move();
|
||||
self.render_state.note_move();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +262,10 @@ impl<'a> Painter<'a> {
|
||||
{
|
||||
None
|
||||
} else {
|
||||
self.state.active.get(&id.id()).map(|a| a.size.axis(axis))
|
||||
self.render_state
|
||||
.active
|
||||
.get(&id.id())
|
||||
.map(|a| a.size.axis(axis))
|
||||
};
|
||||
if len.is_some() && !self.size_dependencies.contains(&id.id()) {
|
||||
self.size_dependencies.push(id.id());
|
||||
@@ -277,7 +280,7 @@ impl<'a> Painter<'a> {
|
||||
) -> DrawResult<'p, 'a> {
|
||||
self.children.push(id.id());
|
||||
let parent_move_slot = self.child_move_slot.unwrap_or(self.move_slot);
|
||||
self.state.draw_inner(
|
||||
self.render_state.draw_inner(
|
||||
self.layer,
|
||||
id.id(),
|
||||
region,
|
||||
@@ -300,16 +303,16 @@ impl<'a> Painter<'a> {
|
||||
) -> DrawResult<'p, 'a> {
|
||||
let region = region.within(&self.region);
|
||||
let retained = self
|
||||
.state
|
||||
.render_state
|
||||
.active
|
||||
.get(&id.id())
|
||||
.map(|active| (active.layer, active.mask));
|
||||
if self.state.place(id.id(), region, self.rsc).is_some() {
|
||||
if self.render_state.place(id.id(), region, self.rsc).is_some() {
|
||||
} else if let Some((layer, mask)) = retained {
|
||||
self.children.push(id.id());
|
||||
self.rsc.widgets_mut().needs_redraw.insert(id.id());
|
||||
let parent_move_slot = self.child_move_slot.unwrap_or(self.move_slot);
|
||||
self.state.draw_inner(
|
||||
self.render_state.draw_inner(
|
||||
layer,
|
||||
id.id(),
|
||||
region,
|
||||
@@ -322,7 +325,7 @@ impl<'a> Painter<'a> {
|
||||
} else {
|
||||
self.children.push(id.id());
|
||||
let parent_move_slot = self.child_move_slot.unwrap_or(self.move_slot);
|
||||
self.state.draw_inner(
|
||||
self.render_state.draw_inner(
|
||||
self.layer,
|
||||
id.id(),
|
||||
region,
|
||||
@@ -385,7 +388,7 @@ impl<'a> Painter<'a> {
|
||||
fn write_image(&mut self, texture_idx: u32, region: UiRegion) {
|
||||
let h = match self.take_recycled(IMAGE_BINDING, Drawn::Yes) {
|
||||
Some(h) => {
|
||||
self.state.primitives.recycle_image(
|
||||
self.render_state.primitives.recycle_image(
|
||||
&h,
|
||||
self.id,
|
||||
texture_idx,
|
||||
@@ -395,7 +398,7 @@ impl<'a> Painter<'a> {
|
||||
);
|
||||
h
|
||||
}
|
||||
None => self.state.write_image(
|
||||
None => self.render_state.write_image(
|
||||
self.layer,
|
||||
self.id,
|
||||
texture_idx,
|
||||
@@ -416,9 +419,9 @@ impl<'a> Painter<'a> {
|
||||
attrs: &TextAttrs,
|
||||
width: Option<f32>,
|
||||
) -> RenderedText {
|
||||
let density = self.state.density;
|
||||
self.state.shape_count += 1;
|
||||
let ui = self.rsc.ui_mut();
|
||||
let density = self.render_state.density;
|
||||
self.render_state.shape_count += 1;
|
||||
let ui: &mut UiData = self.rsc.ui_mut();
|
||||
ui.text
|
||||
.render(buffer, attrs, width, &mut ui.textures, density)
|
||||
}
|
||||
@@ -477,17 +480,17 @@ impl<'a> Painter<'a> {
|
||||
}
|
||||
|
||||
pub fn output_size(&self) -> Vec2 {
|
||||
self.state.output_size
|
||||
self.render_state.output_size
|
||||
}
|
||||
|
||||
/// Physical pixels per `dp` -- see `UiRenderState::density`'s field
|
||||
/// doc. What `Len::dp`'s `apply_rest` call resolves against.
|
||||
pub fn density(&self) -> f32 {
|
||||
self.state.density
|
||||
self.render_state.density
|
||||
}
|
||||
|
||||
pub fn px_size(&mut self) -> Vec2 {
|
||||
self.region.size().to_abs(self.state.output_size)
|
||||
self.region.size().to_abs(self.render_state.output_size)
|
||||
}
|
||||
|
||||
pub fn text_data(&mut self) -> &mut TextData {
|
||||
@@ -495,11 +498,11 @@ impl<'a> Painter<'a> {
|
||||
}
|
||||
|
||||
pub fn child_layer(&mut self) {
|
||||
self.layer = self.state.layers.child(self.layer);
|
||||
self.layer = self.render_state.layers.child(self.layer);
|
||||
}
|
||||
|
||||
pub fn next_layer(&mut self) {
|
||||
self.layer = self.state.layers.next(self.layer);
|
||||
self.layer = self.render_state.layers.next(self.layer);
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
|
||||
@@ -441,7 +441,7 @@ impl UiRenderState {
|
||||
]
|
||||
});
|
||||
let mut painter = Painter {
|
||||
state: self,
|
||||
render_state: self,
|
||||
region,
|
||||
mask,
|
||||
move_slot,
|
||||
@@ -466,7 +466,7 @@ impl UiRenderState {
|
||||
widget.size_hint(Axis::X).map(|len| len.fold_dp(density)),
|
||||
widget.size_hint(Axis::Y).map(|len| len.fold_dp(density)),
|
||||
];
|
||||
painter.state.draw_count += 1;
|
||||
painter.render_state.draw_count += 1;
|
||||
widget.draw(&mut painter);
|
||||
let size = painter.size.unwrap_or_else(|| {
|
||||
panic!(
|
||||
@@ -491,10 +491,10 @@ impl UiRenderState {
|
||||
);
|
||||
}
|
||||
drop(widget);
|
||||
painter.state.draw_started.remove(&id);
|
||||
painter.render_state.draw_started.remove(&id);
|
||||
|
||||
let Painter {
|
||||
state: _,
|
||||
render_state: _,
|
||||
rsc: _,
|
||||
region,
|
||||
mask: _,
|
||||
|
||||
Reference in new issue
Block a user