nightshade-api 0.46.0

Procedural high level API for the nightshade game engine
Documentation
//! # nightshade-api
//!
//! A procedural high level API over the nightshade engine. Write a full 3d
//! scene or a small game as straight-line code with free functions and plain
//! data. No trait to implement, no callbacks to wire up, no ECS knowledge
//! required to get started.
//!
//! A spinning cube:
//!
//! ```ignore
//! use nightshade_api::prelude::*;
//!
//! fn main() {
//!     let mut app = open();
//!     let cube = spawn_cube(&mut app.world, vec3(0.0, 0.5, 0.0));
//!     while frame(&mut app) {
//!         let step = delta_time(&app.world);
//!         rotate(&mut app.world, cube, Vec3::y(), step);
//!     }
//! }
//! ```
//!
//! Add to Cargo.toml:
//!
//! ```toml
//! nightshade-api = "0.46"
//! ```
//!
//! ## What you get for free
//!
//! [`prelude::open`] gives you a window with a sky, a sun with shadows, a
//! reference grid, an orbit camera focused on the origin, prototype textures
//! like `"checkerboard"`, and escape to exit. Every program starts from a lit,
//! navigable scene. Override any of it with one call: [`prelude::set_background`],
//! [`prelude::show_grid`], [`prelude::fly_camera`], [`prelude::set_sun`].
//!
//! ## The two entry points
//!
//! Own the loop (native only). Setup is ordinary code before the loop, state
//! is ordinary locals across loop iterations:
//!
//! ```ignore
//! let mut app = open();
//! let mut score = 0;
//! while frame(&mut app) {
//!     score += 1;
//! }
//! ```
//!
//! Or hand the engine the loop with [`run`](fn@crate::prelude::run), which also works on
//! wasm. Setup returns your state, the update closure receives it back every
//! frame:
//!
//! ```ignore
//! run(
//!     |world| spawn_cube(world, vec3(0.0, 0.5, 0.0)),
//!     |world, cube| {
//!         let step = delta_time(world);
//!         rotate(world, *cube, Vec3::y(), step);
//!     },
//! )
//! .unwrap();
//! ```
//!
//! `run` returns a `Result`, so a real `main` returns it. For several per-frame
//! jobs, the [`run!`](crate::run!) macro takes any number of update systems:
//!
//! ```ignore
//! fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     run!(setup, handle_input, move_player, check_collisions)
//! }
//! ```
//!
//! For immediate-mode UI, enable the `egui` feature, call
//! [`enable_egui`](fn@crate::prelude::enable_egui) once in setup, then draw from
//! your update closure by pulling the frame's context with
//! [`egui_context`](fn@crate::prelude::egui_context). No extra closure: it
//! composes with [`run`](fn@crate::prelude::run) and [`run!`](crate::run!) as is.
//! `egui` is re-exported from the prelude.
//!
//! ```ignore
//! run(
//!     |world| { enable_egui(world); spawn_cube(world, vec3(0.0, 0.5, 0.0)) },
//!     |world, cube| {
//!         rotate(world, *cube, Vec3::y(), delta_time(world));
//!         if let Some(ctx) = egui_context(world) {
//!             egui::Window::new("Inspector").show(&ctx, |ui| ui.label(format!("{cube:?}")));
//!         }
//!     },
//! )
//! .unwrap();
//! ```
//!
//! ## Vocabulary
//!
//! Two verbs carry the lifetime rules. `spawn_` is retained: the thing exists
//! until you [`prelude::despawn`] it. `draw_` is immediate: visible for
//! exactly one frame, redraw it every frame you want it on screen.
//!
//! - Scene content: [`prelude::spawn_cube`], [`prelude::spawn_sphere`],
//!   [`prelude::spawn_floor`], [`prelude::spawn_model`], [`prelude::spawn_object`]
//! - Crowds: [`prelude::spawn_objects`], [`prelude::spawn_instanced`]
//! - Tags: [`prelude::tag`], [`prelude::tagged`], [`prelude::for_each_tagged`]
//! - Looks: [`prelude::set_color`], [`prelude::set_metallic_roughness`],
//!   [`prelude::set_emissive`], [`prelude::set_texture`],
//!   [`prelude::set_normal_texture`]
//! - Placement: [`prelude::set_position`], [`prelude::rotate`], [`prelude::set_scale`],
//!   [`prelude::set_parent`]
//! - Cameras: [`prelude::orbit_camera`], [`prelude::fly_camera`],
//!   [`prelude::first_person`], [`prelude::fixed_camera`],
//!   [`prelude::set_field_of_view`], [`prelude::set_orthographic`]
//! - Input: [`prelude::key_down`], [`prelude::wasd`], [`prelude::mouse_clicked`],
//!   [`prelude::clicked_entity`]
//! - Immediate drawing: [`prelude::draw_cube`], [`prelude::draw_sphere`],
//!   [`prelude::draw_line`]
//! - Text: [`prelude::spawn_text`], [`prelude::set_text`], [`prelude::spawn_label`]
//! - UI: [`prelude::spawn_panel`], [`prelude::panel_button`],
//!   [`prelude::panel_label`], [`prelude::button_clicked`]; plus the full widget
//!   set: [`prelude::panel_data_grid`], [`prelude::panel_tree_view`],
//!   [`prelude::panel_property_grid`], [`prelude::panel_color_picker`],
//!   [`prelude::panel_date_picker`], [`prelude::panel_command_palette`],
//!   [`prelude::panel_modal`], [`prelude::panel_virtual_list`]
//! - Animation: [`prelude::play_animation`], [`prelude::play_animation_named`],
//!   [`prelude::blend_to_animation`], [`prelude::set_animation_speed`]
//! - Post-processing: [`prelude::set_ssao`], [`prelude::set_ssr`],
//!   [`prelude::set_tonemap`], [`prelude::set_color_grading`]
//! - Live physics tuning: [`prelude::set_friction`], [`prelude::set_restitution`],
//!   [`prelude::set_mass`], [`prelude::set_gravity_scale`]
//! - Layout containers: [`prelude::panel_row`], [`prelude::panel_grid`],
//!   [`prelude::panel_scroll`]; world-space UI: [`prelude::spawn_world_panel`]
//! - Animation extras: [`prelude::add_animation_event`],
//!   [`prelude::add_animation_layer`], [`prelude::reach_to`], [`prelude::aim_at`]
//! - Prefabs and undo: [`prelude::make_prefab`], [`prelude::spawn_prefab`],
//!   [`prelude::UndoStack`]
//!
//! ## Reading the scene back
//!
//! The setters have readers, which is what a tool that edits a scene rather than
//! just building one needs. [`prelude::describe_entity`] gathers an entity's
//! whole editable state, [`prelude::get_color`] and friends read one field,
//! [`prelude::scene_tree`] and [`prelude::children`] walk the hierarchy,
//! [`prelude::list_materials`] reads the shared material registry, and
//! [`prelude::bounds_of`] with [`prelude::frame_entities`] measure and frame a
//! selection. [`prelude::save_scene`] and [`prelude::load_scene`] round-trip the
//! whole world to bytes. Components are added, removed, and snapshotted for undo
//! by [`prelude::ComponentKind`], the surface the standalone editor is built on.
//!
//! ## Commands
//!
//! Every call also has a data form. [`prelude::Command`] is a serde enum with
//! one variant per function, [`prelude::submit_command`] runs one, and
//! [`prelude::submit_commands`] runs a batch where a later command can name an
//! entity an earlier one produced with [`prelude::Ref::Result`], so one batch
//! builds and wires up a scene. The enum is the wire format a binding targets:
//! build `Command` values, read [`prelude::CommandReply`] back, with the json
//! schema from [`prelude::command_schema`]. The free functions stay the real
//! implementations and the dispatch forwards to them.
//! See the `commands` example and `docs/COMMAND_API.md`.
//!
//! ## Dropping down to the engine
//!
//! Every function here takes the real engine [`prelude::World`] and bottoms
//! out in normal nightshade calls. Nothing is hidden behind a wrapper type,
//! so when a program outgrows the facade you replace one call site at a time.
//! The full engine is re-exported at [`nightshade`], one path away:
//!
//! ```ignore
//! use nightshade_api::nightshade::prelude::*;
//! ```
//!
//! ## Examples
//!
//! The `examples/` directory is the tour. Run one with
//! `just run-example solar_system` from the repo root, or
//! `cargo run -r -p nightshade-api --example solar_system`. Every example also
//! runs in the browser with `just run-example-wasm solar_system`, which serves
//! it through trunk.

