lgui-core 0.2.0

Platform-neutral runtime and UI primitives for LGUI
Documentation
use super::*;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct HostNodeId {
    pub(super) index: u32,
    pub(super) generation: u32,
}

impl fmt::Display for HostNodeId {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "{}:{}", self.index, self.generation)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HostUpdateKind {
    Layout,
    Paint,
    Interaction,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum HostMutation {
    InsertNode {
        id: HostNodeId,
        source: UiId,
        bounds: UiRect,
    },
    RemoveNode {
        id: HostNodeId,
        source: UiId,
        old_bounds: UiRect,
    },
    UpdateProps {
        id: HostNodeId,
        source: UiId,
        kind: HostUpdateKind,
        old_bounds: UiRect,
        new_bounds: UiRect,
    },
    ReorderChildren {
        id: HostNodeId,
        source: UiId,
        bounds: UiRect,
    },
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SceneMutation {
    Insert(HostNodeId),
    Update(HostNodeId),
    Remove(HostNodeId),
    Reorder,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct HostCommitMetrics {
    pub host_nodes: usize,
    pub scene_nodes: usize,
    pub visited_host_nodes: usize,
    pub compiled_scene_nodes: usize,
    pub host_mutations: usize,
    pub scene_mutations: usize,
    pub reused_scene_nodes: usize,
}

#[cfg(feature = "diagnostics-timing")]
#[derive(Clone, Copy, Debug, Default)]
#[doc(hidden)]
pub struct HostCommitTimings {
    pub change_scan_ms: f32,
    pub node_patch_ms: f32,
    pub scene_reconcile_ms: f32,
    pub scene_snapshot_ms: f32,
    pub damage_ms: f32,
    pub finalize_ms: f32,
}

#[derive(Clone, Debug)]
pub struct HostCommit {
    pub mutations: Vec<HostMutation>,
    pub scene_mutations: Vec<SceneMutation>,
    pub damage: DamageReport,
    pub scene: Scene,
    pub metrics: HostCommitMetrics,
    pub semantics: SemanticUpdate,
    #[cfg(feature = "diagnostics-timing")]
    #[doc(hidden)]
    pub timings: HostCommitTimings,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DamageReason {
    FirstCommit,
    Explicit,
    Insert,
    Remove,
    Layout,
    Paint,
    Interaction,
    Structure,
    Clean,
}

#[derive(Clone, Debug)]
pub struct DamageDetail {
    pub reason: DamageReason,
    pub node_id: Option<UiId>,
    pub old_bounds: Option<UiRect>,
    pub new_bounds: Option<UiRect>,
    pub rects: Vec<UiRect>,
}

#[derive(Clone, Debug)]
pub struct DamageReport {
    pub dirty: DirtyRegionSet,
    pub reasons: Vec<DamageReason>,
    pub details: Vec<DamageDetail>,
}

pub(super) struct HostNode {
    pub(super) source: UiId,
    pub(super) mounted: bool,
    pub(super) parent: Option<HostNodeId>,
    pub(super) children: Vec<HostNodeId>,
    pub(super) kind: UiNodeKind,
    pub(super) layout_bounds: UiRect,
    pub(super) paint_bounds: UiRect,
    pub(super) interaction: InteractionFlags,
    pub(super) node: UiNode,
}

pub(super) struct HostSlot {
    pub(super) generation: u32,
    pub(super) node: Option<HostNode>,
}

#[derive(Clone)]
pub(super) struct SceneNode {
    pub(super) signature: u64,
    pub(super) commands: Vec<ScenePrimitive>,
}

#[derive(Default)]
pub struct HostRuntime {
    pub(super) slots: Vec<HostSlot>,
    pub(super) free: Vec<u32>,
    pub(super) sources: HashMap<UiId, HostNodeId>,
    pub(super) paint_order: Vec<HostNodeId>,
    pub(super) scene: HashMap<HostNodeId, SceneNode>,
    pub(super) scene_order: Vec<HostNodeId>,
    pub(super) scene_ranges: HashMap<HostNodeId, (usize, usize)>,
    pub(super) composed_scene: Scene,
    pub(super) semantics: HashMap<UiId, SemanticNode>,
    pub(super) initialized: bool,
}

impl HostRuntime {
    pub(crate) fn estimated_bytes(&self) -> usize {
        let host_nodes = self
            .slots
            .iter()
            .filter_map(|slot| slot.node.as_ref())
            .map(|node| {
                std::mem::size_of::<HostNode>()
                    .saturating_add(
                        node.children
                            .capacity()
                            .saturating_mul(std::mem::size_of::<HostNodeId>()),
                    )
                    .saturating_add(node.node.estimated_bytes())
            })
            .sum::<usize>();
        let scene_nodes = self
            .scene
            .values()
            .map(|node| crate::core::estimate_scene_commands_bytes(&node.commands))
            .sum::<usize>();
        std::mem::size_of::<Self>()
            .saturating_add(host_nodes)
            .saturating_add(scene_nodes)
            .saturating_add(self.composed_scene.estimated_bytes())
    }
}