Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiflavor layers #6477

Merged
merged 6 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 114 additions & 53 deletions lib/rust/ensogl/core/src/display/scene/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,15 @@ pub struct LayerModel {
pub name: String,
camera: RefCell<Camera2d>,
pub shape_system_registry: ShapeSystemRegistry,
shape_system_to_symbol_info_map: RefCell<HashMap<ShapeSystemId, ShapeSystemSymbolInfo>>,
symbol_to_shape_system_map: RefCell<HashMap<SymbolId, ShapeSystemId>>,
shape_system_to_symbol_info_map:
RefCell<HashMap<ShapeSystemIdWithFlavor, ShapeSystemSymbolInfo>>,
symbol_to_shape_system_map: RefCell<HashMap<SymbolId, ShapeSystemIdWithFlavor>>,
elements: RefCell<BTreeSet<LayerItem>>,
symbols_renderable: RefCell<RenderGroup>,
depth_order: RefCell<DependencyGraph<LayerItem>>,
depth_order: RefCell<DependencyGraph<LayerOrderItem>>,
depth_order_dirty: dirty::SharedBool<OnDepthOrderDirty>,
parent: Rc<RefCell<Option<Sublayers>>>,
global_element_depth_order: RefCell<DependencyGraph<LayerItem>>,
global_element_depth_order: RefCell<DependencyGraph<LayerOrderItem>>,
sublayers: Sublayers,
symbol_buffer_partitions: RefCell<HashMap<ShapeSystemId, usize>>,
mask: RefCell<Option<WeakLayer>>,
Expand Down Expand Up @@ -496,21 +497,11 @@ impl LayerModel {
self.symbols_renderable.borrow()
}

/// Return the [`SymbolId`] of the provided [`LayerItem`] if it was added to the current
/// layer.
pub fn symbol_id_of_element(&self, element: LayerItem) -> Option<SymbolId> {
use LayerItem::*;
match element {
Symbol(id) => Some(id),
ShapeSystem(id) => self.shape_system_to_symbol_info_map.borrow().get(&id).map(|t| t.id),
}
}

/// Add depth-order dependency between two [`LayerItem`]s in this layer.
/// Add depth-order dependency between two [`LayerOrderItem`]s in this layer.
pub fn add_elements_order_dependency(
&self,
below: impl Into<LayerItem>,
above: impl Into<LayerItem>,
below: impl Into<LayerOrderItem>,
above: impl Into<LayerOrderItem>,
) {
let below = below.into();
let above = above.into();
Expand All @@ -523,8 +514,8 @@ impl LayerModel {
/// if the dependency was found, and `false` otherwise.
pub fn remove_elements_order_dependency(
&self,
below: impl Into<LayerItem>,
above: impl Into<LayerItem>,
below: impl Into<LayerOrderItem>,
above: impl Into<LayerOrderItem>,
) -> bool {
let below = below.into();
let above = above.into();
Expand Down Expand Up @@ -630,11 +621,12 @@ impl LayerModel {
/// Remove the [`ShapeSystem`] registered in this layer together with all of its [`Symbol`]s.
pub fn remove_shape_system(&self, shape_system_id: ShapeSystemId) {
self.depth_order_dirty.set();
self.elements.borrow_mut().remove(&LayerItem::ShapeSystem(shape_system_id));
if let Some(symbol_id) =
self.shape_system_to_symbol_info_map.borrow_mut().remove(&shape_system_id)
{
self.symbol_to_shape_system_map.borrow_mut().remove(&symbol_id.id);
for flavor in self.shape_system_registry.flavors(shape_system_id) {
let id = ShapeSystemIdWithFlavor { id: shape_system_id, flavor };
self.elements.borrow_mut().remove(&LayerItem::ShapeSystem(id));
if let Some(symbol_id) = self.shape_system_to_symbol_info_map.borrow_mut().remove(&id) {
self.symbol_to_shape_system_map.borrow_mut().remove(&symbol_id.id);
}
}
}

Expand All @@ -648,7 +640,7 @@ impl LayerModel {
#[profile(Debug)]
pub(crate) fn update_internal(
&self,
global_element_depth_order: Option<&DependencyGraph<LayerItem>>,
global_element_depth_order: Option<&DependencyGraph<LayerOrderItem>>,
parent_depth_order_changed: bool,
) -> bool {
let mut was_dirty = false;
Expand Down Expand Up @@ -683,8 +675,8 @@ impl LayerModel {
/// to learn more).
fn combined_depth_order_graph(
&self,
global_element_depth_order: Option<&DependencyGraph<LayerItem>>,
) -> DependencyGraph<LayerItem> {
global_element_depth_order: Option<&DependencyGraph<LayerOrderItem>>,
) -> DependencyGraph<LayerOrderItem> {
let mut graph = if let Some(global_element_depth_order) = global_element_depth_order {
let mut graph = global_element_depth_order.clone();
graph.extend(self.depth_order.borrow().clone().into_iter());
Expand All @@ -696,35 +688,56 @@ impl LayerModel {
if let LayerItem::ShapeSystem(id) = element {
if let Some(info) = self.shape_system_to_symbol_info_map.borrow().get(id) {
for &id2 in &info.below {
graph.insert_dependency(*element, id2.into());
graph.insert_dependency(element.into(), id2.into());
}
for &id2 in &info.above {
graph.insert_dependency(id2.into(), *element);
graph.insert_dependency(id2.into(), element.into());
}
}
}
}
graph
}

fn depth_sort(&self, global_element_depth_order: Option<&DependencyGraph<LayerItem>>) {
fn depth_sort(&self, global_element_depth_order: Option<&DependencyGraph<LayerOrderItem>>) {
let graph = self.combined_depth_order_graph(global_element_depth_order);
let elements_sorted = self.elements.borrow().iter().copied().collect_vec();
let sorted_elements = graph.into_unchecked_topo_sort(elements_sorted);
let sorted_symbols = sorted_elements
.into_iter()
.filter_map(|element| match element {
LayerItem::Symbol(symbol_id) => Some(symbol_id),
LayerItem::ShapeSystem(id) => {
let out = self.shape_system_to_symbol_info_map.borrow().get(&id).map(|t| t.id);
if out.is_none() {
warn!("Trying to perform depth-order of non-existing element '{:?}'.", id)
}
out
let elements = self.elements.borrow();
let mut order_items = elements.iter().map(|&e| LayerOrderItem::from(e)).collect_vec();
order_items.dedup();
let dependency_sorted_elements = graph.into_unchecked_topo_sort(order_items);
let mut result = Vec::with_capacity(self.elements.borrow().len());
for element in dependency_sorted_elements {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked sorted_symbols more than result.

match element {
LayerOrderItem::Symbol(id) => result.push(id),
LayerOrderItem::ShapeSystem(id) => {
let lower_bound = LayerItem::ShapeSystem(ShapeSystemIdWithFlavor {
id,
flavor: ShapeSystemFlavor::MIN,
});
let flavors = elements
.range(lower_bound..)
.take_while(|e| matches!(e, LayerItem::ShapeSystem(info) if info.id == id));
result.extend(flavors.filter_map(|item| match *item {
LayerItem::Symbol(symbol_id) => Some(symbol_id),
LayerItem::ShapeSystem(id) => {
let out = self
.shape_system_to_symbol_info_map
.borrow()
.get(&id)
.map(|t| t.id);
if out.is_none() {
warn!(
"Trying to perform depth-order of non-existing element '{:?}'.",
id
)
}
out
}
}))
}
})
.collect();
self.symbols_renderable.borrow_mut().set(sorted_symbols);
};
}
self.symbols_renderable.borrow_mut().set(result);
}
}

Expand Down Expand Up @@ -898,8 +911,8 @@ impl LayerModel {
/// otherwise. All sublayers will inherit these rules.
pub fn add_global_elements_order_dependency(
&self,
below: impl Into<LayerItem>,
above: impl Into<LayerItem>,
below: impl Into<LayerOrderItem>,
above: impl Into<LayerOrderItem>,
) -> bool {
let below = below.into();
let above = above.into();
Expand All @@ -914,8 +927,8 @@ impl LayerModel {
/// if the dependency was found, and `false` otherwise.
pub fn remove_global_elements_order_dependency(
&self,
below: impl Into<LayerItem>,
above: impl Into<LayerItem>,
below: impl Into<LayerOrderItem>,
above: impl Into<LayerOrderItem>,
) -> bool {
let below = below.into();
let above = above.into();
Expand Down Expand Up @@ -1254,16 +1267,50 @@ newtype_prim! {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
#[allow(missing_docs)]
pub enum LayerItem {
Symbol(SymbolId),
ShapeSystem(ShapeSystemIdWithFlavor),
}

impl From<ShapeSystemIdWithFlavor> for LayerItem {
fn from(t: ShapeSystemIdWithFlavor) -> Self {
Self::ShapeSystem(t)
}
}


// === LayerOrderItem ===

/// Identifies an item only in terms of the information necessary to describe ordering
/// relationships. This is equivalent to [`LayerItem`], except different flavors of the same layer
/// are not distinguished.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
#[allow(missing_docs)]
pub enum LayerOrderItem {
Symbol(SymbolId),
ShapeSystem(ShapeSystemId),
}

impl From<ShapeSystemId> for LayerItem {
impl From<ShapeSystemId> for LayerOrderItem {
fn from(t: ShapeSystemId) -> Self {
Self::ShapeSystem(t)
}
}

impl From<LayerItem> for LayerOrderItem {
fn from(t: LayerItem) -> Self {
Self::from(&t)
}
}

impl From<&LayerItem> for LayerOrderItem {
fn from(t: &LayerItem) -> Self {
match *t {
LayerItem::Symbol(id) => Self::Symbol(id),
LayerItem::ShapeSystem(ShapeSystemIdWithFlavor { id, .. }) => Self::ShapeSystem(id),
}
}
}



// =====================
Expand Down Expand Up @@ -1318,7 +1365,10 @@ impl {
let above = S::always_above().to_vec();
let below = S::always_below().to_vec();
let ordering = ShapeSystemStaticDepthOrdering {above,below};
let shape_system_info = ShapeSystemInfo::new(system_id,ordering);
let system_id_with_flavor = ShapeSystemIdWithFlavor {
id: system_id, flavor: S::flavor(data),
};
let shape_system_info = ShapeSystemInfo::new(system_id_with_flavor, ordering);
*entry.instance_count += 1;
(shape_system_info, symbol_id, shape_instance, global_instance_id)
})
Expand Down Expand Up @@ -1346,6 +1396,10 @@ impl {

(no_more_instances, system_id, PhantomData)
}

fn flavors(&self, shape_system_id: ShapeSystemId) -> impl Iterator<Item=ShapeSystemFlavor> {
self.shape_system_flavors.get(&shape_system_id).cloned().unwrap_or_default().into_iter()
}
}}

impl ShapeSystemRegistryData {
Expand Down Expand Up @@ -1410,8 +1464,8 @@ impl ShapeSystemRegistryData {
// === ShapeSystemInfo ===
// =======================

/// [`ShapeSystemInfoTemplate`] specialized for [`ShapeSystemId`].
pub type ShapeSystemInfo = ShapeSystemInfoTemplate<ShapeSystemId>;
/// [`ShapeSystemInfoTemplate`] specialized for [`ShapeSystemIdWithFlavor`].
pub type ShapeSystemInfo = ShapeSystemInfoTemplate<ShapeSystemIdWithFlavor>;

/// [`ShapeSystemInfoTemplate`] specialized for [`SymbolId`].
pub type ShapeSystemSymbolInfo = ShapeSystemInfoTemplate<SymbolId>;
Expand Down Expand Up @@ -1446,6 +1500,13 @@ impl<T> ShapeSystemInfoTemplate<T> {
}
}

/// Identifies a specific flavor of a shape system.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ShapeSystemIdWithFlavor {
id: ShapeSystemId,
flavor: ShapeSystemFlavor,
}



// ======================
Expand Down
6 changes: 6 additions & 0 deletions lib/rust/ensogl/core/src/display/shape/primitive/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ pub struct ShapeSystemFlavor {
pub flavor: u64,
}

impl ShapeSystemFlavor {
/// A value that will compare less-than or equal-to any other flavor. Not guaranteed to be a
/// valid flavor for any particular shape system.
pub const MIN: Self = ShapeSystemFlavor { flavor: u64::MIN };
}



// =====================
Expand Down