mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
More work on the state binding for transition:
When there is a transition, turn the state property into a property of StateInfo Not yet implemented for C++
This commit is contained in:
parent
05924da620
commit
cfa9413861
11 changed files with 156 additions and 71 deletions
|
@ -64,6 +64,7 @@ using ItemVisitorRefMut = vtable::VRefMut<cbindgen_private::ItemVisitorVTable>;
|
||||||
}
|
}
|
||||||
using cbindgen_private::EasingCurve;
|
using cbindgen_private::EasingCurve;
|
||||||
using cbindgen_private::PropertyAnimation;
|
using cbindgen_private::PropertyAnimation;
|
||||||
|
using cbindgen_private::StateInfo;
|
||||||
using cbindgen_private::Slice;
|
using cbindgen_private::Slice;
|
||||||
using cbindgen_private::TextHorizontalAlignment;
|
using cbindgen_private::TextHorizontalAlignment;
|
||||||
using cbindgen_private::TextVerticalAlignment;
|
using cbindgen_private::TextVerticalAlignment;
|
||||||
|
|
|
@ -159,6 +159,11 @@ pub use sixtyfps_corelib::string::SharedString;
|
||||||
pub use sixtyfps_corelib::timers::{Timer, TimerMode};
|
pub use sixtyfps_corelib::timers::{Timer, TimerMode};
|
||||||
pub use sixtyfps_corelib::{ARGBColor, Color};
|
pub use sixtyfps_corelib::{ARGBColor, Color};
|
||||||
|
|
||||||
|
// FIXME: this should not be in this namespace
|
||||||
|
// but the name is `sixtyfps::StateInfo` in builtin.60
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use sixtyfps_corelib::properties::StateInfo;
|
||||||
|
|
||||||
/// internal re_exports used by the macro generated
|
/// internal re_exports used by the macro generated
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod re_exports {
|
pub mod re_exports {
|
||||||
|
@ -187,7 +192,7 @@ pub mod re_exports {
|
||||||
pub use sixtyfps_corelib::items::*;
|
pub use sixtyfps_corelib::items::*;
|
||||||
pub use sixtyfps_corelib::layout::*;
|
pub use sixtyfps_corelib::layout::*;
|
||||||
pub use sixtyfps_corelib::model::*;
|
pub use sixtyfps_corelib::model::*;
|
||||||
pub use sixtyfps_corelib::properties::{Property, PropertyTracker};
|
pub use sixtyfps_corelib::properties::{set_state_binding, Property, PropertyTracker};
|
||||||
pub use sixtyfps_corelib::signals::Signal;
|
pub use sixtyfps_corelib::signals::Signal;
|
||||||
pub use sixtyfps_corelib::slice::Slice;
|
pub use sixtyfps_corelib::slice::Slice;
|
||||||
pub use sixtyfps_corelib::Color;
|
pub use sixtyfps_corelib::Color;
|
||||||
|
|
|
@ -203,6 +203,13 @@ export struct StandardListViewItem := {
|
||||||
text: string
|
text: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export struct StateInfo := {
|
||||||
|
//-name:sixtyfps::StateInfo
|
||||||
|
current_state: int,
|
||||||
|
previous_state: int,
|
||||||
|
//change_time: duration,
|
||||||
|
}
|
||||||
|
|
||||||
export NativeButton := _ {
|
export NativeButton := _ {
|
||||||
property <length> x;
|
property <length> x;
|
||||||
property <length> y;
|
property <length> y;
|
||||||
|
|
|
@ -144,7 +144,8 @@ fn handle_property_binding(
|
||||||
init: &mut Vec<TokenStream>,
|
init: &mut Vec<TokenStream>,
|
||||||
) {
|
) {
|
||||||
let rust_property = access_member(item_rc, prop_name, component, quote!(_self), false);
|
let rust_property = access_member(item_rc, prop_name, component, quote!(_self), false);
|
||||||
if matches!(item_rc.borrow().lookup_property(prop_name), Type::Signal{..}) {
|
let prop_type = item_rc.borrow().lookup_property(prop_name);
|
||||||
|
if matches!(prop_type, Type::Signal{..}) {
|
||||||
let tokens_for_expression = compile_expression(binding_expression, &component);
|
let tokens_for_expression = compile_expression(binding_expression, &component);
|
||||||
init.push(quote!(
|
init.push(quote!(
|
||||||
#rust_property.set_handler({
|
#rust_property.set_handler({
|
||||||
|
@ -172,26 +173,30 @@ fn handle_property_binding(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let tokens_for_expression = compile_expression(binding_expression, &component);
|
let tokens_for_expression = compile_expression(binding_expression, &component);
|
||||||
let setter = if binding_expression.is_constant() {
|
init.push(if binding_expression.is_constant() {
|
||||||
quote!(set((#tokens_for_expression) as _))
|
quote! { #rust_property.set((#tokens_for_expression) as _); }
|
||||||
} else {
|
} else {
|
||||||
property_set_binding_tokens(
|
let binding_tokens = quote!({
|
||||||
component,
|
|
||||||
&item_rc,
|
|
||||||
prop_name,
|
|
||||||
quote!({
|
|
||||||
let self_weak = sixtyfps::re_exports::VRc::downgrade(&self_pinned);
|
let self_weak = sixtyfps::re_exports::VRc::downgrade(&self_pinned);
|
||||||
move || {
|
move || {
|
||||||
let self_pinned = self_weak.upgrade().unwrap();
|
let self_pinned = self_weak.upgrade().unwrap();
|
||||||
let _self = self_pinned.as_pin_ref();
|
let _self = self_pinned.as_pin_ref();
|
||||||
(#tokens_for_expression) as _
|
(#tokens_for_expression) as _
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
)
|
|
||||||
|
let is_state_info = match prop_type {
|
||||||
|
Type::Object { name: Some(name), .. } if name.ends_with("::StateInfo") => true,
|
||||||
|
_ => false,
|
||||||
};
|
};
|
||||||
init.push(quote!(
|
if is_state_info {
|
||||||
#rust_property.#setter;
|
quote! { sixtyfps::re_exports::set_state_binding(#rust_property, #binding_tokens); }
|
||||||
));
|
} else if let Some(anim) = property_animation_tokens(component, &item_rc, prop_name) {
|
||||||
|
quote! { #rust_property.set_animated_binding(#binding_tokens, #anim); }
|
||||||
|
} else {
|
||||||
|
quote! { #rust_property.set_binding(#binding_tokens); }
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,19 +904,6 @@ fn property_set_value_tokens(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn property_set_binding_tokens(
|
|
||||||
component: &Rc<Component>,
|
|
||||||
element: &ElementRc,
|
|
||||||
property_name: &str,
|
|
||||||
binding_tokens: TokenStream,
|
|
||||||
) -> TokenStream {
|
|
||||||
if let Some(animation_tokens) = property_animation_tokens(component, element, property_name) {
|
|
||||||
quote!(set_animated_binding(#binding_tokens, #animation_tokens))
|
|
||||||
} else {
|
|
||||||
quote!(set_binding(#binding_tokens))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the code that can access the given property or signal (but without the set or get)
|
/// Returns the code that can access the given property or signal (but without the set or get)
|
||||||
///
|
///
|
||||||
/// to be used like:
|
/// to be used like:
|
||||||
|
|
|
@ -156,7 +156,7 @@ pub async fn run_passes<'a>(
|
||||||
passes::materialize_fake_properties::materialize_fake_properties(&doc.root_component);
|
passes::materialize_fake_properties::materialize_fake_properties(&doc.root_component);
|
||||||
passes::collect_resources::collect_resources(&doc.root_component);
|
passes::collect_resources::collect_resources(&doc.root_component);
|
||||||
doc.root_component.embed_file_resources.set(compiler_config.embed_resources);
|
doc.root_component.embed_file_resources.set(compiler_config.embed_resources);
|
||||||
passes::lower_states::lower_states(&doc.root_component, diag);
|
passes::lower_states::lower_states(&doc.root_component, &doc.local_registry, diag);
|
||||||
passes::repeater_component::process_repeater_components(&doc.root_component);
|
passes::repeater_component::process_repeater_components(&doc.root_component);
|
||||||
passes::lower_layout::lower_layouts(&doc.root_component, &mut type_loader, diag).await;
|
passes::lower_layout::lower_layouts(&doc.root_component, &mut type_loader, diag).await;
|
||||||
passes::deduplicate_property_read::deduplicate_property_read(&doc.root_component);
|
passes::deduplicate_property_read::deduplicate_property_read(&doc.root_component);
|
||||||
|
|
|
@ -15,19 +15,38 @@ use crate::langtype::Type;
|
||||||
use crate::object_tree::*;
|
use crate::object_tree::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn lower_states(component: &Rc<Component>, diag: &mut BuildDiagnostics) {
|
pub fn lower_states(
|
||||||
recurse_elem(&component.root_element, &(), &mut |elem, _| lower_state_in_element(elem, diag));
|
component: &Rc<Component>,
|
||||||
|
tr: &crate::typeregister::TypeRegister,
|
||||||
|
diag: &mut BuildDiagnostics,
|
||||||
|
) {
|
||||||
|
let state_info_type = tr.lookup("StateInfo");
|
||||||
|
assert!(matches!(state_info_type, Type::Object{ name: Some(_), .. }));
|
||||||
|
recurse_elem(&component.root_element, &(), &mut |elem, _| {
|
||||||
|
lower_state_in_element(elem, &state_info_type, diag)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_state_in_element(root_element: &ElementRc, _diag: &mut BuildDiagnostics) {
|
fn lower_state_in_element(
|
||||||
|
root_element: &ElementRc,
|
||||||
|
state_info_type: &Type,
|
||||||
|
_diag: &mut BuildDiagnostics,
|
||||||
|
) {
|
||||||
if root_element.borrow().states.is_empty() {
|
if root_element.borrow().states.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let has_transitions = !root_element.borrow().transitions.is_empty();
|
||||||
let state_property = compute_state_property_name(root_element);
|
let state_property = compute_state_property_name(root_element);
|
||||||
let state_property_ref = Expression::PropertyReference(NamedReference {
|
let mut state_property_ref = Expression::PropertyReference(NamedReference {
|
||||||
element: Rc::downgrade(root_element),
|
element: Rc::downgrade(root_element),
|
||||||
name: state_property.clone(),
|
name: state_property.clone(),
|
||||||
});
|
});
|
||||||
|
if has_transitions {
|
||||||
|
state_property_ref = Expression::ObjectAccess {
|
||||||
|
base: Box::new(state_property_ref),
|
||||||
|
name: "current_state".into(),
|
||||||
|
};
|
||||||
|
}
|
||||||
let mut state_value = Expression::NumberLiteral(0., Unit::None);
|
let mut state_value = Expression::NumberLiteral(0., Unit::None);
|
||||||
let states = std::mem::take(&mut root_element.borrow_mut().states);
|
let states = std::mem::take(&mut root_element.borrow_mut().states);
|
||||||
for (idx, state) in states.into_iter().enumerate().rev() {
|
for (idx, state) in states.into_iter().enumerate().rev() {
|
||||||
|
@ -58,7 +77,10 @@ fn lower_state_in_element(root_element: &ElementRc, _diag: &mut BuildDiagnostics
|
||||||
}
|
}
|
||||||
root_element.borrow_mut().property_declarations.insert(
|
root_element.borrow_mut().property_declarations.insert(
|
||||||
state_property.clone(),
|
state_property.clone(),
|
||||||
PropertyDeclaration { property_type: Type::Int32, ..PropertyDeclaration::default() },
|
PropertyDeclaration {
|
||||||
|
property_type: if has_transitions { state_info_type.clone() } else { Type::Int32 },
|
||||||
|
..PropertyDeclaration::default()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
root_element.borrow_mut().bindings.insert(state_property.clone(), state_value.into());
|
root_element.borrow_mut().bindings.insert(state_property.clone(), state_value.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl Default for EasingCurve {
|
||||||
/// Represent an instant, in miliseconds since the AnimationDriver's initial_instant
|
/// Represent an instant, in miliseconds since the AnimationDriver's initial_instant
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Ord, PartialOrd, Eq)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Ord, PartialOrd, Eq)]
|
||||||
pub struct Instant(u64);
|
pub struct Instant(pub u64);
|
||||||
|
|
||||||
impl core::ops::Sub<Instant> for Instant {
|
impl core::ops::Sub<Instant> for Instant {
|
||||||
type Output = core::time::Duration;
|
type Output = core::time::Duration;
|
||||||
|
|
|
@ -1175,11 +1175,11 @@ mod animation_tests {
|
||||||
#[derive(Clone, Default, Debug, PartialEq)]
|
#[derive(Clone, Default, Debug, PartialEq)]
|
||||||
pub struct StateInfo {
|
pub struct StateInfo {
|
||||||
/// The current state value
|
/// The current state value
|
||||||
current_state: u32,
|
pub current_state: i32,
|
||||||
/// The previous state
|
/// The previous state
|
||||||
previous_state: u32,
|
pub previous_state: i32,
|
||||||
/// The instant in which the state changed last
|
/// The instant in which the state changed last
|
||||||
change_time: crate::animations::Instant,
|
pub change_time: crate::animations::Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StateInfoBinding<F> {
|
struct StateInfoBinding<F> {
|
||||||
|
@ -1187,7 +1187,7 @@ struct StateInfoBinding<F> {
|
||||||
binding: F,
|
binding: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fn() -> u32> crate::properties::BindingCallable for StateInfoBinding<F> {
|
impl<F: Fn() -> i32> crate::properties::BindingCallable for StateInfoBinding<F> {
|
||||||
unsafe fn evaluate(self: Pin<&Self>, value: *mut ()) -> BindingResult {
|
unsafe fn evaluate(self: Pin<&Self>, value: *mut ()) -> BindingResult {
|
||||||
// Safety: We should ony set this binding on a property of type StateInfo
|
// Safety: We should ony set this binding on a property of type StateInfo
|
||||||
let value = &mut *(value as *mut StateInfo);
|
let value = &mut *(value as *mut StateInfo);
|
||||||
|
@ -1196,6 +1196,7 @@ impl<F: Fn() -> u32> crate::properties::BindingCallable for StateInfoBinding<F>
|
||||||
if new_state != value.current_state {
|
if new_state != value.current_state {
|
||||||
value.previous_state = value.current_state;
|
value.previous_state = value.current_state;
|
||||||
value.change_time = timestamp.unwrap_or_else(crate::animations::current_tick);
|
value.change_time = timestamp.unwrap_or_else(crate::animations::current_tick);
|
||||||
|
value.current_state = new_state;
|
||||||
}
|
}
|
||||||
BindingResult::KeepBinding
|
BindingResult::KeepBinding
|
||||||
}
|
}
|
||||||
|
@ -1208,7 +1209,7 @@ impl<F: Fn() -> u32> crate::properties::BindingCallable for StateInfoBinding<F>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a binding that returns a state to a StateInfo property
|
/// Sets a binding that returns a state to a StateInfo property
|
||||||
pub fn set_state_binding(property: Pin<&Property<StateInfo>>, binding: impl Fn() -> u32 + 'static) {
|
pub fn set_state_binding(property: Pin<&Property<StateInfo>>, binding: impl Fn() -> i32 + 'static) {
|
||||||
let bind_callable = StateInfoBinding { dirty_time: Cell::new(None), binding };
|
let bind_callable = StateInfoBinding { dirty_time: Cell::new(None), binding };
|
||||||
// Safety: The StateInfoBinding is a BindingCallable for type StateInfo
|
// Safety: The StateInfoBinding is a BindingCallable for type StateInfo
|
||||||
unsafe { property.handle.set_binding(bind_callable) }
|
unsafe { property.handle.set_binding(bind_callable) }
|
||||||
|
|
|
@ -643,6 +643,9 @@ fn generate_component<'id>(
|
||||||
.insert(name.clone(), builder.add_field_type::<Signal<[eval::Value]>>());
|
.insert(name.clone(), builder.add_field_type::<Signal<[eval::Value]>>());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Type::Object { name: Some(name), .. } if name.ends_with("::StateInfo") => {
|
||||||
|
property_info::<sixtyfps_corelib::properties::StateInfo>()
|
||||||
|
}
|
||||||
Type::Object { .. } => property_info::<eval::Value>(),
|
Type::Object { .. } => property_info::<eval::Value>(),
|
||||||
Type::Array(_) => property_info::<eval::Value>(),
|
Type::Array(_) => property_info::<eval::Value>(),
|
||||||
Type::Percent => property_info::<f32>(),
|
Type::Percent => property_info::<f32>(),
|
||||||
|
@ -888,6 +891,39 @@ pub fn instantiate<'id>(
|
||||||
offset, prop: prop_info, ..
|
offset, prop: prop_info, ..
|
||||||
}) = component_type.custom_properties.get(prop.as_str())
|
}) = component_type.custom_properties.get(prop.as_str())
|
||||||
{
|
{
|
||||||
|
let c = Pin::new_unchecked(vtable::VRef::from_raw(
|
||||||
|
NonNull::from(&component_type.ct).cast(),
|
||||||
|
component_box.instance.as_ptr().cast(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let is_state_info = match ty {
|
||||||
|
Type::Object { name: Some(name), .. }
|
||||||
|
if name.ends_with("::StateInfo") =>
|
||||||
|
{
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if is_state_info {
|
||||||
|
let prop = Pin::new_unchecked(
|
||||||
|
&*(instance_ref.as_ptr().add(*offset)
|
||||||
|
as *const Property<sixtyfps_corelib::properties::StateInfo>),
|
||||||
|
);
|
||||||
|
let e = expr.expression.clone();
|
||||||
|
sixtyfps_corelib::properties::set_state_binding(prop, move || {
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
eval::eval_expression(
|
||||||
|
&e,
|
||||||
|
&mut eval::EvalLocalContext::from_component_instance(
|
||||||
|
InstanceRef::from_pin_ref(c, guard),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let maybe_animation = animation_for_property(
|
let maybe_animation = animation_for_property(
|
||||||
instance_ref,
|
instance_ref,
|
||||||
&component_type.original.root_element.borrow().property_animations,
|
&component_type.original.root_element.borrow().property_animations,
|
||||||
|
@ -912,12 +948,6 @@ pub fn instantiate<'id>(
|
||||||
prop_info.set(item, v, None).unwrap();
|
prop_info.set(item, v, None).unwrap();
|
||||||
} else {
|
} else {
|
||||||
let e = e.clone();
|
let e = e.clone();
|
||||||
let component_type = component_type.clone();
|
|
||||||
let instance = component_box.instance.as_ptr();
|
|
||||||
let c = Pin::new_unchecked(vtable::VRef::from_raw(
|
|
||||||
NonNull::from(&component_type.ct).cast(),
|
|
||||||
instance.cast(),
|
|
||||||
));
|
|
||||||
prop_info
|
prop_info
|
||||||
.set_binding(
|
.set_binding(
|
||||||
item,
|
item,
|
||||||
|
|
|
@ -159,27 +159,33 @@ declare_value_conversion!(Color => [Color] );
|
||||||
declare_value_conversion!(PathElements => [PathData]);
|
declare_value_conversion!(PathElements => [PathData]);
|
||||||
declare_value_conversion!(EasingCurve => [corelib::animations::EasingCurve]);
|
declare_value_conversion!(EasingCurve => [corelib::animations::EasingCurve]);
|
||||||
|
|
||||||
impl TryFrom<corelib::model::StandardListViewItem> for Value {
|
macro_rules! declare_value_struct_conversion {
|
||||||
|
(struct $name:path { $($field:ident),* $(,)? }) => {
|
||||||
|
impl TryFrom<$name> for Value {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn try_from(
|
fn try_from($name { $($field),* }: $name) -> Result<Self, ()> {
|
||||||
corelib::model::StandardListViewItem { text }: corelib::model::StandardListViewItem,
|
|
||||||
) -> Result<Self, ()> {
|
|
||||||
let mut hm = HashMap::new();
|
let mut hm = HashMap::new();
|
||||||
hm.insert("text".into(), text.try_into()?);
|
$(hm.insert(stringify!($field).into(), $field.try_into()?);)*
|
||||||
Ok(Value::Object(hm))
|
Ok(Value::Object(hm))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl TryInto<corelib::model::StandardListViewItem> for Value {
|
impl TryInto<$name> for Value {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn try_into(self) -> Result<corelib::model::StandardListViewItem, ()> {
|
fn try_into(self) -> Result<$name, ()> {
|
||||||
match self {
|
match self {
|
||||||
Self::Object(x) => Ok(corelib::model::StandardListViewItem {
|
Self::Object(x) => {
|
||||||
text: x.get("text").ok_or(())?.clone().try_into()?,
|
type Ty = $name;
|
||||||
}),
|
Ok(Ty { $($field: x.get(stringify!($field)).ok_or(())?.clone().try_into()?),* })
|
||||||
|
}
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_value_struct_conversion!(struct corelib::model::StandardListViewItem { text });
|
||||||
|
declare_value_struct_conversion!(struct corelib::properties::StateInfo { current_state, previous_state, change_time });
|
||||||
|
|
||||||
macro_rules! declare_value_enum_conversion {
|
macro_rules! declare_value_enum_conversion {
|
||||||
($ty:ty, $n:ident) => {
|
($ty:ty, $n:ident) => {
|
||||||
|
@ -212,6 +218,22 @@ declare_value_enum_conversion!(corelib::items::TextHorizontalAlignment, TextHori
|
||||||
declare_value_enum_conversion!(corelib::items::TextVerticalAlignment, TextVerticalAlignment);
|
declare_value_enum_conversion!(corelib::items::TextVerticalAlignment, TextVerticalAlignment);
|
||||||
declare_value_enum_conversion!(corelib::layout::LayoutAlignment, LayoutAlignment);
|
declare_value_enum_conversion!(corelib::layout::LayoutAlignment, LayoutAlignment);
|
||||||
|
|
||||||
|
impl TryFrom<corelib::animations::Instant> for Value {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(value: corelib::animations::Instant) -> Result<Self, ()> {
|
||||||
|
Ok(Value::Number(value.0 as _))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TryInto<corelib::animations::Instant> for Value {
|
||||||
|
type Error = ();
|
||||||
|
fn try_into(self) -> Result<corelib::animations::Instant, ()> {
|
||||||
|
match self {
|
||||||
|
Value::Number(x) => Ok(corelib::animations::Instant(x as _)),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum ComponentInstance<'a, 'id> {
|
enum ComponentInstance<'a, 'id> {
|
||||||
InstanceRef(InstanceRef<'a, 'id>),
|
InstanceRef(InstanceRef<'a, 'id>),
|
||||||
|
|
|
@ -110,6 +110,11 @@ fn gen_corelib(include_dir: &Path) -> anyhow::Result<()> {
|
||||||
|
|
||||||
let mut properties_config = config.clone();
|
let mut properties_config = config.clone();
|
||||||
properties_config.export.exclude.clear();
|
properties_config.export.exclude.clear();
|
||||||
|
properties_config.export.include.push("StateInfo".into());
|
||||||
|
properties_config
|
||||||
|
.export
|
||||||
|
.pre_body
|
||||||
|
.insert("StateInfo".to_owned(), " using Instant = uint64_t;".into());
|
||||||
cbindgen::Builder::new()
|
cbindgen::Builder::new()
|
||||||
.with_config(properties_config)
|
.with_config(properties_config)
|
||||||
.with_src(crate_dir.join("properties.rs"))
|
.with_src(crate_dir.join("properties.rs"))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue