nightshade-api 0.53.0

Procedural high level API for the nightshade game engine
Documentation
//! Animation depth: clip listing, named blending, playback control, additive
//! layers driven by a slider, and inverse kinematics (reach_to / aim_at) on
//! plain parented primitives that need no rig.

use nightshade_api::prelude::*;

struct State {
    fox: Entity,
    root: Entity,
    mid: Entity,
    tip: Entity,
    turret: Entity,
    slider: Entity,
    layer: Option<usize>,
}

fn main() {
    run(
        |world| {
            set_background(world, Background::Sky);
            show_grid(world, true);
            spawn_floor(world, 10.0);

            let fox = spawn_model(
                world,
                include_bytes!("../../../assets/gltf/fox.glb"),
                vec3(-2.0, 0.0, 0.0),
            );
            set_scale(world, fox, vec3(0.02, 0.02, 0.02));
            play_animation(world, fox, 0);
            set_animation_looping(world, fox, true);
            set_animation_speed(world, fox, 1.0);
            let layer = add_animation_layer(world, fox, 1, 0.5);

            let clips = animation_clips(world, fox);
            spawn_text(
                world,
                &format!("clips: {}", clips.join(", ")),
                ScreenAnchor::TopLeft,
            );
            spawn_text(
                world,
                "1 walk  2 run  3 survey  P pause  R resume  X stop  C clear layers",
                ScreenAnchor::BottomLeft,
            );

            let root = spawn_cube(world, vec3(2.0, 0.5, 0.0));
            set_scale(world, root, vec3(0.2, 0.6, 0.2));
            set_color(world, root, TEAL);
            let mid = spawn_cube(world, vec3(2.0, 1.5, 0.0));
            set_scale(world, mid, vec3(0.2, 0.6, 0.2));
            set_color(world, mid, GREEN);
            let tip = spawn_cube(world, vec3(2.0, 2.5, 0.0));
            set_scale(world, tip, vec3(0.2, 0.6, 0.2));
            set_color(world, tip, GOLD);
            set_parent(world, mid, Some(root));
            set_parent(world, tip, Some(mid));

            let turret = spawn_cube(world, vec3(4.0, 0.5, 0.0));
            set_color(world, turret, RED);

            let panel = spawn_panel(world, ScreenAnchor::TopRight, 220.0, 80.0);
            let slider = panel_slider(world, panel, 0.0, 1.0, 0.5);

            orbit_camera(world, vec3(1.0, 1.0, 0.0), 9.0);
            State {
                fox,
                root,
                mid,
                tip,
                turret,
                slider,
                layer,
            }
        },
        |world, state| {
            let time = elapsed_seconds(world);
            let target = vec3(
                2.0 + time.cos() * 1.2,
                1.8 + time.sin() * 0.8,
                time.sin() * 1.2,
            );
            reach_to(world, state.root, state.mid, state.tip, target, None);
            aim_at(world, state.turret, target, Vec3::z());

            if key_pressed(world, KeyCode::Digit1)
                && !blend_to_animation_named(world, state.fox, "Walk", 0.3)
            {
                play_animation(world, state.fox, 0);
            }
            if key_pressed(world, KeyCode::Digit2) {
                if !blend_to_animation_named(world, state.fox, "Run", 0.3) {
                    play_animation(world, state.fox, 0);
                }
                set_animation_speed(world, state.fox, 1.5);
            }
            if key_pressed(world, KeyCode::Digit3)
                && !blend_to_animation_named(world, state.fox, "Survey", 0.3)
            {
                play_animation(world, state.fox, 0);
            }
            if key_pressed(world, KeyCode::KeyP) {
                pause_animation(world, state.fox);
            }
            if key_pressed(world, KeyCode::KeyR) {
                resume_animation(world, state.fox);
            }
            if key_pressed(world, KeyCode::KeyX) {
                stop_animation(world, state.fox);
            }
            if key_pressed(world, KeyCode::KeyC) {
                clear_animation_layers(world, state.fox);
            }
            if let Some(layer) = state.layer {
                let weight = slider_value(world, state.slider);
                set_animation_layer_weight(world, state.fox, layer, weight);
            }
            if morph_target_count(world, state.fox) > 0 {
                set_morph_weights(world, state.fox, &[0.5]);
            }
        },
    )
    .unwrap();
}