Introduce ghost mode for elements #85

Merged
glen merged 4 commits from Vectornaut/dyna3:ghost-mode into main 2025-06-02 15:56:08 +00:00
4 changed files with 40 additions and 7 deletions
Showing only changes of commit fc230e4993 - Show all commits

View file

@ -90,6 +90,10 @@ summary > div, .regulator {
padding-right: 8px;
}
.element > input {
margin-left: 8px;
}
.element-switch {
width: 18px;
padding-left: 2px;

View file

@ -101,6 +101,7 @@ pub trait Element: Serial + ProblemPoser + DisplayItem {
fn id(&self) -> &String;
fn label(&self) -> &String;
fn representation(&self) -> Signal<DVector<f64>>;
fn ghost(&self) -> Signal<bool>;
// the regulators the element is subject to. the assembly that owns the
// element is responsible for keeping this set up to date
@ -154,6 +155,7 @@ pub struct Sphere {
pub label: String,
pub color: ElementColor,
pub representation: Signal<DVector<f64>>,
pub ghost: Signal<bool>,
pub regulators: Signal<BTreeSet<Rc<dyn Regulator>>>,
serial: u64,
column_index: Cell<Option<usize>>
@ -173,6 +175,7 @@ impl Sphere {
label: label,
color: color,
representation: create_signal(representation),
ghost: create_signal(false),
regulators: create_signal(BTreeSet::new()),
serial: Self::next_serial(),
column_index: None.into()
@ -210,6 +213,10 @@ impl Element for Sphere {
self.representation
}
fn ghost(&self) -> Signal<bool> {
self.ghost
}
fn regulators(&self) -> Signal<BTreeSet<Rc<dyn Regulator>>> {
self.regulators
}
@ -244,6 +251,7 @@ pub struct Point {
pub label: String,
pub color: ElementColor,
pub representation: Signal<DVector<f64>>,
pub ghost: Signal<bool>,
pub regulators: Signal<BTreeSet<Rc<dyn Regulator>>>,
serial: u64,
column_index: Cell<Option<usize>>
@ -263,6 +271,7 @@ impl Point {
label,
color,
representation: create_signal(representation),
ghost: create_signal(false),
regulators: create_signal(BTreeSet::new()),
serial: Self::next_serial(),
column_index: None.into()
@ -296,6 +305,10 @@ impl Element for Point {
self.representation
}
fn ghost(&self) -> Signal<bool> {
self.ghost
}
fn regulators(&self) -> Signal<BTreeSet<Rc<dyn Regulator>>> {
self.regulators
}

View file

@ -25,6 +25,7 @@ use crate::{
struct SceneSpheres {
representations: Vec<DVector<f64>>,
colors: Vec<ElementColor>,
opacities: Vec<f32>,
highlights: Vec<f32>
}
@ -33,6 +34,7 @@ impl SceneSpheres {
SceneSpheres {
representations: Vec::new(),
colors: Vec::new(),
opacities: Vec::new(),
highlights: Vec::new()
}
}
@ -41,9 +43,10 @@ impl SceneSpheres {
self.representations.len().try_into().expect("Number of spheres must fit in a 32-bit integer")
}
fn push(&mut self, representation: DVector<f64>, color: ElementColor, highlight: f32) {
fn push(&mut self, representation: DVector<f64>, color: ElementColor, opacity: f32, highlight: f32) {
self.representations.push(representation);
self.colors.push(color);
self.opacities.push(opacity);
self.highlights.push(highlight);
}
}
@ -98,11 +101,16 @@ pub trait DisplayItem {
impl DisplayItem for Sphere {
fn show(&self, scene: &mut Scene, selected: bool) {
const HIGHLIGHT: f32 = 0.2; /* SCAFFOLDING */
/* SCAFFOLDING */
const DEFAULT_OPACITY: f32 = 0.5;
const GHOST_OPACITY: f32 = 0.2;
const HIGHLIGHT: f32 = 0.2;
let representation = self.representation.get_clone_untracked();
let color = if selected { self.color.map(|channel| 0.2 + 0.8*channel) } else { self.color };
let opacity = if self.ghost.get() { GHOST_OPACITY } else { DEFAULT_OPACITY };
let highlight = if selected { 1.0 } else { HIGHLIGHT };
scene.spheres.push(representation, color, highlight);
scene.spheres.push(representation, color, opacity, highlight);
}
// this method should be kept synchronized with `sphere_cast` in
@ -365,6 +373,7 @@ pub fn Display() -> View {
state.assembly.elements.with(|elts| {
for elt in elts {
elt.representation().track();
elt.ghost().track();
}
});
state.selection.track();
@ -395,7 +404,6 @@ pub fn Display() -> View {
const SHRINKING_SPEED: f64 = 0.15; // in length units per second
// display parameters
const OPACITY: f32 = 0.5; /* SCAFFOLDING */
const LAYER_THRESHOLD: i32 = 0; /* DEBUG */
const DEBUG_MODE: i32 = 0; /* DEBUG */
@ -648,7 +656,7 @@ pub fn Display() -> View {
let sphere_color = &mut [0.0; 4];
sphere_color[..3].copy_from_slice(&scene.spheres.colors[n]);
sphere_color[3] = OPACITY;
sphere_color[3] = scene.spheres.opacities[n];
ctx.uniform3fv_with_f32_array(
sphere_sp_locs[n].as_ref(),
@ -854,7 +862,11 @@ pub fn Display() -> View {
let (dir, pixel_size) = event_dir(&event);
console::log_1(&JsValue::from(dir.to_string()));
let mut clicked: Option<(Rc<dyn Element>, f64)> = None;
for elt in state.assembly.elements.get_clone_untracked() {
let tangible_elts = state.assembly.elements
.get_clone_untracked()
.into_iter()
.filter(|elt| !elt.ghost().get());
for elt in tangible_elts {
match assembly_to_world.with(|asm_to_world| elt.cast(dir, asm_to_world, pixel_size)) {
Some(depth) => match clicked {
Some((_, best_depth)) => {

View file

@ -202,7 +202,11 @@ fn ElementOutlineItem(element: Rc<dyn Element>) -> View {
) {
div(class="element-label") { (label) }
div(class="element-representation") { (rep_components) }
div(class="status")

Did we intentionally remove this indicator, which flags an element with an invalidly specified regulator when the regulator list is closed? The removal looks like a regression—especially because we didn't remove the associated CSS—but I wanted to check in case we decided on it in a meeting and I forgot to write it down.

Did we intentionally remove this indicator, which flags an element with an invalidly specified regulator when the regulator list is closed? The removal looks like a regression—especially because we didn't remove the associated CSS—but I wanted to check in case we decided on it in a meeting and I forgot to write it down.

I think I never responded to this. If you think there should be some indication of a regulator with bad input (or something like that) and there currently is no such indication, absolutely feel free to file an issue. I don't recall any discussion that we should not have such an indication. (And hopefully filing issues/recording notes in some permanent online fashion immediately after our meetings will help with confidence on such matters!)

I think I never responded to this. If you think there should be some indication of a regulator with bad input (or something like that) and there currently is no such indication, absolutely feel free to file an issue. I don't recall any discussion that we should not have such an indication. (And hopefully filing issues/recording notes in some permanent online fashion immediately after our meetings will help with confidence on such matters!)
input(
r#type="checkbox",
bind:checked=element.ghost(),
on:click=|event: MouseEvent| event.stop_propagation()
)
}
}
ul(class="regulators") {