mirror of
https://github.com/enso-org/enso.git
synced 2024-12-19 14:12:20 +03:00
Cleaning the code, adding batched node position notifications to graph editor. (https://github.com/enso-org/ide/pull/508)
Original commit: 1b05c19aa8
This commit is contained in:
parent
48eeef9873
commit
4a07474ea2
@ -108,14 +108,14 @@ where Color<D> : HasComponents<ComponentsRepr=(f32,f32,f32,f32)> {
|
||||
}
|
||||
|
||||
impl<D> Into<Vector3<f32>> for &Color<D>
|
||||
where Color<D> : Copy + HasComponents<ComponentsRepr=(f32,f32,f32)> {
|
||||
where Color<D> : Copy + HasComponents<ComponentsRepr=(f32,f32,f32)> {
|
||||
fn into(self) -> Vector3<f32> {
|
||||
Into::<Vector3<f32>>::into((*self).into_components())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> Into<Vector4<f32>> for &Color<D>
|
||||
where Color<D> : Copy + HasComponents<ComponentsRepr=(f32,f32,f32,f32)> {
|
||||
where Color<D> : Copy + HasComponents<ComponentsRepr=(f32,f32,f32,f32)> {
|
||||
fn into(self) -> Vector4<f32> {
|
||||
Into::<Vector4<f32>>::into((*self).into_components())
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ macro_rules! define_vector {
|
||||
|
||||
/// Smart constructor.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn $name<T>($($field:T),*) -> $name<T> {
|
||||
pub const fn $name<T>($($field:T),*) -> $name<T> {
|
||||
$name {$($field),*}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,17 @@ use ensogl::gui::component;
|
||||
|
||||
|
||||
|
||||
// =================
|
||||
// === Constants ===
|
||||
// =================
|
||||
|
||||
const DEFAULT_SIZE : V2 = V2(16.0,16.0);
|
||||
const DEFAULT_RADIUS : f32 = 8.0;
|
||||
const DEFAULT_COLOR_LAB : V3 = V3(1.0,0.0,0.0);
|
||||
const DEFAULT_COLOR_ALPHA : f32 = 0.2;
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// === StyleValue ===
|
||||
// ==================
|
||||
@ -58,7 +69,7 @@ impl<T> StyleValue<T> {
|
||||
// === Style ===
|
||||
// =============
|
||||
|
||||
macro_rules! define_style {( $($field:ident : $field_type:ty),* $(,)? ) => {
|
||||
macro_rules! define_style {( $( $(#$meta:tt)* $field:ident : $field_type:ty),* $(,)? ) => {
|
||||
/// Set of cursor style parameters. You can construct this object in FRP network, merge it using
|
||||
/// its `Semigroup` instance, and finally pass to the cursor to apply the style. Please note
|
||||
/// that cursor does not implement any complex style management (like pushing or popping a style
|
||||
@ -66,7 +77,7 @@ macro_rules! define_style {( $($field:ident : $field_type:ty),* $(,)? ) => {
|
||||
/// it in FRP.
|
||||
#[derive(Debug,Clone,Default)]
|
||||
pub struct Style {
|
||||
$($field : $field_type),*
|
||||
$($(#$meta)? $field : Option<$field_type>),*
|
||||
}
|
||||
|
||||
impl PartialSemigroup<&Style> for Style {
|
||||
@ -84,12 +95,15 @@ macro_rules! define_style {( $($field:ident : $field_type:ty),* $(,)? ) => {
|
||||
};}
|
||||
|
||||
define_style! {
|
||||
host : Option<display::object::Instance>,
|
||||
size : Option<StyleValue<Vector2<f32>>>,
|
||||
offset : Option<StyleValue<Vector2<f32>>>,
|
||||
color : Option<StyleValue<color::Lcha>>,
|
||||
radius : Option<StyleValue<f32>>,
|
||||
press : Option<StyleValue<f32>>,
|
||||
/// Host defines an object which the cursor position is bound to. It is used to implement
|
||||
/// label selection. After setting the host to the label, cursor will not follow mouse anymore,
|
||||
/// it will inherit its position from the label instead.
|
||||
host : display::object::Instance,
|
||||
size : StyleValue<Vector2<f32>>,
|
||||
offset : StyleValue<Vector2<f32>>,
|
||||
color : StyleValue<color::Lcha>,
|
||||
radius : StyleValue<f32>,
|
||||
press : StyleValue<f32>,
|
||||
}
|
||||
|
||||
|
||||
@ -117,8 +131,9 @@ impl Style {
|
||||
}
|
||||
|
||||
pub fn new_box_selection(size:Vector2<f32>) -> Self {
|
||||
let def_size = Vector2::new(DEFAULT_SIZE.x,DEFAULT_SIZE.y);
|
||||
let offset = Some(StyleValue::new_no_animation(-size / 2.0));
|
||||
let size = Some(StyleValue::new_no_animation(size.abs() + Vector2::new(16.0,16.0)));
|
||||
let size = Some(StyleValue::new_no_animation(size.abs() + def_size));
|
||||
Self {size,offset,..default()}
|
||||
}
|
||||
|
||||
@ -166,7 +181,8 @@ pub mod shape {
|
||||
) {
|
||||
let width : Var<Distance<Pixels>> = "input_size.x".into();
|
||||
let height : Var<Distance<Pixels>> = "input_size.y".into();
|
||||
let press_diff = 2.px() * &press;
|
||||
let press_side_shrink = 2.px();
|
||||
let press_diff = press_side_shrink * &press;
|
||||
let radius = 1.px() * radius - &press_diff;
|
||||
let selection_width = 1.px() * &selection_size.x();
|
||||
let selection_height = 1.px() * &selection_size.y();
|
||||
@ -243,7 +259,7 @@ impl CursorModel {
|
||||
let logger = Logger::new("cursor");
|
||||
let frp = FrpInputs::new(network);
|
||||
let view = component::ShapeView::<shape::Shape>::new(&logger,&scene);
|
||||
let style = Rc::new(RefCell::new(Style::default()));
|
||||
let style = default();
|
||||
|
||||
let shape_system = scene.shapes.shape_system(PhantomData::<shape::Shape>);
|
||||
shape_system.shape_system.set_pointer_events(false);
|
||||
@ -279,16 +295,16 @@ impl Cursor {
|
||||
|
||||
// === Animations ===
|
||||
//
|
||||
// The following animators are used for smooth cursor transitions. There are two components
|
||||
// The following animators are used for smooth cursor transitions. There are two of them
|
||||
// with a non-obvious behavior, namely the `host_follow_weight` and `host_attached_weight`.
|
||||
// The mouse position can be in three stages:
|
||||
// The mouse position is driven by three factors:
|
||||
//
|
||||
// - Real-time cursor mode.
|
||||
// Cursor follows the system mouse position.
|
||||
//
|
||||
// - Host-follow mode.
|
||||
// Cursor follows the host using dynamic simulator. The `host_follow_weight` variable is
|
||||
// a weight between real-time mode and this one.
|
||||
// Cursor follows the host using dynamic inertia simulator. The `host_follow_weight`
|
||||
// variable is a weight between real-time mode and this one.
|
||||
//
|
||||
// - Host-attached mode.
|
||||
// Cursor follows the host without any delay. The `host_attached_weight` variable is a
|
||||
@ -307,17 +323,11 @@ impl Cursor {
|
||||
let host_follow_weight = Animation :: <f32> :: new(&network);
|
||||
let host_attached_weight = Tween :: new(&network);
|
||||
|
||||
let default_size = V2(16.0,16.0);
|
||||
let default_radius = 8.0;
|
||||
let default_lab = V3(1.0,0.0,0.0);
|
||||
let default_alpha = 0.2;
|
||||
|
||||
host_attached_weight.set_duration(300.0);
|
||||
color_lab.set_target_value(default_lab);
|
||||
color_alpha.set_target_value(default_alpha);
|
||||
radius.set_target_value(default_radius);
|
||||
size.set_target_value(default_size);
|
||||
|
||||
color_lab.set_target_value(DEFAULT_COLOR_LAB);
|
||||
color_alpha.set_target_value(DEFAULT_COLOR_ALPHA);
|
||||
radius.set_target_value(DEFAULT_RADIUS);
|
||||
size.set_target_value(DEFAULT_SIZE);
|
||||
|
||||
frp::extend! { network
|
||||
eval press.value ((v) model.view.shape.press.set(*v));
|
||||
@ -344,8 +354,8 @@ impl Cursor {
|
||||
|
||||
match &new_style.color {
|
||||
None => {
|
||||
color_lab.set_target_value(default_lab);
|
||||
color_alpha.set_target_value(default_alpha);
|
||||
color_lab.set_target_value(DEFAULT_COLOR_LAB);
|
||||
color_alpha.set_target_value(DEFAULT_COLOR_ALPHA);
|
||||
}
|
||||
Some(new_color) => {
|
||||
let lab = color::Laba::from(new_color.value);
|
||||
@ -359,7 +369,7 @@ impl Cursor {
|
||||
}
|
||||
|
||||
match &new_style.size {
|
||||
None => size.set_target_value(default_size),
|
||||
None => size.set_target_value(DEFAULT_SIZE),
|
||||
Some(new_size) => {
|
||||
size.set_target_value(V2::new(new_size.value.x,new_size.value.y));
|
||||
if !new_size.animate { size.skip() }
|
||||
@ -375,7 +385,7 @@ impl Cursor {
|
||||
}
|
||||
|
||||
match &new_style.radius {
|
||||
None => radius.set_target_value(default_radius),
|
||||
None => radius.set_target_value(DEFAULT_RADIUS),
|
||||
Some(new_radius) => {
|
||||
radius.set_target_value(new_radius.value);
|
||||
if !new_radius.animate { radius.skip() }
|
||||
|
@ -211,9 +211,6 @@ impl<K,V,S> SharedHashMap<K,V,S> {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#[derive(Debug,Clone,CloneRef)]
|
||||
pub struct Frp {
|
||||
pub inputs : FrpInputs,
|
||||
@ -483,6 +480,7 @@ generate_frp_outputs! {
|
||||
node_selected : NodeId,
|
||||
node_deselected : NodeId,
|
||||
node_position_set : (NodeId,Position),
|
||||
node_position_set_batched : (NodeId,Position),
|
||||
node_expression_set : (NodeId,node::Expression),
|
||||
|
||||
edge_added : EdgeId,
|
||||
@ -1042,6 +1040,14 @@ impl GraphEditorModel {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_position(&self, node_id:impl Into<NodeId>) -> Position {
|
||||
let node_id = node_id.into();
|
||||
self.nodes.get_cloned_ref(&node_id).map(|node| {
|
||||
let v_pos = node.position();
|
||||
frp::Position::new(v_pos.x, v_pos.y)
|
||||
}).unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn node_pos_mod
|
||||
(&self, node_id:impl Into<NodeId>, pos_diff:impl Into<Position>) -> (NodeId,Position) {
|
||||
let node_id = node_id.into();
|
||||
@ -1398,6 +1404,7 @@ fn new_graph_editor(world:&World) -> GraphEditor {
|
||||
|
||||
node_with_position <- add_node_at_cursor.map3(&new_node,&mouse.position,|_,id,pos| (*id,*pos));
|
||||
outputs.node_position_set <+ node_with_position;
|
||||
outputs.node_position_set_batched <+ node_with_position;
|
||||
|
||||
cursor_style <- all
|
||||
[ cursor_selection
|
||||
@ -1481,16 +1488,26 @@ fn new_graph_editor(world:&World) -> GraphEditor {
|
||||
node_drag <- mouse.translation.gate(&touch.nodes.is_down);
|
||||
was_selected <- touch.nodes.down.map(f!((id) model.nodes.selected.contains(id)));
|
||||
tx_sel_nodes <- any (node_drag, inputs.translate_selected_nodes);
|
||||
non_selected_drag <- tx_sel_nodes.map2(&touch.nodes.down,|_,id|*id).gate_not(&was_selected);
|
||||
selected_drag <= tx_sel_nodes.map(f_!(model.nodes.selected.keys())).gate(&was_selected);
|
||||
non_selected_drag <- tx_sel_nodes.map2(&touch.nodes.down,|_,id|vec![*id]).gate_not(&was_selected);
|
||||
selected_drag <- tx_sel_nodes.map(f_!(model.nodes.selected.keys())).gate(&was_selected);
|
||||
nodes_to_drag <- any (non_selected_drag, selected_drag);
|
||||
nodes_new_pos <- nodes_to_drag.map2(&tx_sel_nodes,f!((id,tx) model.node_pos_mod(id,tx)));
|
||||
outputs.node_position_set <+ nodes_new_pos;
|
||||
node_to_drag <= nodes_to_drag;
|
||||
node_new_pos <- node_to_drag.map2(&tx_sel_nodes,f!((id,tx) model.node_pos_mod(id,tx)));
|
||||
outputs.node_position_set <+ node_new_pos;
|
||||
|
||||
was_drag_false <- touch.nodes.down.constant(false);
|
||||
was_drag_true <- node_drag.constant(true);
|
||||
was_drag <- any (was_drag_false,was_drag_true);
|
||||
drag_finish <- touch.nodes.up.gate(&was_drag);
|
||||
dragged_node <= nodes_to_drag.sample(&drag_finish);
|
||||
dragged_node_pos <- dragged_node.map(f!([model] (id) (*id,model.node_position(id))));
|
||||
outputs.node_position_set_batched <+ dragged_node_pos;
|
||||
|
||||
|
||||
// === Set Node Position ===
|
||||
|
||||
outputs.node_position_set <+ inputs.set_node_position;
|
||||
outputs.node_position_set_batched <+ inputs.set_node_position;
|
||||
eval outputs.node_position_set (((id,pos)) model.set_node_position(id,pos));
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user