use sycamore::prelude::*; use web_sys::{console, wasm_bindgen::JsValue}; use crate::{engine, AppState, assembly::{Assembly, Constraint, Element}}; /* DEBUG */ // load an example assembly for testing. this code will be removed once we've // built a more formal test assembly system fn load_gen_assemb(assembly: &Assembly) { let _ = assembly.try_insert_element( Element::new( String::from("gemini_a"), String::from("Castor"), [1.00_f32, 0.25_f32, 0.00_f32], engine::sphere(0.5, 0.5, 0.0, 1.0) ) ); let _ = assembly.try_insert_element( Element::new( String::from("gemini_b"), String::from("Pollux"), [0.00_f32, 0.25_f32, 1.00_f32], engine::sphere(-0.5, -0.5, 0.0, 1.0) ) ); let _ = assembly.try_insert_element( Element::new( String::from("ursa_major"), String::from("Ursa major"), [0.25_f32, 0.00_f32, 1.00_f32], engine::sphere(-0.5, 0.5, 0.0, 0.75) ) ); let _ = assembly.try_insert_element( Element::new( String::from("ursa_minor"), String::from("Ursa minor"), [0.25_f32, 1.00_f32, 0.00_f32], engine::sphere(0.5, -0.5, 0.0, 0.5) ) ); let _ = assembly.try_insert_element( Element::new( String::from("moon_deimos"), String::from("Deimos"), [0.75_f32, 0.75_f32, 0.00_f32], engine::sphere(0.0, 0.15, 1.0, 0.25) ) ); let _ = assembly.try_insert_element( Element::new( String::from("moon_phobos"), String::from("Phobos"), [0.00_f32, 0.75_f32, 0.50_f32], engine::sphere(0.0, -0.15, -1.0, 0.25) ) ); } /* DEBUG */ // load an example assembly for testing. this code will be removed once we've // built a more formal test assembly system fn load_low_curv_assemb(assembly: &Assembly) { let a = 0.75_f64.sqrt(); let _ = assembly.try_insert_element( Element::new( "central".to_string(), "Central".to_string(), [0.75_f32, 0.75_f32, 0.75_f32], engine::sphere(0.0, 0.0, 0.0, 1.0) ) ); let _ = assembly.try_insert_element( Element::new( "assemb_plane".to_string(), "Assembly plane".to_string(), [0.75_f32, 0.75_f32, 0.75_f32], engine::sphere_with_offset(0.0, 0.0, 1.0, 0.0, 0.0) ) ); let _ = assembly.try_insert_element( Element::new( "side1".to_string(), "Side 1".to_string(), [1.00_f32, 0.00_f32, 0.25_f32], engine::sphere_with_offset(1.0, 0.0, 0.0, 1.0, 0.0) ) ); let _ = assembly.try_insert_element( Element::new( "side2".to_string(), "Side 2".to_string(), [0.25_f32, 1.00_f32, 0.00_f32], engine::sphere_with_offset(-0.5, a, 0.0, 1.0, 0.0) ) ); let _ = assembly.try_insert_element( Element::new( "side3".to_string(), "Side 3".to_string(), [0.00_f32, 0.25_f32, 1.00_f32], engine::sphere_with_offset(-0.5, -a, 0.0, 1.0, 0.0) ) ); let _ = assembly.try_insert_element( Element::new( "corner1".to_string(), "Corner 1".to_string(), [0.75_f32, 0.75_f32, 0.75_f32], engine::sphere(-4.0/3.0, 0.0, 0.0, 1.0/3.0) ) ); let _ = assembly.try_insert_element( Element::new( "corner2".to_string(), "Corner 2".to_string(), [0.75_f32, 0.75_f32, 0.75_f32], engine::sphere(2.0/3.0, -4.0/3.0 * a, 0.0, 1.0/3.0) ) ); let _ = assembly.try_insert_element( Element::new( String::from("corner3"), String::from("Corner 3"), [0.75_f32, 0.75_f32, 0.75_f32], engine::sphere(2.0/3.0, 4.0/3.0 * a, 0.0, 1.0/3.0) ) ); } #[component] pub fn AddRemove() -> View { /* DEBUG */ let assembly_name = create_signal("general".to_string()); create_effect(move || { // get name of chosen assembly let name = assembly_name.get_clone(); console::log_1( &JsValue::from(format!("Showing assembly \"{}\"", name.clone())) ); batch(|| { let state = use_context::(); let assembly = &state.assembly; // clear state assembly.elements.update(|elts| elts.clear()); assembly.elements_by_id.update(|elts_by_id| elts_by_id.clear()); state.selection.update(|sel| sel.clear()); // load assembly match name.as_str() { "general" => load_gen_assemb(assembly), "low-curv" => load_low_curv_assemb(assembly), _ => () }; }); }); view! { div(id="add-remove") { button( on:click=|_| { let state = use_context::(); state.assembly.insert_new_element(); /* DEBUG */ // print updated list of elements by identifier console::log_1(&JsValue::from("elements by identifier:")); for (id, key) in state.assembly.elements_by_id.get_clone().iter() { console::log_3( &JsValue::from(" "), &JsValue::from(id), &JsValue::from(*key) ); } } ) { "+" } button( class="emoji", /* KLUDGE */ // for convenience, we're using an emoji as a temporary icon for this button disabled={ let state = use_context::(); state.selection.with(|sel| sel.len() != 2) }, on:click=|_| { let state = use_context::(); let subjects = state.selection.with( |sel| { let subject_vec: Vec<_> = sel.into_iter().collect(); (subject_vec[0].clone(), subject_vec[1].clone()) } ); let lorentz_prod = create_signal(0.0); let lorentz_prod_valid = create_signal(false); let active = create_signal(true); state.assembly.insert_constraint(Constraint { subjects: subjects, lorentz_prod: lorentz_prod, lorentz_prod_text: create_signal(String::new()), lorentz_prod_valid: lorentz_prod_valid, active: active, }); state.selection.update(|sel| sel.clear()); /* DEBUG */ // print updated constraint list console::log_1(&JsValue::from("Constraints:")); state.assembly.constraints.with(|csts| { for (_, cst) in csts.into_iter() { console::log_5( &JsValue::from(" "), &JsValue::from(cst.subjects.0), &JsValue::from(cst.subjects.1), &JsValue::from(":"), &JsValue::from(cst.lorentz_prod.get_untracked()) ); } }); // update the realization when the constraint becomes active // and valid, or is edited while active and valid create_effect(move || { console::log_1(&JsValue::from( format!("Constraint ({}, {}) updated", subjects.0, subjects.1) )); lorentz_prod.track(); if active.get() && lorentz_prod_valid.get() { state.assembly.realize(); } }); } ) { "🔗" } select(bind:value=assembly_name) { /* DEBUG */ // example assembly chooser option(value="general") { "General" } option(value="low-curv") { "Low-curvature" } option(value="empty") { "Empty" } } } } }