nightshade-api 0.40.0

Procedural high level API for the nightshade game engine
Documentation
//! Move, rotate, and scale entities without touching quaternions or dirty
//! flags.

use nightshade::prelude::nalgebra_glm::Mat4;
use nightshade::prelude::*;

/// Sets the entity's position in its parent's space (world space when it has
/// no parent).
#[inline]
pub fn set_position(world: &mut World, entity: Entity, position: Vec3) {
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.translation = position;
    }
}

/// Sets the entity's scale.
#[inline]
pub fn set_scale(world: &mut World, entity: Entity, scale: Vec3) {
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.scale = scale;
    }
}

/// Replaces the entity's rotation with `radians` around `axis`.
#[inline]
pub fn set_rotation(world: &mut World, entity: Entity, axis: Vec3, radians: f32) {
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.rotation = nalgebra_glm::quat_angle_axis(radians, &axis.normalize());
    }
}

/// Rotates the entity by `radians` around `axis` on top of its current
/// rotation. Call every frame with a delta for a steady spin.
#[inline]
pub fn rotate(world: &mut World, entity: Entity, axis: Vec3, radians: f32) {
    if let Some(transform) = mutate_local_transform(world, entity) {
        transform.rotation =
            nalgebra_glm::quat_angle_axis(radians, &axis.normalize()) * transform.rotation;
    }
}

/// The entity's position in world space, correct even before the engine's
/// transform propagation has run for the frame.
pub fn position(world: &World, entity: Entity) -> Vec3 {
    let matrix = world_matrix(world, entity);
    nalgebra_glm::vec3(matrix[(0, 3)], matrix[(1, 3)], matrix[(2, 3)])
}

pub(crate) fn local_matrix(transform: &LocalTransform) -> Mat4 {
    nalgebra_glm::translation(&transform.translation)
        * nalgebra_glm::quat_to_mat4(&transform.rotation)
        * nalgebra_glm::scaling(&transform.scale)
}

pub(crate) fn world_matrix(world: &World, entity: Entity) -> Mat4 {
    let matrix = world
        .core
        .get_local_transform(entity)
        .map(local_matrix)
        .unwrap_or_else(Mat4::identity);
    match world.core.get_parent(entity).and_then(|parent| parent.0) {
        Some(parent_entity) => world_matrix(world, parent_entity) * matrix,
        None => matrix,
    }
}