pub use nightshade;

mod animate;
#[cfg(not(target_arch = "wasm32"))]
mod app;
mod appearance;
#[cfg(feature = "audio")]
mod audio;
mod bounds;
mod camera;
#[cfg(feature = "physics")]
mod character;
mod cloth;
mod command;
mod cutscene;
mod decals;
mod draw;
#[cfg(feature = "scripting")]
mod dynamic_de;
#[cfg(feature = "protocol")]
pub mod editor;
mod effects;
mod environment;
mod events;
mod filesystem;
mod groups;
mod hierarchy;
mod input;
mod inspect;
mod lighting;
mod materials;
mod mesh;
mod messaging;
mod morph;
#[cfg(feature = "navmesh")]
mod navigation;
#[cfg(all(feature = "net", not(target_arch = "wasm32")))]
mod net;
mod palette;
#[cfg(feature = "physics")]
mod physics;
#[cfg(feature = "picking")]
mod picking;
mod placement;
mod prefab;
mod reflect;
mod render;
mod runner;
mod scene;
#[cfg(feature = "scripting")]
mod scripting;
mod serialize;
#[cfg(any(feature = "terrain", feature = "grass"))]
mod terrain;
mod text;
mod ui;
mod undo;
mod window;
#[cfg(feature = "picking")]
mod world_ui;

