Skip to main content

nightshade_api/
lib.rs

1//! # nightshade-api
2//!
3//! A procedural high level API over the nightshade engine. Write a full 3d
4//! scene or a small game as straight-line code with free functions and plain
5//! data. No trait to implement, no callbacks to wire up, no ECS knowledge
6//! required to get started.
7//!
8//! A spinning cube:
9//!
10//! ```ignore
11//! use nightshade_api::prelude::*;
12//!
13//! fn main() {
14//!     let mut app = open();
15//!     let cube = spawn_cube(&mut app.world, vec3(0.0, 0.5, 0.0));
16//!     while frame(&mut app) {
17//!         let step = delta_time(&app.world);
18//!         rotate(&mut app.world, cube, Vec3::y(), step);
19//!     }
20//! }
21//! ```
22//!
23//! Add to Cargo.toml:
24//!
25//! ```toml
26//! nightshade-api = "0.44"
27//! ```
28//!
29//! ## What you get for free
30//!
31//! [`prelude::open`] gives you a window with a sky, a sun with shadows, a
32//! reference grid, an orbit camera focused on the origin, prototype textures
33//! like `"checkerboard"`, and escape to exit. Every program starts from a lit,
34//! navigable scene. Override any of it with one call: [`prelude::set_background`],
35//! [`prelude::show_grid`], [`prelude::fly_camera`], [`prelude::set_sun`].
36//!
37//! ## The two entry points
38//!
39//! Own the loop (native only). Setup is ordinary code before the loop, state
40//! is ordinary locals across loop iterations:
41//!
42//! ```ignore
43//! let mut app = open();
44//! let mut score = 0;
45//! while frame(&mut app) {
46//!     score += 1;
47//! }
48//! ```
49//!
50//! Or hand the engine the loop with [`prelude::run`], which also works on
51//! wasm. Setup returns your state, the update closure receives it back every
52//! frame:
53//!
54//! ```ignore
55//! run(
56//!     |world| spawn_cube(world, vec3(0.0, 0.5, 0.0)),
57//!     |world, cube| {
58//!         let step = delta_time(world);
59//!         rotate(world, *cube, Vec3::y(), step);
60//!     },
61//! )
62//! .unwrap();
63//! ```
64//!
65//! `run` returns a `Result`, so a real `main` returns it. For several per-frame
66//! jobs, the [`run!`](crate::run) macro takes any number of update systems:
67//!
68//! ```ignore
69//! fn main() -> Result<(), Box<dyn std::error::Error>> {
70//!     run!(setup, handle_input, move_player, check_collisions)
71//! }
72//! ```
73//!
74//! ## Vocabulary
75//!
76//! Two verbs carry the lifetime rules. `spawn_` is retained: the thing exists
77//! until you [`prelude::despawn`] it. `draw_` is immediate: visible for
78//! exactly one frame, redraw it every frame you want it on screen.
79//!
80//! - Scene content: [`prelude::spawn_cube`], [`prelude::spawn_sphere`],
81//!   [`prelude::spawn_floor`], [`prelude::spawn_model`], [`prelude::spawn_object`]
82//! - Crowds: [`prelude::spawn_objects`], [`prelude::spawn_instanced`]
83//! - Tags: [`prelude::tag`], [`prelude::tagged`], [`prelude::for_each_tagged`]
84//! - Looks: [`prelude::set_color`], [`prelude::set_metallic_roughness`],
85//!   [`prelude::set_emissive`], [`prelude::set_texture`],
86//!   [`prelude::set_normal_texture`]
87//! - Placement: [`prelude::set_position`], [`prelude::rotate`], [`prelude::set_scale`],
88//!   [`prelude::set_parent`]
89//! - Cameras: [`prelude::orbit_camera`], [`prelude::fly_camera`],
90//!   [`prelude::first_person`], [`prelude::fixed_camera`],
91//!   [`prelude::set_field_of_view`], [`prelude::set_orthographic`]
92//! - Input: [`prelude::key_down`], [`prelude::wasd`], [`prelude::mouse_clicked`],
93//!   [`prelude::clicked_entity`]
94//! - Immediate drawing: [`prelude::draw_cube`], [`prelude::draw_sphere`],
95//!   [`prelude::draw_line`]
96//! - Text: [`prelude::spawn_text`], [`prelude::set_text`], [`prelude::spawn_label`]
97//! - UI: [`prelude::spawn_panel`], [`prelude::panel_button`],
98//!   [`prelude::panel_label`], [`prelude::button_clicked`]
99//! - Animation: [`prelude::play_animation`], [`prelude::play_animation_named`],
100//!   [`prelude::blend_to_animation`], [`prelude::set_animation_speed`]
101//! - Post-processing: [`prelude::set_ssao`], [`prelude::set_ssr`],
102//!   [`prelude::set_tonemap`], [`prelude::set_color_grading`]
103//! - Live physics tuning: [`prelude::set_friction`], [`prelude::set_restitution`],
104//!   [`prelude::set_mass`], [`prelude::set_gravity_scale`]
105//! - Layout containers: [`prelude::panel_row`], [`prelude::panel_grid`],
106//!   [`prelude::panel_scroll`]; world-space UI: [`prelude::spawn_world_panel`]
107//! - Animation extras: [`prelude::add_animation_event`],
108//!   [`prelude::add_animation_layer`], [`prelude::reach_to`], [`prelude::aim_at`]
109//! - Prefabs and undo: [`prelude::make_prefab`], [`prelude::spawn_prefab`],
110//!   [`prelude::UndoStack`]
111//!
112//! ## Reading the scene back
113//!
114//! The setters have readers, which is what a tool that edits a scene rather than
115//! just building one needs. [`prelude::describe_entity`] gathers an entity's
116//! whole editable state, [`prelude::get_color`] and friends read one field,
117//! [`prelude::scene_tree`] and [`prelude::children`] walk the hierarchy,
118//! [`prelude::list_materials`] reads the shared material registry, and
119//! [`prelude::bounds_of`] with [`prelude::frame_entities`] measure and frame a
120//! selection. [`prelude::save_scene`] and [`prelude::load_scene`] round-trip the
121//! whole world to bytes. Components are added, removed, and snapshotted for undo
122//! by [`prelude::ComponentKind`], the surface the standalone editor is built on.
123//!
124//! ## Commands
125//!
126//! Every call also has a data form. [`prelude::Command`] is a serde enum with
127//! one variant per function, [`prelude::submit_command`] runs one, and
128//! [`prelude::submit_commands`] runs a batch where a later command can name an
129//! entity an earlier one produced with [`prelude::Ref::Result`], so one batch
130//! builds and wires up a scene. The enum is the wire format a binding targets:
131//! build `Command` values, read [`prelude::CommandReply`] back, with the json
132//! schema from [`prelude::command_schema`]. The free functions stay the real
133//! implementations and the dispatch forwards to them.
134//! See the `commands` example and `docs/COMMAND_API.md`.
135//!
136//! ## Dropping down to the engine
137//!
138//! Every function here takes the real engine [`prelude::World`] and bottoms
139//! out in normal nightshade calls. Nothing is hidden behind a wrapper type,
140//! so when a program outgrows the facade you replace one call site at a time.
141//! The full engine is re-exported at [`nightshade`], one path away:
142//!
143//! ```ignore
144//! use nightshade_api::nightshade::prelude::*;
145//! ```
146//!
147//! ## Examples
148//!
149//! The `examples/` directory is the tour. Run one with
150//! `just run-example solar_system` from the repo root, or
151//! `cargo run -r -p nightshade-api --example solar_system`. Every example also
152//! runs in the browser with `just run-example-wasm solar_system`, which serves
153//! it through trunk.
154
155pub use nightshade;
156
157mod animate;
158#[cfg(not(target_arch = "wasm32"))]
159mod app;
160mod appearance;
161#[cfg(feature = "audio")]
162mod audio;
163mod bounds;
164mod camera;
165#[cfg(feature = "physics")]
166mod character;
167mod cloth;
168mod command;
169mod cutscene;
170mod decals;
171mod draw;
172#[cfg(feature = "protocol")]
173pub mod editor;
174mod effects;
175mod environment;
176mod events;
177mod groups;
178mod hierarchy;
179mod input;
180mod inspect;
181mod lighting;
182mod materials;
183mod mesh;
184mod messaging;
185mod morph;
186#[cfg(feature = "navmesh")]
187mod navigation;
188#[cfg(all(feature = "net", not(target_arch = "wasm32")))]
189mod net;
190mod palette;
191#[cfg(feature = "physics")]
192mod physics;
193#[cfg(feature = "picking")]
194mod picking;
195mod placement;
196mod prefab;
197mod reflect;
198mod render;
199mod runner;
200mod scene;
201#[cfg(feature = "scripting")]
202mod scripting;
203mod serialize;
204#[cfg(any(feature = "terrain", feature = "grass"))]
205mod terrain;
206mod text;
207mod ui;
208mod undo;
209mod window;
210#[cfg(feature = "picking")]
211mod world_ui;
212
213/// Everything in one import.
214///
215/// ```ignore
216/// use nightshade_api::prelude::*;
217/// ```
218///
219/// Pulls in the full api surface plus the engine types it hands you:
220/// [`World`], [`Entity`], the math types, [`KeyCode`], and [`MouseButton`].
221pub mod prelude {
222    pub use crate::animate::*;
223    #[cfg(not(target_arch = "wasm32"))]
224    pub use crate::app::{App, Window, frame, open, open_with, render_image};
225    pub use crate::appearance::*;
226    #[cfg(feature = "audio")]
227    pub use crate::audio::*;
228    pub use crate::bounds::*;
229    pub use crate::camera::*;
230    #[cfg(feature = "physics")]
231    pub use crate::character::*;
232    pub use crate::cloth::*;
233    pub use crate::command::*;
234    pub use crate::cutscene::*;
235    pub use crate::decals::*;
236    pub use crate::draw::*;
237    pub use crate::effects::*;
238    pub use crate::environment::*;
239    pub use crate::events::*;
240    pub use crate::groups::*;
241    pub use crate::hierarchy::*;
242    pub use crate::input::*;
243    pub use crate::inspect::*;
244    pub use crate::lighting::*;
245    pub use crate::materials::*;
246    pub use crate::mesh::*;
247    pub use crate::messaging::*;
248    pub use crate::morph::*;
249    #[cfg(feature = "navmesh")]
250    pub use crate::navigation::*;
251    #[cfg(all(feature = "net", not(target_arch = "wasm32")))]
252    pub use crate::net::*;
253    pub use crate::palette::*;
254    #[cfg(feature = "physics")]
255    pub use crate::physics::*;
256    #[cfg(feature = "picking")]
257    pub use crate::picking::*;
258    pub use crate::placement::*;
259    pub use crate::prefab::*;
260    pub use crate::reflect::*;
261    pub use crate::render::*;
262    pub use crate::run;
263    pub use crate::runner::{run, run_scene, systems};
264    pub use crate::scene::*;
265    #[cfg(feature = "scripting")]
266    pub use crate::scripting::*;
267    pub use crate::serialize::*;
268    #[cfg(any(feature = "terrain", feature = "grass"))]
269    pub use crate::terrain::*;
270    pub use crate::text::*;
271    pub use crate::ui::*;
272    pub use crate::undo::*;
273    pub use crate::window::*;
274    #[cfg(feature = "picking")]
275    pub use crate::world_ui::*;
276
277    pub use nightshade::ecs::graphics::resources::DepthOfField;
278    #[cfg(feature = "physics")]
279    pub use nightshade::ecs::physics::joints::{
280        FixedJoint, JointAxisDirection, JointHandle, RevoluteJoint, RopeJoint, SpringJoint,
281    };
282    #[cfg(feature = "physics")]
283    pub use nightshade::prelude::{CollisionEvent, RaycastHit};
284    pub use nightshade::prelude::{
285        EasingFunction, Entity, Fog, InstanceTransform, KeyCode, Line, MouseButton, ShadingMode,
286        TextAlignment, Vec2, Vec3, Vec4, VerticalAlignment, ViewportShading, World, nalgebra_glm,
287        vec2, vec3, vec4,
288    };
289}