diff --git a/studio-frontend/src/dioxus-machine.ts b/studio-frontend/src/dioxus-machine.ts index ac4a25c..633c005 100644 --- a/studio-frontend/src/dioxus-machine.ts +++ b/studio-frontend/src/dioxus-machine.ts @@ -148,7 +148,12 @@ function create_float_input(element : HTMLInputElement) { const onMouseMove = (e: MouseEvent) => { if (isMouseDown) { const dx = e.clientX - startX; - element.value = (value + dx / 10).toString(); // Изменение на 1 за каждые 5 пикселей движения мыши + startX = e.clientX; + var float_value = parseFloat(element.value); + if (float_value == null) { + return; + } + element.value = (float_value + dx / 10.0).toString(); // Изменение на 1 за каждые 5 пикселей движения мыши //dispatch update event const event = new Event('input', { bubbles: true, @@ -164,11 +169,11 @@ function create_float_input(element : HTMLInputElement) { document.removeEventListener('mouseup', onMouseUp); }; - element.addEventListener('keydown', (e: KeyboardEvent) => { - if (!e.key.match(/^[0-9]$/)) { - e.preventDefault(); // Предотвратить ввод нечисловых символов - } - }); + // element.addEventListener('keydown', (e: KeyboardEvent) => { + // if (!e.key.match(/^[0-9]$/)) { + // e.preventDefault(); // Предотвратить ввод нечисловых символов + // } + // }); }; function append_style(parent : HTMLElement) { @@ -205,11 +210,13 @@ function append_style(parent : HTMLElement) { .struct-grid { display: grid; grid-template-columns: min-content 1fr; - gap: 8px; + column-gap: 8px; + row-gap: 4px; align-items: center; } `; + parent.appendChild(style); } \ No newline at end of file diff --git a/studio/src/ui/utils.rs b/studio/src/ui/utils.rs index 75459af..b2ab0af 100644 --- a/studio/src/ui/utils.rs +++ b/studio/src/ui/utils.rs @@ -165,19 +165,33 @@ impl WebEventExecutor for ReflectValueExecutor { if let Some(v) = refl_value.downcast_mut::() { *v = value; } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } else if let Some(v) = refl_value.downcast_mut::() { - *v = value.parse().unwrap(); + if let Ok(value) = value.parse::() { + *v = value; + } } } } @@ -206,12 +220,28 @@ impl EntityChangeExecutor { } } +fn euler_to_degrees(euler : (f32, f32, f32)) -> (f32, f32, f32) { + ( + euler.0.to_degrees(), + euler.1.to_degrees(), + euler.2.to_degrees() + ) +} + +fn degrees_to_euler(degrees : (f32, f32, f32)) -> (f32, f32, f32) { + ( + degrees.0.to_radians(), + degrees.1.to_radians(), + degrees.2.to_radians() + ) +} + fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option { if let Some(name) = r.downcast_ref::() { Some(Element::Component(Component { tag: "div".to_string(), attributes: vec![ - ("style".to_string(), "font-weight: bold".to_string()), + ("style".to_string(), "font-weight: bold; font-size: 24px".to_string()), ], children: vec![ Element::Text(format!("{}", &name)), @@ -237,6 +267,7 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option() { let euler = quat.to_euler(EulerRot::XYZ); + let degrees = euler_to_degrees(euler); Some(Element::Component(Component { tag: "div".to_string(), attributes: vec![ @@ -248,16 +279,23 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option().ok() else { return; }; + let value = value.to_radians(); let mut e = world.get_entity_mut(entity).unwrap(); + let mut transform = e.get_mut::().unwrap(); + if transform.is_changed() { + return; + } let euler = transform.rotation.to_euler(EulerRot::XYZ); - transform.rotation = Quat::from_euler(EulerRot::XYZ, value.parse().unwrap(), euler.1, euler.2); + transform.rotation = Quat::from_euler(EulerRot::XYZ, value, euler.1, euler.2); } )) }), @@ -266,20 +304,48 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option().ok() else { return; }; + let mut e = world.get_entity_mut(entity).unwrap(); + let mut transform = e.get_mut::().unwrap(); + if transform.is_changed() { + return; + } + let value = value.to_radians(); + let euler = transform.rotation.to_euler(EulerRot::XYZ); + transform.rotation = transform.rotation * Quat::from_axis_angle(Vec3::Y, value - euler.1); + } + )) }), Element::Text("Z: ".to_string()), Element::Component(Component { - tag: "input".to_string(), + tag: "input".to_string(), attributes: vec![ ("type".to_string(), "number".to_string()), - ("value".to_string(), euler.2.to_string()), + ("value".to_string(), format!("{:.2}",degrees.2)), + ("step".to_string(), "0.01".to_string()), ], children: vec![], - onchange: None + onchange: Some(EntityChangeExecutor::new_boxed( + onchange.entity_id, + |world : &mut World, entity, value : String| { + let Some(value) = value.parse::().ok() else { return; }; + let value = value.to_radians(); + let mut e = world.get_entity_mut(entity).unwrap(); + let mut transform = e.get_mut::().unwrap(); + if transform.is_changed() { + return; + } + let euler = transform.rotation.to_euler(EulerRot::XYZ); + transform.rotation = Quat::from_euler(EulerRot::XYZ, euler.0, euler.1, value); + } + )) }) ], onchange: None @@ -297,7 +363,8 @@ fn check_predefined(r : &dyn Reflect, onchange : ReflectChange) -> Option Option Option