Integrate engine into application prototype #15

Merged
glen merged 24 commits from engine-integration into main 2024-11-12 00:46:16 +00:00
5 changed files with 49 additions and 13 deletions
Showing only changes of commit e0880d2ad2 - Show all commits

View File

@ -26,6 +26,7 @@ console_error_panic_hook = { version = "0.1.7", optional = true }
version = "0.3.69" version = "0.3.69"
features = [ features = [
'HtmlCanvasElement', 'HtmlCanvasElement',
'HtmlInputElement',
'Performance', 'Performance',
'WebGl2RenderingContext', 'WebGl2RenderingContext',
'WebGlBuffer', 'WebGlBuffer',

View File

@ -93,7 +93,7 @@ details[open]:has(li) .elt-switch::after {
display: flex; display: flex;
} }
.elt-rep > div, .cst-rep { .elt-rep > div {
padding: 2px 0px 0px 0px; padding: 2px 0px 0px 0px;
font-size: 10pt; font-size: 10pt;
text-align: center; text-align: center;
@ -104,10 +104,17 @@ details[open]:has(li) .elt-switch::after {
font-style: italic; font-style: italic;
} }
.cst > input { .cst > input[type=checkbox] {
margin: 0px 8px 0px 0px; margin: 0px 8px 0px 0px;
} }
.cst > input[type=number] {
color: #fcfcfc;
background-color: inherit;
border: 1px solid #555;
border-radius: 2px;
}
/* display */ /* display */
canvas { canvas {

View File

@ -214,11 +214,14 @@ pub fn AddRemove() -> View {
(arg_vec[0].clone(), arg_vec[1].clone()) (arg_vec[0].clone(), arg_vec[1].clone())
} }
); );
let rep = create_signal(0.0);
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: 0.0, rep: rep,
active: active rep_text: create_signal(String::new()),
rep_valid: create_signal(false),
active: active,
}); });
state.assembly.realize(); state.assembly.realize();
state.selection.update(|sel| sel.clear()); state.selection.update(|sel| sel.clear());
@ -233,13 +236,19 @@ pub fn AddRemove() -> View {
&JsValue::from(cst.args.0), &JsValue::from(cst.args.0),
&JsValue::from(cst.args.1), &JsValue::from(cst.args.1),
&JsValue::from(":"), &JsValue::from(":"),
&JsValue::from(cst.rep) &JsValue::from(cst.rep.get_untracked())
); );
} }
}); });
// make constraint activation trigger a realization update // update the realization when the constraint activated, or
// edited while active
create_effect(move || { create_effect(move || {
rep.track();
console::log_2(
&JsValue::from("Constraint rep updated to"),
&JsValue::from(rep.get_untracked())
);
if active.get() { if active.get() {
state.assembly.realize(); state.assembly.realize();
} }

View File

@ -22,7 +22,9 @@ pub struct Element {
#[derive(Clone)] #[derive(Clone)]
pub struct Constraint { pub struct Constraint {
pub args: (usize, usize), pub args: (usize, usize),
pub rep: f64, pub rep: Signal<f64>,
pub rep_text: Signal<String>,
pub rep_valid: Signal<bool>,
pub active: Signal<bool> pub active: Signal<bool>
} }
@ -116,11 +118,11 @@ impl Assembly {
let mut gram_to_be = PartialMatrix::new(); let mut gram_to_be = PartialMatrix::new();
self.constraints.with_untracked(|csts| { self.constraints.with_untracked(|csts| {
for (_, cst) in csts { for (_, cst) in csts {
if cst.active.get_untracked() { if cst.active.get_untracked() && cst.rep_valid.get_untracked() {
let args = cst.args; let args = cst.args;
let row = elts[args.0].index; let row = elts[args.0].index;
let col = elts[args.1].index; let col = elts[args.1].index;
gram_to_be.push_sym(row, col, cst.rep); gram_to_be.push_sym(row, col, cst.rep.get_untracked());
} }
} }
}); });

View File

@ -1,6 +1,7 @@
use itertools::Itertools; use itertools::Itertools;
glen marked this conversation as resolved
Review

Definitely at some point we are going to need to separate the src directory into parts for the Assembly/Engine and for each of the views, but fine if you don't think that's warranted yet. On the other hand, if you just want to set up a reasonable hierarchy now and see how it works, that's fine too.

Definitely at some point we are going to need to separate the src directory into parts for the Assembly/Engine and for each of the views, but fine if you don't think that's warranted yet. On the other hand, if you just want to set up a reasonable hierarchy now and see how it works, that's fine too.
Review

Definitely at some point we are going to need to separate the src directory into parts for the Assembly/Engine [...]

Yeah, I think we'll probably want separate modules for "front of house" and "back of house" code at some point. Right now it does seem like the engine and assembly modules should go together in the "back of house" module, but I could imagine that changing, since the assembly structure is pretty tailored to the needs of the user interface.

[...] and for each of the views

Note that the Display and Outline views each have their own module already: that's why the expressions mod display; and mod outline; appear at the top of main.rs.

> Definitely at some point we are going to need to separate the src directory into parts for the Assembly/Engine [...] Yeah, I think we'll probably want separate modules for "front of house" and "back of house" code at some point. Right now it does seem like the `engine` and `assembly` modules should go together in the "back of house" module, but I could imagine that changing, since the assembly structure is pretty tailored to the needs of the user interface. > [...] and for each of the views Note that the `Display` and `Outline` views each have their own module already: that's why the expressions `mod display;` and `mod outline;` appear at the top of `main.rs`.
Review

I was commenting on the fact that outline is in the same directory as assembly and engine. I guess the module structure may not be immediately clear to the untrained eye; but directory structure is.

Also be cautious about the notion that "assembly is tailored to needs of UI". The driver for what goes in Assembly is the facts of the platonic universe we are observing. So color and label are OK because the sphere labeled George is red in the platonic universe. But unless "hidden" means that an entity must be hidden in all possible views -- and I doubt it should -- that should not be part of Assembly. (That's just an example, I know there is not a "hidden" property yet.)

I was commenting on the fact that outline is in the same directory as assembly and engine. I guess the module structure may not be immediately clear to the untrained eye; but directory structure is. Also be cautious about the notion that "assembly is tailored to needs of UI". The driver for what goes in Assembly is the facts of the platonic universe we are observing. So color and label are OK because the sphere labeled George is red in the platonic universe. But unless "hidden" means that an entity must be hidden in all possible views -- and I doubt it should -- that should not be part of Assembly. (That's just an example, I know there is not a "hidden" property yet.)
use sycamore::{prelude::*, web::tags::div}; use sycamore::{prelude::*, web::tags::div};
use web_sys::{Element, KeyboardEvent, MouseEvent, wasm_bindgen::JsCast}; use web_sys::{Element, Event, HtmlInputElement, KeyboardEvent, MouseEvent, wasm_bindgen::JsCast};
use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */
use crate::AppState; use crate::AppState;
@ -51,8 +52,6 @@ pub fn Outline() -> View {
let constrained = elt.constraints.len() > 0; let constrained = elt.constraints.len() > 0;
let details_node = create_node_ref(); let details_node = create_node_ref();
view! { view! {
/* [TO DO] switch to integer-valued parameters whenever
that becomes possible again */
li { li {
details(ref=details_node) { details(ref=details_node) {
summary( summary(
@ -138,7 +137,25 @@ pub fn Outline() -> View {
li(class="cst") { li(class="cst") {
input(r#type="checkbox", bind:checked=cst.active) input(r#type="checkbox", bind:checked=cst.active)
div(class="cst-label") { (other_arg_label) } div(class="cst-label") { (other_arg_label) }
div(class="cst-rep") { (cst.rep) } input(
r#type="number",
step="0.01",
bind:value=cst.rep_text,
on:change=move |event: Event| {
let target: HtmlInputElement = event.target().unwrap().unchecked_into();
let rep_valid = target.check_validity() && !target.value().is_empty();
batch(|| {
cst.rep_valid.set(rep_valid);
if rep_valid {
console::log_2(
&JsValue::from("Constraint rep parsed to"),
&JsValue::from(target.value_as_number())
);
cst.rep.set(target.value_as_number());
}
});
}
)
} }
} }
}, },