diff --git a/api/sixtyfps-node/native/lib.rs b/api/sixtyfps-node/native/lib.rs index 4952ab6ce..9feecdfc3 100644 --- a/api/sixtyfps-node/native/lib.rs +++ b/api/sixtyfps-node/native/lib.rs @@ -230,7 +230,7 @@ fn to_eval_value<'cx>( | Type::Callback { .. } | Type::Easing | Type::Component(_) - | Type::PathElements + | Type::PathData | Type::LayoutCache | Type::ElementReference => cx.throw_error("Cannot convert to a Sixtyfps property value"), } diff --git a/sixtyfps_compiler/builtin_macros.rs b/sixtyfps_compiler/builtin_macros.rs index bad57c24b..4cb246f61 100644 --- a/sixtyfps_compiler/builtin_macros.rs +++ b/sixtyfps_compiler/builtin_macros.rs @@ -182,7 +182,7 @@ fn to_debug_string( | Type::ElementReference | Type::LayoutCache | Type::Model - | Type::PathElements => { + | Type::PathData => { diag.push_error("Cannot debug this expression".into(), &node); Expression::Invalid } diff --git a/sixtyfps_compiler/expression_tree.rs b/sixtyfps_compiler/expression_tree.rs index e7f613d44..a5da5bacd 100644 --- a/sixtyfps_compiler/expression_tree.rs +++ b/sixtyfps_compiler/expression_tree.rs @@ -431,9 +431,7 @@ pub enum Expression { values: HashMap, }, - PathElements { - elements: Path, - }, + PathData(Path), EasingCurve(EasingCurve), @@ -585,7 +583,7 @@ impl Expression { Expression::UnaryOp { sub, .. } => sub.ty(), Expression::Array { element_ty, .. } => Type::Array(Box::new(element_ty.clone())), Expression::Struct { ty, .. } => ty.clone(), - Expression::PathElements { .. } => Type::PathElements, + Expression::PathData { .. } => Type::PathData, Expression::StoreLocalVariable { .. } => Type::Void, Expression::ReadLocalVariable { ty, .. } => ty.clone(), Expression::EasingCurve(_) => Type::Easing, @@ -653,8 +651,8 @@ impl Expression { visitor(x); } } - Expression::PathElements { elements } => { - if let Path::Elements(elements) = elements { + Expression::PathData(data) => { + if let Path::Elements(elements) = data { for element in elements { element.bindings.values().for_each(|binding| visitor(&binding.borrow())) } @@ -735,8 +733,8 @@ impl Expression { visitor(x); } } - Expression::PathElements { elements } => { - if let Path::Elements(elements) = elements { + Expression::PathData(data) => { + if let Path::Elements(elements) = data { for element in elements { element .bindings @@ -811,8 +809,8 @@ impl Expression { Expression::UnaryOp { sub, .. } => sub.is_constant(), Expression::Array { values, .. } => values.iter().all(Expression::is_constant), Expression::Struct { values, .. } => values.iter().all(|(_, v)| v.is_constant()), - Expression::PathElements { elements } => { - if let Path::Elements(elements) = elements { + Expression::PathData(data) => { + if let Path::Elements(elements) = data { elements .iter() .all(|element| element.bindings.values().all(|v| v.borrow().is_constant())) @@ -1024,7 +1022,7 @@ impl Expression { }, Type::Bool => Expression::BoolLiteral(false), Type::Model => Expression::Invalid, - Type::PathElements => Expression::PathElements { elements: Path::Elements(vec![]) }, + Type::PathData => Expression::PathData(Path::Elements(vec![])), Type::Array(element_ty) => { Expression::Array { element_ty: (**element_ty).clone(), values: vec![] } } @@ -1319,7 +1317,7 @@ pub fn pretty_print(f: &mut dyn std::fmt::Write, expression: &Expression) -> std } write!(f, " }}") } - Expression::PathElements { elements } => write!(f, "{:?}", elements), + Expression::PathData(data) => write!(f, "{:?}", data), Expression::EasingCurve(e) => write!(f, "{:?}", e), Expression::LinearGradient { angle, stops } => { write!(f, "@linear-gradient(")?; diff --git a/sixtyfps_compiler/generator/cpp.rs b/sixtyfps_compiler/generator/cpp.rs index a26d2107a..26bdbffeb 100644 --- a/sixtyfps_compiler/generator/cpp.rs +++ b/sixtyfps_compiler/generator/cpp.rs @@ -2297,7 +2297,7 @@ fn compile_expression( panic!("Expression::Object is not a Type::Object") } } - Expression::PathElements { elements } => compile_path(elements, component), + Expression::PathData(data) => compile_path(data, component), Expression::EasingCurve(EasingCurve::Linear) => "sixtyfps::cbindgen_private::EasingCurve()".into(), Expression::EasingCurve(EasingCurve::CubicBezier(a, b, c, d)) => format!( "sixtyfps::cbindgen_private::EasingCurve(sixtyfps::cbindgen_private::EasingCurve::Tag::CubicBezier, {}, {}, {}, {})", diff --git a/sixtyfps_compiler/generator/rust.rs b/sixtyfps_compiler/generator/rust.rs index fe5706809..4e77d6db5 100644 --- a/sixtyfps_compiler/generator/rust.rs +++ b/sixtyfps_compiler/generator/rust.rs @@ -1343,7 +1343,7 @@ impl<'a> llr::EvaluationContext for EvaluationContext<'a> { llr::PropertyReference::InNativeItem { sub_component_path, item_index, prop_name } => { if prop_name == "elements" { // The `Path::elements` property is not in the NativeClasss - return &Type::PathElements; + return &Type::PathData; } let mut sub_component = self.current_sub_component.unwrap(); @@ -1413,6 +1413,22 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream let id = struct_name_to_tokens(n); quote!({ let obj = #f; #id { #(#fields),*} }) } + (Type::Array(..), Type::PathData) + if matches!( + from.as_ref(), + Expression::Array { element_ty: Type::Struct { .. }, .. } + ) => + { + let path_elements = match from.as_ref() { + Expression::Array { element_ty: _, values, as_model: _ } => values + .iter() + .map(|path_elem_expr| compile_expression(path_elem_expr, ctx)), + _ => { + unreachable!() + } + }; + quote!(sixtyfps::re_exports::PathData::Elements(sixtyfps::re_exports::SharedVector::<_>::from_slice(&[#((#path_elements).into()),*]))) + } _ => f, } } diff --git a/sixtyfps_compiler/langtype.rs b/sixtyfps_compiler/langtype.rs index da767ec98..ecfd6333f 100644 --- a/sixtyfps_compiler/langtype.rs +++ b/sixtyfps_compiler/langtype.rs @@ -49,7 +49,7 @@ pub enum Type { Image, Bool, Model, - PathElements, + PathData, // Either a vector of path elements or a two vectors of events and coordinates Easing, Brush, /// This is usually a model @@ -103,7 +103,7 @@ impl core::cmp::PartialEq for Type { Type::Image => matches!(other, Type::Image), Type::Bool => matches!(other, Type::Bool), Type::Model => matches!(other, Type::Model), - Type::PathElements => matches!(other, Type::PathElements), + Type::PathData => matches!(other, Type::PathData), Type::Easing => matches!(other, Type::Easing), Type::Brush => matches!(other, Type::Brush), Type::Array(a) => matches!(other, Type::Array(b) if a == b), @@ -177,7 +177,7 @@ impl Display for Type { write!(f, "}}") } - Type::PathElements => write!(f, "pathelements"), + Type::PathData => write!(f, "pathdata"), Type::Easing => write!(f, "easing"), Type::Brush => write!(f, "brush"), Type::Enumeration(enumeration) => write!(f, "enum {}", enumeration.name), @@ -484,7 +484,7 @@ impl Type { Type::Image => None, Type::Bool => None, Type::Model => None, - Type::PathElements => None, + Type::PathData => None, Type::Easing => None, Type::Brush => None, Type::Array(_) => None, diff --git a/sixtyfps_compiler/llr/expression.rs b/sixtyfps_compiler/llr/expression.rs index 43cb278e8..c2c2cdb03 100644 --- a/sixtyfps_compiler/llr/expression.rs +++ b/sixtyfps_compiler/llr/expression.rs @@ -190,7 +190,7 @@ impl Expression { }, Type::Bool => Expression::BoolLiteral(false), Type::Model => return None, - Type::PathElements => Expression::PathEvents(Default::default()), + Type::PathData => Expression::PathEvents(Default::default()), Type::Array(element_ty) => Expression::Array { element_ty: (**element_ty).clone(), values: vec![], diff --git a/sixtyfps_compiler/llr/lower_expression.rs b/sixtyfps_compiler/llr/lower_expression.rs index 562e079aa..83b861bad 100644 --- a/sixtyfps_compiler/llr/lower_expression.rs +++ b/sixtyfps_compiler/llr/lower_expression.rs @@ -166,7 +166,7 @@ pub fn lower_expression( .map(|(s, e)| Some((s.clone(), lower_expression(e, ctx)?))) .collect::>()?, }), - tree_Expression::PathElements { elements } => compile_path(elements, ctx), + tree_Expression::PathData(data) => compile_path(data, ctx), tree_Expression::EasingCurve(x) => Some(llr_Expression::EasingCurve(x.clone())), tree_Expression::LinearGradient { angle, stops } => Some(llr_Expression::LinearGradient { angle: Box::new(lower_expression(angle, ctx)?), @@ -873,12 +873,16 @@ fn compile_path( .collect(); Some(llr_Expression::Cast { from: llr_Expression::Array { - element_ty: Type::PathElements, + element_ty: Type::Struct { + fields: Default::default(), + name: Some("PathElement".to_owned()), + node: None, + }, values: converted_elements, as_model: false, } .into(), - to: Type::PathElements, + to: Type::PathData, }) } crate::expression_tree::Path::Events(events) => { diff --git a/sixtyfps_compiler/passes/compile_paths.rs b/sixtyfps_compiler/passes/compile_paths.rs index 01d0d1a16..245da1b7b 100644 --- a/sixtyfps_compiler/passes/compile_paths.rs +++ b/sixtyfps_compiler/passes/compile_paths.rs @@ -115,9 +115,7 @@ pub fn compile_paths( crate::expression_tree::Path::Elements(path_data) }; - elem.bindings.insert( - "elements".into(), - RefCell::new(Expression::PathElements { elements: path_data }.into()), - ); + elem.bindings + .insert("elements".into(), RefCell::new(Expression::PathData(path_data).into())); }); } diff --git a/sixtyfps_compiler/passes/lower_layout.rs b/sixtyfps_compiler/passes/lower_layout.rs index f4cd2bb3b..95ac54ae1 100644 --- a/sixtyfps_compiler/passes/lower_layout.rs +++ b/sixtyfps_compiler/passes/lower_layout.rs @@ -596,9 +596,7 @@ fn lower_path_layout(layout_element: &ElementRc, diag: &mut BuildDiagnostics) { .remove("elements") .map(RefCell::into_inner) { - Some(BindingExpression { expression: Expression::PathElements { elements }, .. }) => { - elements - } + Some(BindingExpression { expression: Expression::PathData(data), .. }) => data, _ => { diag.push_error("Internal error: elements binding in PathLayout does not contain path elements expression".into(), &*layout_element.borrow()); return; diff --git a/sixtyfps_runtime/corelib/graphics/path.rs b/sixtyfps_runtime/corelib/graphics/path.rs index a42d19078..a682e881a 100644 --- a/sixtyfps_runtime/corelib/graphics/path.rs +++ b/sixtyfps_runtime/corelib/graphics/path.rs @@ -118,7 +118,7 @@ pub struct PathQuadraticTo { } #[repr(C)] -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, derive_more::From)] /// PathElement describes a single element on a path, such as move-to, line-to, etc. pub enum PathElement { /// The MoveTo variant sets the current position on the path. diff --git a/sixtyfps_runtime/interpreter/api.rs b/sixtyfps_runtime/interpreter/api.rs index 8f2930453..430881a4b 100644 --- a/sixtyfps_runtime/interpreter/api.rs +++ b/sixtyfps_runtime/interpreter/api.rs @@ -102,7 +102,7 @@ pub enum Value { Brush(Brush), #[doc(hidden)] /// The elements of a path - PathElements(PathData), + PathData(PathData), #[doc(hidden)] /// An easing curve EasingCurve(sixtyfps_corelib::animations::EasingCurve), @@ -150,7 +150,7 @@ impl PartialEq for Value { Value::Model(lhs) => matches!(other, Value::Model(rhs) if Rc::ptr_eq(lhs, rhs)), Value::Struct(lhs) => matches!(other, Value::Struct(rhs) if lhs == rhs), Value::Brush(lhs) => matches!(other, Value::Brush(rhs) if lhs == rhs), - Value::PathElements(lhs) => matches!(other, Value::PathElements(rhs) if lhs == rhs), + Value::PathData(lhs) => matches!(other, Value::PathData(rhs) if lhs == rhs), Value::EasingCurve(lhs) => matches!(other, Value::EasingCurve(rhs) if lhs == rhs), Value::EnumerationValue(lhs_name, lhs_value) => { matches!(other, Value::EnumerationValue(rhs_name, rhs_value) if lhs_name == rhs_name && lhs_value == rhs_value) @@ -172,7 +172,7 @@ impl std::fmt::Debug for Value { Value::Model(_) => write!(f, "Value::Model()"), Value::Struct(s) => write!(f, "Value::Struct({:?})", s), Value::Brush(b) => write!(f, "Value::Brush({:?})", b), - Value::PathElements(e) => write!(f, "Value::PathElements({:?})", e), + Value::PathData(e) => write!(f, "Value::PathElements({:?})", e), Value::EasingCurve(c) => write!(f, "Value::EasingCurve({:?})", c), Value::EnumerationValue(n, v) => write!(f, "Value::EnumerationValue({:?}, {:?})", n, v), Value::LayoutCache(v) => write!(f, "Value::LayoutCache({:?})", v), @@ -215,7 +215,7 @@ declare_value_conversion!(Bool => [bool] ); declare_value_conversion!(Image => [Image] ); declare_value_conversion!(Struct => [Struct] ); declare_value_conversion!(Brush => [Brush] ); -declare_value_conversion!(PathElements => [PathData]); +declare_value_conversion!(PathData => [PathData]); declare_value_conversion!(EasingCurve => [sixtyfps_corelib::animations::EasingCurve]); declare_value_conversion!(LayoutCache => [SharedVector] ); diff --git a/sixtyfps_runtime/interpreter/eval.rs b/sixtyfps_runtime/interpreter/eval.rs index 9141d5c25..9eea9cbde 100644 --- a/sixtyfps_runtime/interpreter/eval.rs +++ b/sixtyfps_runtime/interpreter/eval.rs @@ -561,8 +561,8 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon .map(|(k, v)| (k.clone(), eval_expression(v, local_context))) .collect(), ), - Expression::PathElements { elements } => { - Value::PathElements(convert_path(elements, local_context)) + Expression::PathData(data) => { + Value::PathData(convert_path(data, local_context)) } Expression::StoreLocalVariable { name, value } => { let value = eval_expression(value, local_context); @@ -847,7 +847,7 @@ fn check_value_type(value: &Value, ty: &Type) -> bool { Type::Model => { matches!(value, Value::Model(_) | Value::Bool(_) | Value::Number(_) | Value::Array(_)) } - Type::PathElements => matches!(value, Value::PathElements(_)), + Type::PathData => matches!(value, Value::PathData(_)), Type::Easing => matches!(value, Value::EasingCurve(_)), Type::Brush => matches!(value, Value::Brush(_)), Type::Array(inner) => { @@ -1138,7 +1138,7 @@ pub fn default_value_for_type(ty: &Type) -> Value { Type::Void | Type::Invalid => Value::Void, Type::Model => Value::Void, Type::UnitProduct(_) => Value::Number(0.), - Type::PathElements => Value::PathElements(Default::default()), + Type::PathData => Value::PathData(Default::default()), Type::LayoutCache => Value::LayoutCache(Default::default()), Type::InferredProperty | Type::InferredCallback diff --git a/sixtyfps_runtime/interpreter/eval_layout.rs b/sixtyfps_runtime/interpreter/eval_layout.rs index a68baf690..7de954519 100644 --- a/sixtyfps_runtime/interpreter/eval_layout.rs +++ b/sixtyfps_runtime/interpreter/eval_layout.rs @@ -145,7 +145,7 @@ pub(crate) fn solve_layout( x: 0., y: 0., elements: &eval::eval_expression( - &Expression::PathElements { elements: path_layout.path.clone() }, + &Expression::PathData(path_layout.path.clone()), local_context, ) .try_into()