khora_sdk/lib.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! The public-facing Software Development Kit (SDK) for the Khora Engine.
16//!
17//! This is the **only** crate that should be used by game developers.
18//! All internal crates (khora-agents, khora-control, etc.) are implementation details.
19//!
20//! # Examples
21//!
22//! A minimal game is an [`EngineApp`] handed to [`run_winit`]. The SDK owns the
23//! engine loop; your type owns the game logic. Everything you need for game code
24//! is in [`prelude`].
25//!
26//! ```rust,no_run
27//! use khora_sdk::prelude::*;
28//! use khora_sdk::prelude::math::Vec3;
29//! use khora_sdk::{
30//! run_winit, AgentProvider, DccService, EngineApp, GameWorld, PhaseProvider,
31//! Runtime, Vessel, WindowConfig,
32//! };
33//! use khora_sdk::winit_adapters::WinitWindowProvider;
34//!
35//! struct MyGame;
36//!
37//! impl EngineApp for MyGame {
38//! fn window_config() -> WindowConfig {
39//! WindowConfig { title: "My Game".into(), ..WindowConfig::default() }
40//! }
41//! fn new() -> Self {
42//! MyGame
43//! }
44//! fn setup(&mut self, world: &mut GameWorld, _runtime: &Runtime) {
45//! // Spawn a camera looking down the -Z axis.
46//! let camera = ecs::Camera::new_perspective(
47//! std::f32::consts::FRAC_PI_4,
48//! 16.0 / 9.0,
49//! 0.1,
50//! 1000.0,
51//! );
52//! Vessel::at(world, Vec3::new(0.0, 2.0, 10.0))
53//! .with_component(camera)
54//! .build();
55//! }
56//! fn update(&mut self, _world: &mut GameWorld, _inputs: &[InputEvent]) {}
57//! }
58//!
59//! // `AgentProvider` / `PhaseProvider` are required super-traits; the default
60//! // (no custom agents, no custom phases) is enough for most games.
61//! impl AgentProvider for MyGame {
62//! fn register_agents(&self, _dcc: &DccService, _runtime: &mut Runtime) {}
63//! }
64//! impl PhaseProvider for MyGame {}
65//!
66//! fn main() -> anyhow::Result<()> {
67//! run_winit::<WinitWindowProvider, MyGame>(|_window, _runtime, _event_loop| {
68//! // Wire backends (renderer, physics, audio, …) into `_runtime` here.
69//! })
70//! }
71//! ```
72
73#![warn(missing_docs)]
74
75mod engine;
76mod game_world;
77mod run_default;
78mod traits;
79mod vessel;
80pub mod winit_adapters;
81
82pub use engine::EngineCore;
83pub use game_world::GameWorld;
84pub use run_default::run_default;
85pub use traits::{AgentProvider, EngineApp, PhaseProvider, WindowProvider};
86pub use vessel::{spawn_cube_at, spawn_plane, spawn_sphere, Vessel};
87pub use winit_adapters::{run_winit, WinitAppRunner};
88
89// Re-export window provider for convenience
90pub use winit_adapters::WinitWindowProvider;
91
92// ─────────────────────────────────────────────────────────────────────
93// Editor UI re-exports — so editor panels can import from SDK only
94// ─────────────────────────────────────────────────────────────────────
95pub mod editor_ui {
96 //! Editor UI types re-exported from khora_core.
97 //!
98 //! Includes everything from `khora_core::ui::editor::*` plus the
99 //! shared `UiTheme` and font types that live one level up in
100 //! `khora_core::ui` (because the hub uses them too).
101 pub use khora_core::ui::editor::*;
102 pub use khora_core::ui::fonts::{FontHandle, FontPack, NamedFont};
103 pub use khora_core::ui::theme::UiTheme;
104}
105
106pub mod tool_ui {
107 //! UI surface for standalone Khora tools (the hub, future asset
108 //! cookers, …).
109 //!
110 //! These tools depend on `khora-sdk` and reach the egui backend
111 //! exclusively through this module — never directly via `egui`
112 //! or `eframe`. The day the engine swaps backend, this re-export
113 //! list moves to whichever crate provides the new
114 //! [`run_native`] + [`AppContext`] implementation.
115 //!
116 //! This module is the **runtime** seam only. Khora's *look* — the brand
117 //! palette and the shared widget vocabulary — is cosmetics and lives in
118 //! the separate `khora-tool-ui` crate, which the SDK deliberately does
119 //! **not** depend on, so a game built on Khora never compiles the engine
120 //! vendor's brand. Tools depend on both.
121
122 pub use khora_core::math::{LinearRgba, Rect2D, Vec2};
123 pub use khora_core::ui::editor::{
124 FontFamilyHint, Icon, InlineEditEvent, Interaction, TextAlign,
125 };
126 pub use khora_core::ui::{
127 Align, Align2, App, AppContext, AppLifecycle, CornerRadius, FontHandle, FontPack, Margin,
128 NamedFont, Stroke, UiBuilder, UiTheme,
129 };
130 pub use khora_infra::ui::egui::app::{run_native, WindowConfigInput, WindowIconInput};
131}
132
133// ─────────────────────────────────────────────────────────────────────
134// Re-exports from internal crates — the SDK is the single entry point
135// ─────────────────────────────────────────────────────────────────────
136
137// Control / DCC
138pub use khora_control::{Context as EngineContext, DccConfig, DccService, EngineMode};
139// Re-export the same Context as `DccContext` so editor code can use the
140// more descriptive name without a separate `use` line. (Same type — both
141// re-exports point at `khora_control::Context`.)
142//
143// `AgentRegistry` is exposed as a read-only telemetry surface for the
144// editor's Control Plane panel. The mutating side (`ExecutionScheduler`,
145// `BudgetChannel`, `EnginePlugin`) stays internal — the SDK is a façade
146// for game code, not for engine internals.
147pub use khora_control::registry::AgentRegistry;
148pub use khora_control::Context as DccContext;
149
150// Core types
151pub use khora_core::agent::{AgentImportance, ExecutionPhase, ExecutionTiming};
152pub use khora_core::control::gorna::{AgentHints, AgentId, AgentStatus, EngineHint, StrategyId};
153pub use khora_core::telemetry::{MonitoredResourceType, TelemetryEvent};
154pub use khora_core::ui::editor::generate_selection_gizmos;
155pub use khora_core::ui::editor::gizmo::GizmoKind;
156pub use khora_core::ui::editor::gizmo::GizmoLineInstance;
157pub use khora_core::ui::editor::viewport_texture::ViewportTextureHandle;
158pub use khora_core::ui::editor::{
159 AssetEntry, CommandHistory, ComponentJson, EditorCamera, EditorCommand, EditorLogCapture,
160 EditorMode, EditorPanel, EditorShell, EditorState, EntityIcon, FontFamilyHint, GizmoMode, Icon,
161 InspectedEntity, Interaction, LogEntry, LogLevel, PanelLocation, PlayMode, PropertyEdit,
162 SceneNode, StatusBarData, TextAlign, UiBuilder,
163};
164pub use khora_core::ui::fonts::{FontHandle, FontPack, NamedFont};
165pub use khora_core::ui::theme::UiTheme;
166pub use khora_core::{Backends, Resources, Runtime, Services};
167
168// Telemetry service
169pub use khora_telemetry::MonitorRegistry;
170pub use khora_telemetry::TelemetryService;
171// AgentRegistry is already re-exported above (line 51) via
172// `pub use khora_control::registry::AgentRegistry`.
173
174// Infra / monitors
175pub use khora_infra::telemetry::memory_monitor::MemoryMonitor;
176pub use khora_infra::GpuMonitor;
177
178// I/O
179pub use khora_core::asset::AssetSource;
180pub use khora_core::scene::{SceneFile, SerializationGoal};
181pub use khora_data::assets::SoundData;
182pub use khora_io;
183pub use khora_io::asset::decoders::audio::SymphoniaDecoder;
184pub use khora_io::asset::{
185 AssetChangeEvent, AssetChangeKind, AssetIdRegistry, AssetIo, AssetService, AssetWatcher,
186 AssetWriter, FileLoader, FileSystemResolver, IndexBuilder, MeshDispatcher, PackBuilder,
187 PackHeader, PackLoader, PackOutput, PackProgress, PACK_FORMAT_VERSION, PACK_HEADER_SIZE,
188 PACK_MAGIC,
189};
190pub use khora_io::serialization::SerializationService;
191pub use khora_telemetry::MetricsRegistry;
192
193// Mesh type (used by editor ops)
194pub use khora_core::renderer::api::scene::mesh::Mesh;
195
196// Scene environment — selects the equirectangular map the IBL bake projects
197// onto the environment cube (absent ⇒ the procedural sky is baked instead).
198pub use khora_data::EnvironmentMap;
199
200/// Renderer sub-modules (used by editor gizmo)
201pub mod renderer {
202 pub use khora_core::renderer::api::resource;
203 pub use khora_core::renderer::api::scene;
204 pub use khora_core::renderer::light;
205}
206
207// WgpuRenderSystem (used by editor main)
208pub use khora_infra::WgpuRenderSystem;
209
210// Backend implementations and their traits — apps insert these into
211// `Runtime::backends` / `Runtime::resources` during the `run_winit`
212// bootstrap closure to wire the engine to its physics, layout, text and
213// audio backends.
214pub use khora_core::audio::{AudioDevice, AudioMixBus, AudioStream, DefaultMixBus, StreamInfo};
215pub use khora_core::physics::PhysicsProvider;
216pub use khora_core::renderer::api::text::TextRenderer;
217pub use khora_core::renderer::traits::PipelineSystem;
218pub use khora_core::ui::LayoutSystem;
219pub use khora_infra::audio::backends::cpal::CpalAudioDevice;
220pub use khora_infra::graphics::WgpuPipelineSystem;
221pub use khora_infra::physics::rapier::RapierPhysicsWorld;
222pub use khora_infra::renderer::StandardTextRenderer;
223pub use khora_infra::ui::TaffyLayoutSystem;
224pub use khora_lanes::render_lane::shaders::TEXT_WGSL;
225
226// Data / ECS (needed for world restore)
227pub use khora_data;
228pub use khora_data::ecs::World as EcsWorld;
229
230// Re-export types used by editor panels and gizmo code
231pub use khora_core;
232pub use khora_core::math::Mat4;
233pub use khora_core::renderer::traits::RenderSystem;
234pub use khora_data::ecs::HandleComponent;
235
236// PropertyEdit is in khora_core::ui::editor, already re-exported via editor_ui
237pub use khora_data::scene::ComponentRegistration;
238pub use khora_data::scene::{instantiate_subtree, serialize_subtree};
239
240// Agents (for when apps need to create their own)
241pub use khora_agents;
242
243// Lanes — re-exported so the editor can reach built-in shaders without
244// taking a direct dependency on khora-lanes.
245pub use khora_lanes;
246
247// Winit — re-exported so the editor can downcast the opaque `&dyn Any`
248// `event_loop` argument passed to the `run_winit` bootstrap closure.
249pub use winit;
250
251// Re-export inventory for editor
252pub extern crate inventory;
253
254pub mod prelude {
255 //! Common imports for game development.
256 //!
257 //! Glob-import this module to bring the everyday game-dev types into scope:
258 //! input ([`InputEvent`], [`KeyCode`], [`MouseButton`]), timing
259 //! ([`Time`], [`SharedTime`]), assets ([`AssetHandle`], [`AssetUUID`]), and
260 //! the [`ecs`], [`materials`], and [`math`] sub-modules. The window config
261 //! types [`WindowConfig`] and [`WindowIcon`] come along too.
262 //!
263 //! # Examples
264 //!
265 //! ```rust
266 //! use khora_sdk::prelude::*;
267 //! use khora_sdk::prelude::math::Vec3;
268 //!
269 //! // ECS components, math, and materials are all reachable through the prelude.
270 //! let _transform = ecs::Transform::from_translation(Vec3::new(0.0, 1.0, 0.0));
271 //! let _material = materials::StandardMaterial::default();
272 //! let _red = math::LinearRgba::RED;
273 //! ```
274
275 // SDK types
276 pub use crate::{WindowConfig, WindowIcon, PRIMARY_VIEWPORT};
277
278 // Assets
279 pub use khora_core::asset::{AssetHandle, AssetUUID};
280
281 // Memory tracking (for `#[global_allocator]`)
282 pub use khora_core::memory::SaaTrackingAllocator;
283
284 // Input
285 pub use khora_core::platform::{InputEvent, KeyCode, MouseButton};
286
287 // Per-frame timing — real frame delta, fixed sim step, interpolation alpha.
288 // `SharedTime` is the interior-mutable handle to cache in `setup` and read
289 // each frame in `update`.
290 pub use khora_core::time::{SharedTime, Time};
291
292 // ECS types
293 pub mod ecs {
294 //! Core ECS types for game logic.
295 pub use khora_core::ecs::entity::EntityId;
296 pub use khora_core::physics::{BodyType, ColliderShape};
297 pub use khora_core::renderer::light::{DirectionalLight, LightType, PointLight, SpotLight};
298 pub use khora_data::ecs::{
299 AudioSource, Camera, Children, Collider, Component, ComponentBundle, GlobalTransform,
300 Light, MaterialRef, MeshRef, Name, Parent, ProceduralMeshKind, ProjectionType,
301 RigidBody, Tag, Transform, Without,
302 };
303 }
304
305 // Materials
306 pub mod materials {
307 //! Built-in material types.
308 //!
309 //! [`AlphaMode`] is re-exported alongside them because it is the type of
310 //! `StandardMaterial::alpha_mode`: without it a game could not select
311 //! masked or blended transparency through the SDK.
312 pub use khora_core::asset::{
313 AlphaMode, EmissiveMaterial, StandardMaterial, UnlitMaterial, WireframeMaterial,
314 };
315 }
316
317 // Math
318 pub mod math {
319 //! Math types and utilities.
320 pub use khora_core::math::LinearRgba;
321 pub use khora_core::math::*;
322 }
323}
324
325// Re-export InputEvent at crate level for trait usage
326pub use khora_core::platform::{InputEvent, KeyCode, MouseButton};
327
328/// Well-known viewport handle for the primary 3D viewport.
329pub const PRIMARY_VIEWPORT: ViewportTextureHandle = ViewportTextureHandle(0);
330
331/// Raw window icon data for native window creation.
332#[derive(Clone, Debug)]
333pub struct WindowIcon {
334 /// RGBA8 pixel buffer stored row-major.
335 pub rgba: Vec<u8>,
336 /// Icon width in pixels.
337 pub width: u32,
338 /// Icon height in pixels.
339 pub height: u32,
340}
341
342/// Window configuration for applications.
343#[derive(Clone, Debug)]
344pub struct WindowConfig {
345 /// Window title shown by the platform window manager.
346 pub title: String,
347 /// Initial window width in pixels.
348 pub width: u32,
349 /// Initial window height in pixels.
350 pub height: u32,
351 /// Optional custom window icon.
352 pub icon: Option<WindowIcon>,
353}
354
355impl Default for WindowConfig {
356 fn default() -> Self {
357 Self {
358 title: "Khora Engine".to_owned(),
359 width: 1024,
360 height: 768,
361 icon: None,
362 }
363 }
364}