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

Add presentation layer #2220

Merged
merged 8 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions crates/fj-core/src/layers/layers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
objects::Objects,
presentation::Presentation,
validate::{Validation, ValidationConfig},
};

Expand Down Expand Up @@ -31,6 +32,11 @@ pub struct Layers {
///
/// Monitors objects and validates them, as they are inserted.
pub validation: Layer<Validation>,

/// The presentation layer
///
/// Stores data concerning the presentation of objects.
pub presentation: Layer<Presentation>,
}

impl Layers {
Expand Down
1 change: 1 addition & 0 deletions crates/fj-core/src/layers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! See [`Layers`].

pub mod objects;
pub mod presentation;
pub mod validation;

mod layer;
Expand Down
104 changes: 104 additions & 0 deletions crates/fj-core/src/layers/presentation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! Layer infrastructure for [`Presentation`]

use fj_interop::Color;

use crate::{
objects::{AnyObject, Region, Stored},
presentation::Presentation,
storage::Handle,
};

use super::{Command, Event, Layer};

impl Layer<Presentation> {
/// Set the color of a region
pub fn set_color(&mut self, region: Handle<Region>, color: Color) {
let mut events = Vec::new();
self.process(SetColor { region, color }, &mut events);
}

/// Mark an object as being derived from another
pub fn derive_object(
&mut self,
original: AnyObject<Stored>,
derived: AnyObject<Stored>,
) {
let mut events = Vec::new();
self.process(DeriveObject { original, derived }, &mut events);
}
}

/// Set the color of a region
pub struct SetColor {
/// The region to set the color for
region: Handle<Region>,

/// The color to set
color: Color,
}

impl Command<Presentation> for SetColor {
type Result = ();
type Event = Self;

fn decide(
self,
_: &Presentation,
events: &mut Vec<Self::Event>,
) -> Self::Result {
events.push(self);
}
}

impl Event<Presentation> for SetColor {
fn evolve(&self, state: &mut Presentation) {
state.color.insert(self.region.clone(), self.color);
}
}

/// Handle an object being derived from another
pub struct DeriveObject {
/// The original object
original: AnyObject<Stored>,

/// The derived object
derived: AnyObject<Stored>,
}

impl Command<Presentation> for DeriveObject {
type Result = ();
type Event = SetColor;

fn decide(
self,
state: &Presentation,
events: &mut Vec<Self::Event>,
) -> Self::Result {
if let (AnyObject::Region(original), AnyObject::Region(derived)) =
(self.original, self.derived)
{
if let Some(color) = state.color.get(&original.0).cloned() {
events.push(SetColor {
region: derived.into(),
color,
});
}
}
}
}

/// Command for `Layer<Presentation>`
pub enum PresentationCommand {}

/// Event produced by `Layer<Presentation>`
#[derive(Clone)]
pub enum PresentationEvent {
/// The color of a region is being set
SetColor {
/// The region the color is being set for
region: Handle<Region>,

/// The color being set
color: Color,
},
}
1 change: 1 addition & 0 deletions crates/fj-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pub mod geometry;
pub mod layers;
pub mod objects;
pub mod operations;
pub mod presentation;
pub mod queries;
pub mod storage;
pub mod validate;
Expand Down
18 changes: 13 additions & 5 deletions crates/fj-core/src/operations/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@
//!
//! See [`DeriveFrom`].

use crate::{storage::Handle, Core};
use crate::{
objects::{AnyObject, Stored},
storage::Handle,
Core,
};

/// Mark a store object as derived from another
pub trait DeriveFrom {
/// Mark this object as derived from the other object provided
fn derive_from(self, other: &Self, core: &mut Core) -> Self;
}

impl<T> DeriveFrom for Handle<T> {
fn derive_from(self, _other: &Self, _core: &mut Core) -> Self {
// This is currently a no-op. Eventually, it will trigger a command to
// the layers that this information is relevant for.
impl<T> DeriveFrom for Handle<T>
where
Self: Into<AnyObject<Stored>>,
{
fn derive_from(self, other: &Self, core: &mut Core) -> Self {
core.layers
.presentation
.derive_object(other.clone().into(), self.clone().into());
self
}
}
19 changes: 16 additions & 3 deletions crates/fj-core/src/operations/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,33 @@ use fj_interop::Color;
use crate::{
objects::{IsObject, Region},
storage::Handle,
Core,
};

/// Set the color of an object
pub trait SetColor: IsObject {
/// Set the color of the object
fn set_color(&self, color: impl Into<Color>) -> Self::BareObject;
fn set_color(
&self,
color: impl Into<Color>,
core: &mut Core,
) -> Self::BareObject;
}

impl SetColor for Handle<Region> {
fn set_color(&self, color: impl Into<Color>) -> Self::BareObject {
fn set_color(
&self,
color: impl Into<Color>,
core: &mut Core,
) -> Self::BareObject {
let color = color.into();

core.layers.presentation.set_color(self.clone(), color);

Region::new(
self.exterior().clone(),
self.interiors().into_iter().cloned(),
Some(color.into()),
Some(color),
)
}
}
4 changes: 2 additions & 2 deletions crates/fj-core/src/operations/split/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl SplitFace for Shell {

if let Some(color) = face.region().color() {
region = region
.set_color(color)
.set_color(color, core)
.insert(core)
.derive_from(&region, core);
}
Expand Down Expand Up @@ -194,7 +194,7 @@ impl SplitFace for Shell {

if let Some(color) = face.region().color() {
region = region
.set_color(color)
.set_color(color, core)
.insert(core)
.derive_from(&region, core);
}
Expand Down
2 changes: 2 additions & 0 deletions crates/fj-core/src/operations/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use fj_math::{Transform, Vector};
use type_map::TypeMap;

use crate::{
objects::{AnyObject, Stored},
operations::insert::Insert,
storage::{Handle, ObjectId},
Core,
Expand Down Expand Up @@ -69,6 +70,7 @@ pub trait TransformObject: Sized {
impl<T> TransformObject for Handle<T>
where
T: Clone + Insert<Inserted = Handle<T>> + TransformObject + 'static,
Handle<T>: Into<AnyObject<Stored>>,
{
fn transform_with_cache(
&self,
Expand Down
26 changes: 26 additions & 0 deletions crates/fj-core/src/presentation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Presentation data for the object graph
//!
//! See [`Presentation`].

use std::collections::BTreeMap;

use fj_interop::Color;

use crate::{objects::Region, storage::Handle};

/// Presentation data for the object graph
///
/// Assigns attributes relating to the presentation of objects (currently just a
/// color) to those objects (currently only to regions).
///
/// This data is made available through [`Layers`].
///
/// [`Layers`]: crate::layers::Layers
#[derive(Default)]
pub struct Presentation {
/// Color assigned to regions
///
/// Having a color is optional, so map does not necessarily contain
/// assignments for all existing regions.
pub color: BTreeMap<Handle<Region>, Color>,
}
2 changes: 1 addition & 1 deletion models/color/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn model(core: &mut fj::core::Core) -> Solid {
shell.faces().first(),
|face, core| {
[face.update_region(
|region, _| region.set_color([0., 1., 0.]),
|region, core| region.set_color([0., 1., 0.], core),
core,
)]
},
Expand Down