ark-api-ffi 0.17.0-pre.15

Ark low-level Wasm FFI API
Documentation
define_api_id!(0x3c5a_8c47_30ab_ec47, "world-v4");

pub use crate::world_v0::EntityHandle;
pub use crate::world_v0::MeshHandle;
pub use crate::world_v0::Ray;
pub use crate::world_v0::Value;
pub use crate::world_v0::ENTITY_HANDLE_INVALID;
pub use crate::world_v2::DataHandle;
pub use crate::world_v2::ResourceHandleRepr;
pub use crate::world_v3::RaycastHit;
use crate::FFIResult;
use bytemuck::Pod;
use bytemuck::Zeroable;

#[ark_api_macros::ark_bindgen(imports = "ark-world-v4")]
mod world {
    use super::*;

    bitflags! {
        #[repr(C)]
        #[derive(Pod, Zeroable)]
        pub struct RaycastQueryOptions : u32 {
            /// For raycasts, skips hits where t = min_t or in other words
            /// direct hits inside a solid primitive.
            const IGNORE_INTERIOR_HITS = 0b0010_0000;
        }
    }

    impl Default for RaycastQueryOptions {
        fn default() -> Self {
            Self::empty()
        }
    }

    #[derive(Copy, Clone, Default, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct RaycastQueryWithOptions {
        pub ray: Ray,
        pub layer_mask: u64,
        pub ignore_entity: EntityHandle,
        pub max_distance: f32,
        pub options: RaycastQueryOptions,
    }

    #[derive(Copy, Clone, Default, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct SpherecastQuery {
        pub ray: Ray,
        pub layer_mask: u64,
        pub ignore_entity: EntityHandle,
        pub max_distance: f32,
        pub options: RaycastQueryOptions,
        /// When zero, this is just a raycast.
        pub spherecast_radius: f32,
        pub _pad: u32,
    }

    #[derive(Copy, Clone, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct SpatialQueryHit {
        pub entity: EntityHandle,
        pub point: [f32; 3],

        /// The distance along the ray.
        ///
        /// The hits are sorted by this distance when returned from raycast and spherecast queries.
        /// In a raycast this is equal to `ray.origin.distance(hit.position)`,
        /// but in a spherecast it can be different.
        pub distance: f32,
        pub normal: [f32; 3],
        pub _pad: u32,
    }

    impl SpatialQueryHit {
        pub fn invalid() -> Self {
            Self {
                entity: ENTITY_HANDLE_INVALID,
                point: [f32::NAN; 3],
                distance: f32::NAN,
                normal: [f32::NAN; 3],
                _pad: 0,
            }
        }
    }

    #[deprecated(note = "Use EntityLocalTransformConformal3 instead")] // 2022-09-13
    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityTransform {
        /// Vec3
        pub translation: [f32; 3],
        /// Quaternion, normalized
        pub rotation: [f32; 4],
        /// Vec3
        pub scale: [f32; 3],
    }

    #[deprecated(note = "Use EntityLocalTransformConformal3 instead")] // 2022-09-13
    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityTransformAffine3 {
        /// Mat3 (rotation, scale)
        pub rotation_scale: [f32; 9],

        /// Vec3 (translation)
        pub translation: [f32; 3],
    }

    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityTransformConformal3 {
        /// Vec4 (translation, scale)
        pub translation_and_scale: [f32; 4],

        /// Quat (rotation)
        pub rotation: [f32; 4],
    }

    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityMeshStyleTint {
        /// Vec4 (rgba)
        pub tint: [f32; 4],
    }

    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityRenderEnable {
        /// 0 = off, 1 = on,
        pub enable: u32,
    }

    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityBounds {
        // Vec3
        pub bounding_box_min: [f32; 3],

        // Vec3
        pub bounding_box_max: [f32; 3],

        // Radius from bounding box center
        pub bounding_sphere_radius: f32,
    }

    #[derive(Clone, Copy, Debug, Pod, Zeroable)]
    #[repr(C)]
    pub struct EntityVelocity {
        // Vec3, linear velocity
        pub positional: [f32; 3],

        // Vec3, angular velocity, axis-angle. length == velocity
        pub rotational: [f32; 3],
    }

    #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
    #[repr(u32)]
    #[non_exhaustive]
    pub enum EntityValueType {
        /// Expects data with the same layout and size as the struct `EntityTransform`
        #[deprecated(note = "Use EntityLocalTransformConformal3 instead")] // 2022-09-13
        EntityLocalTransform = 0,

        /// Expects data with the same layout and size as the struct `EntityMeshStyleTint`
        /// Will set the tint on all mesh styles that are used by this entity. This assumes
        /// each entity uses its own `MeshStyle`.
        EntityRenderTint = 1,

        /// Expects data with the same layout and size as the struct `EntityRenderEnable`
        EntityRenderEnable = 2,

        /// Expects data with the same layout and size as the struct `EntityTransform`
        #[deprecated(note = "Use EntityWorldTransformConformal3 instead")] // 2022-09-13
        EntityWorldTransform = 3,

        /// Expects data with the same layout and size as the struct `EntityBounds`
        EntityLocalBounds = 4,

        /// Expects data with the same layout and size as the struct `EntityVelocity`
        EntityPhysicsVelocity = 5,

        /// Expects data with the same layout and size as the struct `EntityStateFlags`
        EntityStateFlags = 6,

        /// Expects data with the same layout and size as the struct `EntityTransformAffine3`
        #[deprecated(note = "Use EntityWorldTransformConformal3 instead")] // 2022-09-13
        EntityWorldTransformAffine3 = 7,

        /// Expects data with the same layout and size as the struct `EntityTransformConformal3`
        EntityLocalTransformConformal3 = 8,

        /// Expects data with the same layout and size as the struct `EntityTransformConformal3`
        EntityWorldTransformConformal3 = 9,
    }

    impl EntityValueType {
        pub fn size_of_element(&self) -> u32 {
            let size = match self {
                Self::EntityLocalTransform | Self::EntityWorldTransform => {
                    std::mem::size_of::<EntityTransform>()
                }
                Self::EntityRenderTint => std::mem::size_of::<EntityMeshStyleTint>(),
                Self::EntityRenderEnable => std::mem::size_of::<EntityRenderEnable>(),
                Self::EntityLocalBounds => std::mem::size_of::<EntityBounds>(),
                Self::EntityPhysicsVelocity => std::mem::size_of::<EntityVelocity>(),
                Self::EntityStateFlags => std::mem::size_of::<EntityStateFlags>(),
                Self::EntityWorldTransformAffine3 => std::mem::size_of::<EntityTransformAffine3>(),
                Self::EntityLocalTransformConformal3 | Self::EntityWorldTransformConformal3 => {
                    std::mem::size_of::<EntityTransformConformal3>()
                }
            };
            size as u32
        }
    }

    bitflags! {
        /// The state of a requested entity value
        #[repr(C)]
        #[derive(Default, Pod, Zeroable)]
        pub struct EntityStateFlags : u32 {
            const VALID = 0b0000_0001;
            const TRANSFORM_CHANGED = 0b0000_0010;
            const PHYSICS_VELOCITY_CHANGED = 0b0000_0100;
            const BOUNDS_CHANGED = 0b0000_1000;
        }
    }

    bitflags! {
        #[repr(C)]
        #[derive(Pod, Zeroable)]
        pub struct EntityDebugOptions : u32 {
            const PHYSICS_SHAPE_DEBUG_RENDERING_ENABLE = 0b0000_0001;
        }
    }

    /// `min_x`/`min_y`/`width`/`height` are in World units, same as the size the text will appear in the world if you apply no scaling
    #[derive(Debug, Copy, Clone, Pod, Zeroable)]
    #[repr(C)]
    pub struct MeasuredTextSize {
        pub min_x: f32,
        pub min_y: f32,
        pub width: f32,
        pub height: f32,
    }

    #[derive(Debug, Copy, Clone, Pod, Zeroable)]
    #[repr(C)]
    pub struct AudioClipResource {
        pub handle: ResourceHandleRepr,
    }

    #[derive(Default, Copy, Clone, Debug, PartialEq, Pod, Zeroable)]
    #[repr(C)]
    pub struct DominantColorWithArea {
        pub color: [u8; 4], // sRGBA vertex color
        pub area: f32,
    }

    /// Error value that is returned from get/set entity value functions.
    #[derive(Default, Copy, Clone, Debug, PartialEq)]
    #[non_exhaustive]
    #[repr(u32)]
    pub enum EntityValueError {
        /// No error occurred.
        #[default]
        Undefined = 0,
        /// The component parameter value is a NaN value.
        NanValue = 1,
        /// The component parameter value is an infinite value.
        InfiniteParamValue = 2,
        /// The supplied component type is invalid.
        InvalidComponentType = 3,
        /// The supplied component parameter id is invalid.
        InvalidComponentParameterId = 4,
        /// The component did not exist.
        InvalidComponent = 5,
        /// Invalid supplied entity key
        InvalidEntityKey = 6,
        /// Invalid parent of parent (a parent was pointing to an invalid entity)
        InvalidParentOfParent = 7,
        /// Trying to set an entity value that is incompatible with the component parameter value.
        IncompatibleValueType = 8,
        /// Trying to set an entity value that is incompatible with the component parameter value.
        IncompatibleValue = 9,
        /// Could not set the entity component parameter value.
        Unsettable = 10,
        /// Could not get the entity component parameter value.
        Ungettable = 11,
        /// The component was not available.
        NotAvailable = 12,
        /// Trying to set an unnormalized rotation on an entity
        UnnormalizedRotation = 13,
    }

    extern "C" {
        #[deprecated(note = "use `spherecast` instead")] // since 2021-09-23
        #[deprecated_infallible]
        pub fn raycast(raycast: &RaycastQueryWithOptions) -> RaycastHit;

        #[deprecated(note = "use `spherecast_batched` instead")] // since 2021-09-23
        #[deprecated_infallible]
        pub fn raycast_batched(raycasts: &[RaycastQueryWithOptions], hits: &mut [RaycastHit]);

        pub fn spherecast(raycast: &SpherecastQuery) -> RaycastHit;

        pub fn spherecast_batched(raycasts: &[SpherecastQuery], hits: &mut [RaycastHit]);

        /// Sets the debug name of a data object (useful for debugging data memory usage and leaks etc.)
        #[deprecated_infallible]
        pub fn set_data_debug_name(data: DataHandle, name: &str);

        pub fn get_data_debug_name(data: DataHandle) -> String;

        // An empty slice will mean to apply the options to all entities in the world.
        pub fn set_entity_debug_options(
            entities: &[EntityHandle],
            debug_options: &EntityDebugOptions,
        );

        pub fn set_entity_values(
            entities: &[EntityHandle],
            value_type: EntityValueType,
            data: &[u8],
        );

        pub fn get_entity_values(
            entities: &[EntityHandle],
            value_type: EntityValueType,
            out_data: &mut [u8],
        );

        /// Try setting an entity component parameter value.
        ///
        /// - `entity`: The entity handle that has the component on which the value will be set.
        /// - `component_type`: ([ComponentType][crate::world_v2::ComponentType]): the component that is to be updated.
        /// - `component_param_id`: The component parameter id that specifies which parameter is to be updated.
        /// - `new_component_value`: The new value for the component parameter. This should not contain NaN values.
        /// - `out_error_info`: Error values are written to this enum field. Make sure to allocate enough memory.
        ///
        /// This can fail if an invalid entity handle, component type, parameter id, or value was supplied.
        /// Make sure the entity and component actually exist and use the right value for it.
        pub fn try_set_entity_value(
            entity: EntityHandle,
            component_type: u64,
            component_param_id: u32,
            new_component_value: &Value,
            out_error_info: &mut EntityValueError,
        ) -> FFIResult<()>;

        /// Try fetching an entity component parameter value.
        ///
        /// - `entity`: The entity handle that has the component from which the value will be fetched.
        /// - `component_type` ([`crate::world_v2::ComponentType`]): the component with the field that is to be fetched.
        /// - `component_param_id`: The component parameter id that specifies which parameter is to be fetched.
        /// - `out_component_value`: The returned component parameter value. Make sure to allocate enough memory.
        /// - `out_error_info`: Error values are written to this enum field. Make sure to allocate enough memory.
        ///
        /// This can fail if an invalid entity handle, component type, or parameter id was supplied.
        /// Make sure the entity and component actually exist.
        pub fn try_get_entity_value(
            entity: EntityHandle,
            component_type: u64,
            component_param_id: u32,
            out_component_value: &mut Value,
            out_error_info: &mut EntityValueError,
        ) -> FFIResult<()>;

        /// Measure how large text will be when mesh-generated and rendered. Needed for some layout tasks in sandbox.
        /// Formatting information is embedded in the text with the same encoding as is used for display, so just pass
        /// the string in here.
        pub fn measure_formatted_text(text: DataHandle, size: &mut MeasuredTextSize);

        pub fn get_mesh_section_count(handle: MeshHandle) -> u64;

        pub fn get_mesh_section_dominant_color(
            handle: MeshHandle,
            idx: u64,
        ) -> DominantColorWithArea;

        pub fn get_mesh_section_material_index(handle: MeshHandle, idx: u64) -> u64;
    }
}

pub use world::*;