Integrate engine into application prototype #15
@ -26,6 +26,7 @@ console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
version = "0.3.69"
|
||||
features = [
|
||||
'HtmlCanvasElement',
|
||||
'HtmlInputElement',
|
||||
'Performance',
|
||||
'WebGl2RenderingContext',
|
||||
'WebGlBuffer',
|
||||
|
@ -93,7 +93,7 @@ details[open]:has(li) .elt-switch::after {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.elt-rep > div, .cst-rep {
|
||||
.elt-rep > div {
|
||||
padding: 2px 0px 0px 0px;
|
||||
font-size: 10pt;
|
||||
text-align: center;
|
||||
@ -104,10 +104,17 @@ details[open]:has(li) .elt-switch::after {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.cst > input {
|
||||
.cst > input[type=checkbox] {
|
||||
margin: 0px 8px 0px 0px;
|
||||
}
|
||||
|
||||
.cst > input[type=number] {
|
||||
color: #fcfcfc;
|
||||
background-color: inherit;
|
||||
border: 1px solid #555;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* display */
|
||||
|
||||
canvas {
|
||||
|
@ -214,11 +214,14 @@ pub fn AddRemove() -> View {
|
||||
(arg_vec[0].clone(), arg_vec[1].clone())
|
||||
}
|
||||
);
|
||||
let rep = create_signal(0.0);
|
||||
let active = create_signal(true);
|
||||
state.assembly.insert_constraint(Constraint {
|
||||
args: args,
|
||||
rep: 0.0,
|
||||
active: active
|
||||
rep: rep,
|
||||
rep_text: create_signal(String::new()),
|
||||
rep_valid: create_signal(false),
|
||||
active: active,
|
||||
});
|
||||
state.assembly.realize();
|
||||
state.selection.update(|sel| sel.clear());
|
||||
@ -233,13 +236,19 @@ pub fn AddRemove() -> View {
|
||||
&JsValue::from(cst.args.0),
|
||||
&JsValue::from(cst.args.1),
|
||||
&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 || {
|
||||
rep.track();
|
||||
console::log_2(
|
||||
&JsValue::from("Constraint rep updated to"),
|
||||
&JsValue::from(rep.get_untracked())
|
||||
);
|
||||
if active.get() {
|
||||
state.assembly.realize();
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ pub struct Element {
|
||||
#[derive(Clone)]
|
||||
pub struct Constraint {
|
||||
pub args: (usize, usize),
|
||||
glen marked this conversation as resolved
Outdated
|
||||
pub rep: f64,
|
||||
pub rep: Signal<f64>,
|
||||
glen marked this conversation as resolved
Outdated
glen
commented
Let's get into a habit of using full words in interfaces/public property names. Looking at this, I don't know if "rep" is a representation, the number of repetitions, something that is being reported, or what... Please rename this suite of properties. Thanks! Let's get into a habit of using full words in interfaces/public property names. Looking at this, I don't know if "rep" is a representation, the number of repetitions, something that is being reported, or what... Please rename this suite of properties. Thanks!
Vectornaut
commented
I've replaced I've replaced `rep` with `lorentz_prod` in all the `Constraint` field names (commit 5839882). We can streamline the names later if they get too unwieldy.
|
||||
pub rep_text: Signal<String>,
|
||||
pub rep_valid: Signal<bool>,
|
||||
pub active: Signal<bool>
|
||||
}
|
||||
|
||||
@ -116,11 +118,11 @@ impl Assembly {
|
||||
let mut gram_to_be = PartialMatrix::new();
|
||||
self.constraints.with_untracked(|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 row = elts[args.0].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());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
use itertools::Itertools;
|
||||
glen marked this conversation as resolved
glen
commented
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.
Vectornaut
commented
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
Note that the > 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`.
glen
commented
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 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;
|
||||
|
||||
@ -51,8 +52,6 @@ pub fn Outline() -> View {
|
||||
let constrained = elt.constraints.len() > 0;
|
||||
let details_node = create_node_ref();
|
||||
view! {
|
||||
/* [TO DO] switch to integer-valued parameters whenever
|
||||
that becomes possible again */
|
||||
li {
|
||||
details(ref=details_node) {
|
||||
summary(
|
||||
@ -138,7 +137,25 @@ pub fn Outline() -> View {
|
||||
li(class="cst") {
|
||||
input(r#type="checkbox", bind:checked=cst.active)
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
constrains
would work for me, as wouldappliesTo
. Totally open to other choices.usize
s are some sort of references to elements. If a primitive type is being used with semantic baggage, typedef it or something like that so that you can write e.g.,pub constrains: (ElementHandle, ElementHandle)
Again, I am open to other options for the name to use; "ElementRef" would be fine, or you may have another idea. A big part of why to do this is to make development easier should it become convenient to use a different primitive type to encode a reference to an element.
I've switched to
subjects
(in commited1890b
), as in the phrase "[...] subject to the constraint that [...]." Is that a fitting name? I like to name non-boolean variables with nouns, rather than prepositional verbs like "applies to."Right now, there's only one kind of element (a sphere) and one kind of constraint (fixing the generalized angle between two spheres), so the
Element
andConstraint
structures are written pretty narrowly. As we extend dyna3 to more general problems, I'm planning to generalizeElement
andConstraint
as needed—maybe by turning each of them into a trait implemented by a bunch of different structures.Done as soon as I update the PR (in commit
ced001b
). I've chosenElementKey
andConstraintKey
, since the Rust collections I've seen tend to use the language of keys and values.