Support tuple structs in AnimatedField (#16747)

# Objective

Partially fixes #16736.

## Solution

`AnimatedField::new_unchecked` now supports tuple struct fields.
`animated_field!` is unchanged.

## Testing

Added a test to make sure common and simple uses of
`AnimatedField::new_unchecked` with tuple structs don't panic.

---------

Co-authored-by: yonzebu <yonzebu@gmail.com>
This commit is contained in:
yonzebu 2024-12-11 09:06:08 -08:00 committed by GitHub
parent 5f1e114209
commit 2994e53d82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -243,18 +243,26 @@ where
impl<C: Typed, P, F: Fn(&mut C) -> &mut P + 'static> AnimatedField<C, P, F> { impl<C: Typed, P, F: Fn(&mut C) -> &mut P + 'static> AnimatedField<C, P, F> {
/// Creates a new instance of [`AnimatedField`]. This operates under the assumption that /// Creates a new instance of [`AnimatedField`]. This operates under the assumption that
/// `C` is a reflect-able struct with named fields, and that `field_name` is a valid field on that struct. /// `C` is a reflect-able struct, and that `field_name` is a valid field on that struct.
/// ///
/// # Panics /// # Panics
/// If the type of `C` is not a struct with named fields or if the `field_name` does not exist. /// If the type of `C` is not a struct or if the `field_name` does not exist.
pub fn new_unchecked(field_name: &str, func: F) -> Self { pub fn new_unchecked(field_name: &str, func: F) -> Self {
let TypeInfo::Struct(struct_info) = C::type_info() else { let field_index;
if let TypeInfo::Struct(struct_info) = C::type_info() {
field_index = struct_info
.index_of(field_name)
.expect("Field name should exist");
} else if let TypeInfo::TupleStruct(struct_info) = C::type_info() {
field_index = field_name
.parse()
.expect("Field name should be a valid tuple index");
if field_index >= struct_info.field_len() {
panic!("Field name should be a valid tuple index");
}
} else {
panic!("Only structs are supported in `AnimatedField::new_unchecked`") panic!("Only structs are supported in `AnimatedField::new_unchecked`")
}; }
let field_index = struct_info
.index_of(field_name)
.expect("Field name should exist");
Self { Self {
func, func,
@ -984,3 +992,21 @@ macro_rules! animated_field {
}) })
}; };
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_animated_field_tuple_struct_simple_uses() {
#[derive(Clone, Debug, Component, Reflect)]
struct A(f32);
let _ = AnimatedField::new_unchecked("0", |a: &mut A| &mut a.0);
#[derive(Clone, Debug, Component, Reflect)]
struct B(f32, f64, f32);
let _ = AnimatedField::new_unchecked("0", |b: &mut B| &mut b.0);
let _ = AnimatedField::new_unchecked("1", |b: &mut B| &mut b.1);
let _ = AnimatedField::new_unchecked("2", |b: &mut B| &mut b.2);
}
}