ark-api 0.17.0-pre.15

Ark API
Documentation
use super::*;

/// Common trait for value converters.
pub trait ValueConverterTrait<T> {
    /// Wraps the passed-in value in a `Value` enum.
    #[allow(clippy::wrong_self_convention)]
    fn into_value(value: T) -> Value;
    /// Extracts the value from a `Value` enum.
    fn from_value(value: &Value) -> T;
}

/// A utility to convert values to and from the `Value` enum.
pub struct ValueConverter;

impl ValueConverterTrait<bool> for ValueConverter {
    #[inline]
    fn into_value(v: bool) -> Value {
        Value::from_bool(v)
    }
    #[inline]
    fn from_value(v: &Value) -> bool {
        v.as_bool()
    }
}

impl ValueConverterTrait<i64> for ValueConverter {
    #[inline]
    fn into_value(v: i64) -> Value {
        Value::from_i64(v)
    }
    #[inline]
    fn from_value(v: &Value) -> i64 {
        v.as_i64()
    }
}

impl ValueConverterTrait<u64> for ValueConverter {
    #[inline]
    fn into_value(v: u64) -> Value {
        Value::from_i64(v as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> u64 {
        v.as_i64() as u64
    }
}

impl ValueConverterTrait<Entity> for ValueConverter {
    #[inline]
    fn into_value(v: Entity) -> Value {
        Value::from_i64(v.0 as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> Entity {
        Entity::from_ffi(v.as_i64() as u64)
    }
}

impl ValueConverterTrait<Option<MeshStyle>> for ValueConverter {
    #[inline]
    fn into_value(v: Option<MeshStyle>) -> Value {
        <Self as ValueConverterTrait<Entity>>::into_value(
            v.map_or(Entity::invalid(), |v| v.entity()),
        )
    }
    #[inline]
    fn from_value(v: &Value) -> Option<MeshStyle> {
        let e = <Self as ValueConverterTrait<Entity>>::from_value(v);
        e.is_valid().then(|| e.get::<MeshStyle>()).flatten()
    }
}

impl ValueConverterTrait<MeshStyleFlags> for ValueConverter {
    #[inline]
    fn into_value(v: MeshStyleFlags) -> Value {
        Value::from_i64(i64::from(v.bits()))
    }
    #[inline]
    fn from_value(v: &Value) -> MeshStyleFlags {
        MeshStyleFlags::from_bits_truncate(v.as_i64() as u32)
    }
}

impl ValueConverterTrait<MeshVisibilityFlags> for ValueConverter {
    #[inline]
    fn into_value(v: MeshVisibilityFlags) -> Value {
        Value::from_i64(i64::from(v.bits()))
    }
    #[inline]
    fn from_value(v: &Value) -> MeshVisibilityFlags {
        MeshVisibilityFlags::from_bits_truncate(v.as_i64() as u8)
    }
}

impl ValueConverterTrait<DynamicLockFlags> for ValueConverter {
    #[inline]
    fn into_value(v: DynamicLockFlags) -> Value {
        Value::from_i64(i64::from(v.bits()))
    }
    #[inline]
    fn from_value(v: &Value) -> DynamicLockFlags {
        DynamicLockFlags::from_bits_truncate(v.as_i64() as u8)
    }
}

impl ValueConverterTrait<CombineMode> for ValueConverter {
    #[inline]
    fn into_value(v: CombineMode) -> Value {
        Value::from_i64(v as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> CombineMode {
        if let Ok(mode) = CombineMode::try_from(v.as_i64() as u32) {
            mode
        } else {
            log::warn!("Trying to convert a Value to a CombineMode that doesn't exist. Are you running an old version of the api?");

            // Just have to default to something. This is not good but we have
            // no other reasonable choice.
            CombineMode::Average
        }
    }
}

impl ValueConverterTrait<RigidBodyMode> for ValueConverter {
    #[inline]
    fn into_value(v: RigidBodyMode) -> Value {
        Value::from_i64(v as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> RigidBodyMode {
        if let Ok(mode) = RigidBodyMode::try_from(v.as_i64() as u64) {
            mode
        } else {
            log::warn!("Trying to convert a Value to a RigidBodyMode that doesn't exist. Are you running an old version of the api?");

            // Just have to default to something. This is not good but we have
            // no other reasonable choice.
            RigidBodyMode::Off
        }
    }
}

impl ValueConverterTrait<JointType> for ValueConverter {
    #[inline]
    fn into_value(v: JointType) -> Value {
        Value::from_i64(v as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> JointType {
        if let Ok(joint_type) = JointType::try_from(v.as_i64() as u64) {
            joint_type
        } else {
            log::warn!("Trying to convert a Value to a JointType that doesn't exist. Are you running an old version of the api?");

            // Just have to default to something. This is not good but we have
            // no other reasonable choice.
            JointType::Fixed
        }
    }
}

impl ValueConverterTrait<JointLimitType> for ValueConverter {
    #[inline]
    fn into_value(v: JointLimitType) -> Value {
        Value::from_i64(v as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> JointLimitType {
        if let Ok(joint_limit_type) = JointLimitType::try_from(v.as_i64() as u64) {
            joint_limit_type
        } else {
            log::warn!("Trying to convert a Value to a JointLimitType that doesn't exist. Are you running an old version of the api?");

            // At least we have a reasonable fallback here.
            JointLimitType::Off
        }
    }
}

impl ValueConverterTrait<D6MotionType> for ValueConverter {
    #[inline]
    fn into_value(v: D6MotionType) -> Value {
        Value::from_i64(v as i64)
    }
    #[inline]
    fn from_value(v: &Value) -> D6MotionType {
        if let Ok(d6_motion_type) = D6MotionType::try_from(v.as_i64() as u64) {
            d6_motion_type
        } else {
            log::warn!("Trying to convert a Value to a JointLimitType that doesn't exist. Are you running an old version of the api?");
            D6MotionType::Free
        }
    }
}

impl ValueConverterTrait<D6DriveParams> for ValueConverter {
    #[inline]
    fn into_value(v: D6DriveParams) -> Value {
        Value::from_vec3([v.stiffness, v.damping, v.force_limit])
    }
    #[inline]
    fn from_value(v: &Value) -> D6DriveParams {
        let v = v.as_vec3();
        D6DriveParams {
            stiffness: v[0],
            damping: v[1],
            force_limit: v[2],
        }
    }
}

impl ValueConverterTrait<D6SpringParams> for ValueConverter {
    #[inline]
    fn into_value(v: D6SpringParams) -> Value {
        Value::from_vec2([v.stiffness, v.damping])
    }
    #[inline]
    fn from_value(v: &Value) -> D6SpringParams {
        let v = v.as_vec2();
        D6SpringParams {
            stiffness: v[0],
            damping: v[1],
        }
    }
}

impl ValueConverterTrait<LimitPair> for ValueConverter {
    #[inline]
    fn into_value(v: LimitPair) -> Value {
        Value::from_vec2([v.lower, v.upper])
    }
    #[inline]
    fn from_value(v: &Value) -> LimitPair {
        let v = v.as_vec2();
        LimitPair {
            lower: v[0],
            upper: v[1],
        }
    }
}

// Finally, some more primitive types.

impl ValueConverterTrait<f32> for ValueConverter {
    #[inline]
    fn into_value(v: f32) -> Value {
        Value::from_f32(v)
    }
    #[inline]
    fn from_value(v: &Value) -> f32 {
        v.as_f32()
    }
}

impl ValueConverterTrait<Vec2> for ValueConverter {
    #[inline]
    fn into_value(v: Vec2) -> Value {
        Value::from_vec2(v.into())
    }
    #[inline]
    fn from_value(v: &Value) -> Vec2 {
        v.as_vec2().into()
    }
}

impl ValueConverterTrait<Vec3> for ValueConverter {
    #[inline]
    fn into_value(v: Vec3) -> Value {
        Value::from_vec3(v.into())
    }
    #[inline]
    fn from_value(v: &Value) -> Vec3 {
        v.as_vec3().into()
    }
}

impl ValueConverterTrait<Vec4> for ValueConverter {
    #[inline]
    fn into_value(v: Vec4) -> Value {
        Value::from_vec4(v.into())
    }
    #[inline]
    fn from_value(v: &Value) -> Vec4 {
        v.as_vec4().into()
    }
}

impl ValueConverterTrait<Quat> for ValueConverter {
    #[inline]
    fn into_value(v: Quat) -> Value {
        Value::from_quat(v.into())
    }
    #[inline]
    fn from_value(v: &Value) -> Quat {
        Quat::from_vec4(v.as_quat().into())
    }
}