/// Everything in one import.
///
/// ```ignore
/// use nightshade_api::prelude::*;
/// ```
///
/// Pulls in the full api surface plus the engine types it hands you:
/// [`World`](crate::prelude::World), [`Entity`](crate::prelude::Entity), the math types, [`KeyCode`](crate::prelude::KeyCode), and [`MouseButton`](crate::prelude::MouseButton).
pub mod prelude {
    pub use crate::animate::*;
    #[cfg(not(target_arch = "wasm32"))]
    pub use crate::app::{App, Window, frame, open, open_with, render_image};
    pub use crate::appearance::*;
    #[cfg(feature = "audio")]
    pub use crate::audio::*;
    pub use crate::bounds::*;
    pub use crate::camera::*;
    #[cfg(feature = "physics")]
    pub use crate::character::*;
    pub use crate::cloth::*;
    pub use crate::command::*;
    pub use crate::cutscene::*;
    pub use crate::decals::*;
    pub use crate::draw::*;
    pub use crate::effects::*;
    pub use crate::environment::*;
    pub use crate::events::*;
    pub use crate::filesystem::*;
    pub use crate::groups::*;
    pub use crate::hierarchy::*;
    pub use crate::input::*;
    pub use crate::inspect::*;
    pub use crate::lighting::*;
    pub use crate::materials::*;
    pub use crate::mesh::*;
    pub use crate::messaging::*;
    pub use crate::morph::*;
    #[cfg(feature = "navmesh")]
    pub use crate::navigation::*;
    #[cfg(all(feature = "net", not(target_arch = "wasm32")))]
    pub use crate::net::*;
    pub use crate::palette::*;
    #[cfg(feature = "physics")]
    pub use crate::physics::*;
    #[cfg(feature = "picking")]
    pub use crate::picking::*;
    pub use crate::placement::*;
    pub use crate::prefab::*;
    pub use crate::reflect::*;
    pub use crate::render::*;
    pub use crate::run;
    pub use crate::runner::{run, run_scene, systems};
    pub use crate::scene::*;
    #[cfg(feature = "scripting")]
    pub use crate::scripting::*;
    pub use crate::serialize::*;
    #[cfg(any(feature = "terrain", feature = "grass"))]
    pub use crate::terrain::*;
    pub use crate::text::*;
    pub use crate::ui::*;
    pub use crate::undo::*;
    pub use crate::window::*;
    #[cfg(feature = "picking")]
    pub use crate::world_ui::*;
    pub use nightshade::ecs::material::components::Material;
    pub use nightshade::ecs::particles::components::ParticleEmitter;
    #[cfg(feature = "navmesh")]
    pub use nightshade::prelude::RecastNavMeshConfig;
    #[cfg(feature = "egui")]
    pub use nightshade::prelude::{egui, egui_context};

    pub use nightshade::ecs::graphics::resources::DepthOfField;
    #[cfg(feature = "physics")]
    pub use nightshade::ecs::physics::joints::{
        FixedJoint, JointAxisDirection, JointHandle, RevoluteJoint, RopeJoint, SpringJoint,
    };
    #[cfg(feature = "physics")]
    pub use nightshade::prelude::{CollisionEvent, RaycastHit};
    pub use nightshade::prelude::{
        EasingFunction, Entity, Fog, InstanceTransform, KeyCode, Line, MouseButton, ShadingMode,
        TextAlignment, Vec2, Vec3, Vec4, VerticalAlignment, ViewportShading, World, nalgebra_glm,
        vec2, vec3, vec4,
    };
}