From 216036e49c5282e0152e10fe1eee2f614538c971 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 10 May 2020 19:02:17 +0200 Subject: [PATCH] Refactor: Clump area logic together inside of Memory --- emigui/src/containers/area.rs | 22 ++++------ emigui/src/context.rs | 4 +- emigui/src/memory.rs | 77 ++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 44 deletions(-) diff --git a/emigui/src/containers/area.rs b/emigui/src/containers/area.rs index 93972f45..3eff3ad6 100644 --- a/emigui/src/containers/area.rs +++ b/emigui/src/containers/area.rs @@ -99,18 +99,12 @@ impl Area { let id = ctx.register_unique_id(id, "Area", default_pos); let layer = Layer { order, id }; - let (mut state, _is_new) = match ctx.memory().get_area(id) { - Some(state) => (state, false), - None => { - let state = State { - pos: default_pos, - size: Vec2::zero(), - interactable, - vel: Vec2::zero(), - }; - (state, true) - } - }; + let mut state = ctx.memory().areas.get(id).unwrap_or_else(|| State { + pos: default_pos, + size: Vec2::zero(), + interactable, + vel: Vec2::zero(), + }); state.pos = fixed_pos.unwrap_or(state.pos); state.pos = state.pos.round(); @@ -162,9 +156,9 @@ impl Area { // ); if move_interact.active || mouse_pressed_on_area(ctx, layer) { - ctx.memory().move_area_to_top(layer); + ctx.memory().areas.move_to_top(layer); } - ctx.memory().set_area_state(layer, state); + ctx.memory().areas.set_state(layer, state); move_interact } diff --git a/emigui/src/context.rs b/emigui/src/context.rs index 15f718ac..93f442ab 100644 --- a/emigui/src/context.rs +++ b/emigui/src/context.rs @@ -183,7 +183,7 @@ impl Context { fn drain_paint_lists(&self) -> Vec<(Rect, PaintCmd)> { let memory = self.memory(); - self.graphics().drain(memory.area_order()).collect() + self.graphics().drain(memory.areas.order()).collect() } fn paint(&self) -> PaintBatches { @@ -218,7 +218,7 @@ impl Context { id, }; // Ensure we register the background area so it is painted: - self.memory().set_area_state( + self.memory().areas.set_state( layer, containers::area::State { pos: rect.min, diff --git a/emigui/src/memory.rs b/emigui/src/memory.rs index 8fce358d..42d708e3 100644 --- a/emigui/src/memory.rs +++ b/emigui/src/memory.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use crate::{ - containers::{area, collapsing_header, resize, scroll_area}, + containers::{area, collapsing_header, menu, resize, scroll_area}, Id, Layer, Pos2, Rect, }; @@ -18,39 +18,61 @@ pub struct Memory { // states of various types of widgets pub(crate) collapsing_headers: HashMap, + pub(crate) menu_bar: HashMap, pub(crate) scroll_areas: HashMap, pub(crate) resize: HashMap, - area: HashMap, + pub(crate) areas: Areas, +} + +#[derive(Clone, Debug, Default, serde_derive::Deserialize, serde_derive::Serialize)] +#[serde(default)] +pub struct Areas { + areas: HashMap, /// Top is last - area_order: Vec, - area_visible_last_frame: HashSet, - area_visible_current_frame: HashSet, + order: Vec, + visible_last_frame: HashSet, + visible_current_frame: HashSet, } impl Memory { - pub(crate) fn get_area(&mut self, id: Id) -> Option { - self.area.get(&id).cloned() + pub(crate) fn begin_frame(&mut self) { + self.areas.begin_frame() } - pub(crate) fn area_order(&self) -> &[Layer] { - &self.area_order + /// TODO: call once at the start of the frame for the current mouse pos + pub fn layer_at(&self, pos: Pos2) -> Option { + self.areas.layer_at(pos) + } +} + +impl Areas { + pub(crate) fn count(&self) -> usize { + self.areas.len() } - pub(crate) fn set_area_state(&mut self, layer: Layer, state: area::State) { - self.area_visible_current_frame.insert(layer); - let did_insert = self.area.insert(layer.id, state).is_none(); + pub(crate) fn get(&mut self, id: Id) -> Option { + self.areas.get(&id).cloned() + } + + pub(crate) fn order(&self) -> &[Layer] { + &self.order + } + + pub(crate) fn set_state(&mut self, layer: Layer, state: area::State) { + self.visible_current_frame.insert(layer); + let did_insert = self.areas.insert(layer.id, state).is_none(); if did_insert { - self.area_order.push(layer); - self.area_order.sort_by_key(|layer| layer.order); + self.order.push(layer); + self.order.sort_by_key(|layer| layer.order); } } /// TODO: call once at the start of the frame for the current mouse pos pub fn layer_at(&self, pos: Pos2) -> Option { - for layer in self.area_order.iter().rev() { - if self.is_area_visible(layer) { - if let Some(state) = self.area.get(&layer.id) { + for layer in self.order.iter().rev() { + if self.is_visible(layer) { + if let Some(state) = self.areas.get(&layer.id) { if state.interactable { let rect = Rect::from_min_size(state.pos, state.size); if rect.contains(pos) { @@ -63,26 +85,25 @@ impl Memory { None } - pub fn is_area_visible(&self, layer: &Layer) -> bool { - self.area_visible_last_frame.contains(layer) - || self.area_visible_current_frame.contains(layer) + pub fn is_visible(&self, layer: &Layer) -> bool { + self.visible_last_frame.contains(layer) || self.visible_current_frame.contains(layer) } - pub fn move_area_to_top(&mut self, layer: Layer) { - self.area_visible_current_frame.insert(layer); + pub fn move_to_top(&mut self, layer: Layer) { + self.visible_current_frame.insert(layer); - if self.area_order.last() == Some(&layer) { + if self.order.last() == Some(&layer) { return; // common case early-out } - if let Some(index) = self.area_order.iter().position(|x| *x == layer) { - self.area_order.remove(index); + if let Some(index) = self.order.iter().position(|x| *x == layer) { + self.order.remove(index); } - self.area_order.push(layer); + self.order.push(layer); - self.area_order.sort_by_key(|layer| layer.order); + self.order.sort_by_key(|layer| layer.order); } pub(crate) fn begin_frame(&mut self) { - self.area_visible_last_frame = std::mem::take(&mut self.area_visible_current_frame); + self.visible_last_frame = std::mem::take(&mut self.visible_current_frame); } }