Compare commits
10 Commits
1f3a6eea3b
...
fc39f2a5f3
Author | SHA1 | Date | |
---|---|---|---|
|
fc39f2a5f3 | ||
|
6e42681b71 | ||
|
327a1267d5 | ||
|
e12f4332fe | ||
|
5ce5f855d5 | ||
|
e42b8da897 | ||
|
bbeebe4464 | ||
|
fb292d8b5b | ||
|
a3fce9d298 | ||
|
5b522c12ee |
@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<title>dyna3</title>
|
<title>dyna3</title>
|
||||||
<link data-trunk rel="css" href="main.css"/>
|
<link data-trunk rel="css" href="main.css"/>
|
||||||
<link href="https://fonts.bunny.net/css?family=lato:ital,wght@0,400;1,400&display=swap" rel="stylesheet">
|
<link href="https://fonts.bunny.net/css?family=fira-sans:ital,wght@0,400;1,400&display=swap" rel="stylesheet">
|
||||||
<link href="https://fonts.bunny.net/css?family=noto-emoji:wght@400&text=%f0%9f%94%97%e2%9a%a0&display=swap" rel="stylesheet">
|
<link href="https://fonts.bunny.net/css?family=noto-emoji:wght@400&text=%f0%9f%94%97%e2%9a%a0&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body></body>
|
||||||
|
@ -2,7 +2,7 @@ body {
|
|||||||
margin: 0px;
|
margin: 0px;
|
||||||
color: #fcfcfc;
|
color: #fcfcfc;
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
font-family: 'Lato';
|
font-family: 'Fira Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sidebar */
|
/* sidebar */
|
||||||
@ -36,7 +36,7 @@ body {
|
|||||||
|
|
||||||
/* KLUDGE */
|
/* KLUDGE */
|
||||||
#add-remove > button.emoji {
|
#add-remove > button.emoji {
|
||||||
font-family: 'Noto Emoji';
|
font-family: 'Noto Emoji', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* outline */
|
/* outline */
|
||||||
@ -102,6 +102,7 @@ details[open]:has(li) .elt-switch::after {
|
|||||||
.elt-rep > div {
|
.elt-rep > div {
|
||||||
padding: 2px 0px 0px 0px;
|
padding: 2px 0px 0px 0px;
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
width: 56px;
|
width: 56px;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use std::collections::BTreeSet; /* DEBUG */
|
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
use web_sys::{console, wasm_bindgen::JsValue};
|
use web_sys::{console, wasm_bindgen::JsValue};
|
||||||
|
|
||||||
@ -7,64 +6,52 @@ use crate::{engine, AppState, assembly::{Assembly, Constraint, Element}};
|
|||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
fn load_gen_assemb(assembly: &Assembly) {
|
fn load_gen_assemb(assembly: &Assembly) {
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("gemini_a"),
|
String::from("gemini_a"),
|
||||||
label: String::from("Castor"),
|
String::from("Castor"),
|
||||||
color: [1.00_f32, 0.25_f32, 0.00_f32],
|
[1.00_f32, 0.25_f32, 0.00_f32],
|
||||||
rep: engine::sphere(0.5, 0.5, 0.0, 1.0),
|
engine::sphere(0.5, 0.5, 0.0, 1.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("gemini_b"),
|
String::from("gemini_b"),
|
||||||
label: String::from("Pollux"),
|
String::from("Pollux"),
|
||||||
color: [0.00_f32, 0.25_f32, 1.00_f32],
|
[0.00_f32, 0.25_f32, 1.00_f32],
|
||||||
rep: engine::sphere(-0.5, -0.5, 0.0, 1.0),
|
engine::sphere(-0.5, -0.5, 0.0, 1.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("ursa_major"),
|
String::from("ursa_major"),
|
||||||
label: String::from("Ursa major"),
|
String::from("Ursa major"),
|
||||||
color: [0.25_f32, 0.00_f32, 1.00_f32],
|
[0.25_f32, 0.00_f32, 1.00_f32],
|
||||||
rep: engine::sphere(-0.5, 0.5, 0.0, 0.75),
|
engine::sphere(-0.5, 0.5, 0.0, 0.75)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("ursa_minor"),
|
String::from("ursa_minor"),
|
||||||
label: String::from("Ursa minor"),
|
String::from("Ursa minor"),
|
||||||
color: [0.25_f32, 1.00_f32, 0.00_f32],
|
[0.25_f32, 1.00_f32, 0.00_f32],
|
||||||
rep: engine::sphere(0.5, -0.5, 0.0, 0.5),
|
engine::sphere(0.5, -0.5, 0.0, 0.5)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("moon_deimos"),
|
String::from("moon_deimos"),
|
||||||
label: String::from("Deimos"),
|
String::from("Deimos"),
|
||||||
color: [0.75_f32, 0.75_f32, 0.00_f32],
|
[0.75_f32, 0.75_f32, 0.00_f32],
|
||||||
rep: engine::sphere(0.0, 0.15, 1.0, 0.25),
|
engine::sphere(0.0, 0.15, 1.0, 0.25)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("moon_phobos"),
|
String::from("moon_phobos"),
|
||||||
label: String::from("Phobos"),
|
String::from("Phobos"),
|
||||||
color: [0.00_f32, 0.75_f32, 0.50_f32],
|
[0.00_f32, 0.75_f32, 0.50_f32],
|
||||||
rep: engine::sphere(0.0, -0.15, -1.0, 0.25),
|
engine::sphere(0.0, -0.15, -1.0, 0.25)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,84 +59,68 @@ fn load_gen_assemb(assembly: &Assembly) {
|
|||||||
fn load_low_curv_assemb(assembly: &Assembly) {
|
fn load_low_curv_assemb(assembly: &Assembly) {
|
||||||
let a = 0.75_f64.sqrt();
|
let a = 0.75_f64.sqrt();
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "central".to_string(),
|
"central".to_string(),
|
||||||
label: "Central".to_string(),
|
"Central".to_string(),
|
||||||
color: [0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
rep: engine::sphere(0.0, 0.0, 0.0, 1.0),
|
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "assemb_plane".to_string(),
|
"assemb_plane".to_string(),
|
||||||
label: "Assembly plane".to_string(),
|
"Assembly plane".to_string(),
|
||||||
color: [0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
rep: engine::sphere_with_offset(0.0, 0.0, 1.0, 0.0, 0.0),
|
engine::sphere_with_offset(0.0, 0.0, 1.0, 0.0, 0.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "side1".to_string(),
|
"side1".to_string(),
|
||||||
label: "Side 1".to_string(),
|
"Side 1".to_string(),
|
||||||
color: [1.00_f32, 0.00_f32, 0.25_f32],
|
[1.00_f32, 0.00_f32, 0.25_f32],
|
||||||
rep: engine::sphere_with_offset(1.0, 0.0, 0.0, 1.0, 0.0),
|
engine::sphere_with_offset(1.0, 0.0, 0.0, 1.0, 0.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "side2".to_string(),
|
"side2".to_string(),
|
||||||
label: "Side 2".to_string(),
|
"Side 2".to_string(),
|
||||||
color: [0.25_f32, 1.00_f32, 0.00_f32],
|
[0.25_f32, 1.00_f32, 0.00_f32],
|
||||||
rep: engine::sphere_with_offset(-0.5, a, 0.0, 1.0, 0.0),
|
engine::sphere_with_offset(-0.5, a, 0.0, 1.0, 0.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "side3".to_string(),
|
"side3".to_string(),
|
||||||
label: "Side 3".to_string(),
|
"Side 3".to_string(),
|
||||||
color: [0.00_f32, 0.25_f32, 1.00_f32],
|
[0.00_f32, 0.25_f32, 1.00_f32],
|
||||||
rep: engine::sphere_with_offset(-0.5, -a, 0.0, 1.0, 0.0),
|
engine::sphere_with_offset(-0.5, -a, 0.0, 1.0, 0.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "corner1".to_string(),
|
"corner1".to_string(),
|
||||||
label: "Corner 1".to_string(),
|
"Corner 1".to_string(),
|
||||||
color: [0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
rep: engine::sphere(-4.0/3.0, 0.0, 0.0, 1.0/3.0),
|
engine::sphere(-4.0/3.0, 0.0, 0.0, 1.0/3.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: "corner2".to_string(),
|
"corner2".to_string(),
|
||||||
label: "Corner 2".to_string(),
|
"Corner 2".to_string(),
|
||||||
color: [0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
rep: engine::sphere(2.0/3.0, -4.0/3.0 * a, 0.0, 1.0/3.0),
|
engine::sphere(2.0/3.0, -4.0/3.0 * a, 0.0, 1.0/3.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
let _ = assembly.try_insert_element(
|
let _ = assembly.try_insert_element(
|
||||||
Element {
|
Element::new(
|
||||||
id: String::from("corner3"),
|
String::from("corner3"),
|
||||||
label: String::from("Corner 3"),
|
String::from("Corner 3"),
|
||||||
color: [0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
rep: engine::sphere(2.0/3.0, 4.0/3.0 * a, 0.0, 1.0/3.0),
|
engine::sphere(2.0/3.0, 4.0/3.0 * a, 0.0, 1.0/3.0)
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,15 +187,15 @@ pub fn AddRemove() -> View {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
let rep = create_signal(0.0);
|
let rep = create_signal(0.0);
|
||||||
|
let rep_valid = create_signal(false);
|
||||||
let active = create_signal(true);
|
let active = create_signal(true);
|
||||||
state.assembly.insert_constraint(Constraint {
|
state.assembly.insert_constraint(Constraint {
|
||||||
args: args,
|
args: args,
|
||||||
rep: rep,
|
rep: rep,
|
||||||
rep_text: create_signal(String::new()),
|
rep_text: create_signal(String::new()),
|
||||||
rep_valid: create_signal(false),
|
rep_valid: rep_valid,
|
||||||
active: active,
|
active: active,
|
||||||
});
|
});
|
||||||
state.assembly.realize();
|
|
||||||
state.selection.update(|sel| sel.clear());
|
state.selection.update(|sel| sel.clear());
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
@ -242,15 +213,14 @@ pub fn AddRemove() -> View {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// update the realization when the constraint activated, or
|
// update the realization when the constraint becomes active
|
||||||
// edited while active
|
// and valid, or is edited while active and valid
|
||||||
create_effect(move || {
|
create_effect(move || {
|
||||||
|
console::log_1(&JsValue::from(
|
||||||
|
format!("Constraint ({}, {}) updated", args.0, args.1)
|
||||||
|
));
|
||||||
rep.track();
|
rep.track();
|
||||||
console::log_2(
|
if active.get() && rep_valid.get() {
|
||||||
&JsValue::from("Lorentz product updated to"),
|
|
||||||
&JsValue::from(rep.get_untracked())
|
|
||||||
);
|
|
||||||
if active.get() {
|
|
||||||
state.assembly.realize();
|
state.assembly.realize();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -12,13 +12,32 @@ pub struct Element {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub label: String,
|
pub label: String,
|
||||||
pub color: [f32; 3],
|
pub color: [f32; 3],
|
||||||
pub rep: DVector<f64>,
|
pub rep: Signal<DVector<f64>>,
|
||||||
pub constraints: BTreeSet<usize>,
|
pub constraints: Signal<BTreeSet<usize>>,
|
||||||
|
|
||||||
// internal properties, not reflected in any view
|
// internal properties, not reflected in any view
|
||||||
pub index: usize
|
pub index: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Element {
|
||||||
|
pub fn new(
|
||||||
|
id: String,
|
||||||
|
label: String,
|
||||||
|
color: [f32; 3],
|
||||||
|
rep: DVector<f64>
|
||||||
|
) -> Element {
|
||||||
|
Element {
|
||||||
|
id: id,
|
||||||
|
label: label,
|
||||||
|
color: color,
|
||||||
|
rep: create_signal(rep),
|
||||||
|
constraints: create_signal(BTreeSet::default()),
|
||||||
|
index: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Constraint {
|
pub struct Constraint {
|
||||||
pub args: (usize, usize),
|
pub args: (usize, usize),
|
||||||
@ -82,24 +101,23 @@ impl Assembly {
|
|||||||
|
|
||||||
// create and insert a new element
|
// create and insert a new element
|
||||||
self.insert_element_unchecked(
|
self.insert_element_unchecked(
|
||||||
Element {
|
Element::new(
|
||||||
id: id,
|
id,
|
||||||
label: format!("Sphere {}", id_num),
|
format!("Sphere {}", id_num),
|
||||||
color: [0.75_f32, 0.75_f32, 0.75_f32],
|
[0.75_f32, 0.75_f32, 0.75_f32],
|
||||||
rep: DVector::<f64>::from_column_slice(&[0.0, 0.0, 0.0, 0.5, -0.5]),
|
DVector::<f64>::from_column_slice(&[0.0, 0.0, 0.0, 0.5, -0.5])
|
||||||
constraints: BTreeSet::default(),
|
)
|
||||||
index: 0
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_constraint(&self, constraint: Constraint) {
|
pub fn insert_constraint(&self, constraint: Constraint) {
|
||||||
let args = constraint.args;
|
let args = constraint.args;
|
||||||
let key = self.constraints.update(|csts| csts.insert(constraint));
|
let key = self.constraints.update(|csts| csts.insert(constraint));
|
||||||
self.elements.update(|elts| {
|
let arg_constraints = self.elements.with(
|
||||||
elts[args.0].constraints.insert(key);
|
|elts| (elts[args.0].constraints, elts[args.1].constraints)
|
||||||
elts[args.1].constraints.insert(key);
|
);
|
||||||
});
|
arg_constraints.0.update(|csts| csts.insert(key));
|
||||||
|
arg_constraints.1.update(|csts| csts.insert(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- realization ---
|
// --- realization ---
|
||||||
@ -133,7 +151,7 @@ impl Assembly {
|
|||||||
for (_, elt) in elts {
|
for (_, elt) in elts {
|
||||||
let index = elt.index;
|
let index = elt.index;
|
||||||
gram_to_be.push_sym(index, index, 1.0);
|
gram_to_be.push_sym(index, index, 1.0);
|
||||||
guess_to_be.set_column(index, &elt.rep);
|
guess_to_be.set_column(index, &elt.rep.get_clone_untracked());
|
||||||
}
|
}
|
||||||
|
|
||||||
(gram_to_be, guess_to_be)
|
(gram_to_be, guess_to_be)
|
||||||
@ -175,11 +193,11 @@ impl Assembly {
|
|||||||
|
|
||||||
if success {
|
if success {
|
||||||
// read out the solution
|
// read out the solution
|
||||||
self.elements.update(|elts| {
|
for (_, elt) in self.elements.get_clone_untracked() {
|
||||||
for (_, elt) in elts.iter_mut() {
|
elt.rep.update(
|
||||||
elt.rep.set_column(0, &config.column(elt.index));
|
|rep| rep.set_column(0, &config.column(elt.index))
|
||||||
}
|
);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -103,7 +103,11 @@ pub fn Display() -> View {
|
|||||||
// change listener
|
// change listener
|
||||||
let scene_changed = create_signal(true);
|
let scene_changed = create_signal(true);
|
||||||
create_effect(move || {
|
create_effect(move || {
|
||||||
state.assembly.elements.track();
|
state.assembly.elements.with(|elts| {
|
||||||
|
for (_, elt) in elts {
|
||||||
|
elt.rep.track();
|
||||||
|
}
|
||||||
|
});
|
||||||
state.selection.track();
|
state.selection.track();
|
||||||
scene_changed.set(true);
|
scene_changed.set(true);
|
||||||
});
|
});
|
||||||
@ -295,23 +299,40 @@ pub fn Display() -> View {
|
|||||||
let assembly_to_world = &location * &orientation;
|
let assembly_to_world = &location * &orientation;
|
||||||
|
|
||||||
// get the assembly
|
// get the assembly
|
||||||
let elements = state.assembly.elements.get_clone();
|
let (
|
||||||
let element_iter = (&elements).into_iter();
|
elt_cnt,
|
||||||
let reps_world: Vec<_> = element_iter.clone().map(|(_, elt)| &assembly_to_world * &elt.rep).collect();
|
reps_world,
|
||||||
let colors: Vec<_> = element_iter.clone().map(|(key, elt)|
|
colors,
|
||||||
if state.selection.with(|sel| sel.contains(&key)) {
|
highlights
|
||||||
elt.color.map(|ch| 0.2 + 0.8*ch)
|
) = state.assembly.elements.with(|elts| {
|
||||||
} else {
|
(
|
||||||
elt.color
|
// number of elements
|
||||||
}
|
elts.len() as i32,
|
||||||
).collect();
|
|
||||||
let highlights: Vec<_> = element_iter.map(|(key, _)|
|
// representation vectors in world coordinates
|
||||||
if state.selection.with(|sel| sel.contains(&key)) {
|
elts.iter().map(
|
||||||
1.0_f32
|
|(_, elt)| elt.rep.with(|rep| &assembly_to_world * rep)
|
||||||
} else {
|
).collect::<Vec<_>>(),
|
||||||
HIGHLIGHT
|
|
||||||
}
|
// colors
|
||||||
).collect();
|
elts.iter().map(|(key, elt)| {
|
||||||
|
if state.selection.with(|sel| sel.contains(&key)) {
|
||||||
|
elt.color.map(|ch| 0.2 + 0.8*ch)
|
||||||
|
} else {
|
||||||
|
elt.color
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>(),
|
||||||
|
|
||||||
|
// highlight levels
|
||||||
|
elts.iter().map(|(key, _)| {
|
||||||
|
if state.selection.with(|sel| sel.contains(&key)) {
|
||||||
|
1.0_f32
|
||||||
|
} else {
|
||||||
|
HIGHLIGHT
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>()
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
// set the resolution
|
// set the resolution
|
||||||
let width = canvas.width() as f32;
|
let width = canvas.width() as f32;
|
||||||
@ -320,7 +341,7 @@ pub fn Display() -> View {
|
|||||||
ctx.uniform1f(shortdim_loc.as_ref(), width.min(height));
|
ctx.uniform1f(shortdim_loc.as_ref(), width.min(height));
|
||||||
|
|
||||||
// pass the assembly
|
// pass the assembly
|
||||||
ctx.uniform1i(sphere_cnt_loc.as_ref(), elements.len() as i32);
|
ctx.uniform1i(sphere_cnt_loc.as_ref(), elt_cnt);
|
||||||
for n in 0..reps_world.len() {
|
for n in 0..reps_world.len() {
|
||||||
let v = &reps_world[n];
|
let v = &reps_world[n];
|
||||||
ctx.uniform3f(
|
ctx.uniform3f(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use sycamore::{prelude::*, web::tags::div};
|
use sycamore::prelude::*;
|
||||||
use web_sys::{
|
use web_sys::{
|
||||||
Event,
|
Event,
|
||||||
HtmlInputElement,
|
HtmlInputElement,
|
||||||
@ -43,13 +43,9 @@ fn ConstraintOutlineItem(constraint_key: usize, element_key: usize) -> View {
|
|||||||
constraint.args.0
|
constraint.args.0
|
||||||
};
|
};
|
||||||
let other_arg_label = assembly.elements.with(|elts| elts[other_arg].label.clone());
|
let other_arg_label = assembly.elements.with(|elts| elts[other_arg].label.clone());
|
||||||
let class = create_memo(move || {
|
let class = constraint.rep_valid.map(
|
||||||
if constraint.rep_valid.get() {
|
|&rep_valid| if rep_valid { "cst" } else { "cst invalid" }
|
||||||
"cst"
|
);
|
||||||
} else {
|
|
||||||
"cst invalid"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
view! {
|
view! {
|
||||||
li(class=class.get()) {
|
li(class=class.get()) {
|
||||||
input(r#type="checkbox", bind:checked=constraint.active)
|
input(r#type="checkbox", bind:checked=constraint.active)
|
||||||
@ -64,19 +60,19 @@ fn ConstraintOutlineItem(constraint_key: usize, element_key: usize) -> View {
|
|||||||
#[component(inline_props)]
|
#[component(inline_props)]
|
||||||
fn ElementOutlineItem(key: usize, element: assembly::Element) -> View {
|
fn ElementOutlineItem(key: usize, element: assembly::Element) -> View {
|
||||||
let state = use_context::<AppState>();
|
let state = use_context::<AppState>();
|
||||||
let class = create_memo(move || {
|
let class = state.selection.map(
|
||||||
if state.selection.with(|sel| sel.contains(&key)) {
|
move |sel| if sel.contains(&key) { "selected" } else { "" }
|
||||||
"selected"
|
);
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let label = element.label.clone();
|
let label = element.label.clone();
|
||||||
let rep_components = element.rep.iter().map(|u| {
|
let rep_components = element.rep.map(
|
||||||
let u_coord = format!("{:.3}", u).replace("-", "\u{2212}");
|
|rep| rep.iter().map(
|
||||||
View::from(div().children(u_coord))
|
|u| format!("{:.3}", u).replace("-", "\u{2212}")
|
||||||
}).collect::<Vec<_>>();
|
).collect()
|
||||||
let constrained = element.constraints.len() > 0;
|
);
|
||||||
|
let constrained = element.constraints.map(|csts| csts.len() > 0);
|
||||||
|
let constraint_list = element.constraints.map(
|
||||||
|
|csts| csts.clone().into_iter().collect()
|
||||||
|
);
|
||||||
let details_node = create_node_ref();
|
let details_node = create_node_ref();
|
||||||
view! {
|
view! {
|
||||||
li {
|
li {
|
||||||
@ -101,7 +97,7 @@ fn ElementOutlineItem(key: usize, element: assembly::Element) -> View {
|
|||||||
}
|
}
|
||||||
event.prevent_default();
|
event.prevent_default();
|
||||||
},
|
},
|
||||||
"ArrowRight" if constrained => {
|
"ArrowRight" if constrained.get() => {
|
||||||
let _ = details_node
|
let _ = details_node
|
||||||
.get()
|
.get()
|
||||||
.unchecked_into::<web_sys::Element>()
|
.unchecked_into::<web_sys::Element>()
|
||||||
@ -144,13 +140,20 @@ fn ElementOutlineItem(key: usize, element: assembly::Element) -> View {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
div(class="elt-label") { (label) }
|
div(class="elt-label") { (label) }
|
||||||
div(class="elt-rep") { (rep_components) }
|
div(class="elt-rep") {
|
||||||
|
Indexed(
|
||||||
|
list=rep_components,
|
||||||
|
view=|coord_str| view! {
|
||||||
|
div { (coord_str) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
div(class="status")
|
div(class="status")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul(class="constraints") {
|
ul(class="constraints") {
|
||||||
Keyed(
|
Keyed(
|
||||||
list=element.constraints.into_iter().collect::<Vec<_>>(),
|
list=constraint_list,
|
||||||
view=move |cst_key| view! {
|
view=move |cst_key| view! {
|
||||||
ConstraintOutlineItem(
|
ConstraintOutlineItem(
|
||||||
constraint_key=cst_key,
|
constraint_key=cst_key,
|
||||||
@ -173,15 +176,16 @@ fn ElementOutlineItem(key: usize, element: assembly::Element) -> View {
|
|||||||
//
|
//
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Outline() -> View {
|
pub fn Outline() -> View {
|
||||||
// sort the elements alphabetically by ID
|
let state = use_context::<AppState>();
|
||||||
let elements_sorted = create_memo(|| {
|
|
||||||
let state = use_context::<AppState>();
|
// list the elements alphabetically by ID
|
||||||
state.assembly.elements
|
let element_list = state.assembly.elements.map(
|
||||||
.get_clone()
|
|elts| elts
|
||||||
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.sorted_by_key(|(_, elt)| elt.id.clone())
|
.sorted_by_key(|(_, elt)| elt.id.clone())
|
||||||
.collect()
|
.collect()
|
||||||
});
|
);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
ul(
|
ul(
|
||||||
@ -192,16 +196,11 @@ pub fn Outline() -> View {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Keyed(
|
Keyed(
|
||||||
list=elements_sorted,
|
list=element_list,
|
||||||
view=|(key, elt)| view! {
|
view=|(key, elt)| view! {
|
||||||
ElementOutlineItem(key=key, element=elt)
|
ElementOutlineItem(key=key, element=elt)
|
||||||
},
|
},
|
||||||
key=|(key, elt)| (
|
key=|(key, _)| key.clone()
|
||||||
key.clone(),
|
|
||||||
elt.id.clone(),
|
|
||||||
elt.label.clone(),
|
|
||||||
elt.constraints.clone()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user