World & Resources
The World is the central data container in Nightshade. It holds all entities, components, and global resources.
World Structure
The World is generated by the freecs::ecs! macro and contains:
#![allow(unused)] fn main() { pub struct World { pub entities: EntityStorage, pub resources: Resources, } }
Resources
Resources are global singletons accessible throughout the engine:
#![allow(unused)] fn main() { pub struct Resources { pub world_id: u64, pub is_runtime: bool, pub window: Window, pub secondary_windows: SecondaryWindows, pub user_interface: UserInterface, pub graphics: Graphics, pub input: Input, #[cfg(feature = "audio")] pub audio: AudioEngine, #[cfg(feature = "physics")] pub physics: PhysicsWorld, pub navmesh: NavMeshWorld, pub text_cache: TextCache, pub mesh_cache: MeshCache, pub animation_cache: AnimationCache, pub prefab_cache: PrefabCache, pub material_registry: MaterialRegistry, pub texture_cache: TextureCache, pub pending_font_loads: Vec<PendingFontLoad>, pub active_camera: Option<Entity>, pub event_bus: EventBus, pub command_queue: Vec<WorldCommand>, pub transform_dirty_entities: Vec<Entity>, pub children_cache: HashMap<Entity, Vec<Entity>>, pub children_cache_valid: bool, pub cleanup_frame_counter: u64, pub dropped_files: Vec<DroppedFile>, pub skinning_offsets: HashMap<Entity, usize>, pub total_skinning_joints: u32, #[cfg(feature = "scripting")] pub script_runtime: ScriptRuntime, #[cfg(feature = "openxr")] pub xr: XrResources, #[cfg(all(feature = "steam", not(target_arch = "wasm32")))] pub steam: SteamResources, #[cfg(feature = "physics")] pub picking_world: PickingWorld, pub gpu_picking: GpuPicking, #[cfg(feature = "sdf_sculpt")] pub sdf_world: SdfWorld, #[cfg(feature = "sdf_sculpt")] pub sdf_materials: SdfMaterialRegistry, pub mesh_render_state: MeshRenderState, #[cfg(feature = "scene_graph")] pub asset_registry: AssetRegistry, pub entity_names: HashMap<String, Entity>, pub entity_tags: HashMap<Entity, Vec<String>>, pub entity_metadata: HashMap<Entity, HashMap<String, MetadataValue>>, pub pending_particle_textures: Vec<ParticleTextureUpload>, pub ibl_views: IblViews, pub retained_ui: RetainedUiState, pub frame_schedule: FrameSchedule, pub sprite_slot_allocator: SpriteSlotAllocator, #[cfg(all(feature = "mcp", not(target_arch = "wasm32")))] pub mcp_command_queue: CommandQueue, } }
There is no separate Time resource. Timing information is accessed through world.resources.window.timing.
Accessing Resources
Resources are accessed through world.resources:
#![allow(unused)] fn main() { fn run_systems(&mut self, world: &mut World) { let dt = world.resources.window.timing.delta_time; if world.resources.input.keyboard.is_key_pressed(KeyCode::Space) { self.jump(); } world.resources.graphics.bloom_enabled = true; world.resources.graphics.bloom_intensity = 0.5; } }
Common Resources
Time & Timing
Timing is accessed through world.resources.window.timing:
#![allow(unused)] fn main() { let dt = world.resources.window.timing.delta_time; let fps = world.resources.window.timing.frames_per_second; let elapsed = world.resources.window.timing.uptime_milliseconds as f32 / 1000.0; }
The WindowTiming struct contains:
#![allow(unused)] fn main() { pub struct WindowTiming { pub frames_per_second: f32, pub delta_time: f32, pub raw_delta_time: f32, pub time_speed: f32, pub last_frame_start_instant: Option<web_time::Instant>, pub current_frame_start_instant: Option<web_time::Instant>, pub initial_frame_start_instant: Option<web_time::Instant>, pub frame_counter: u32, pub uptime_milliseconds: u64, } }
Input
#![allow(unused)] fn main() { if world.resources.input.keyboard.is_key_pressed(KeyCode::KeyW) { move_forward(); } let mouse_pos = world.resources.input.mouse.position; if world.resources.input.mouse.state.contains(MouseState::LEFT_JUST_PRESSED) { shoot(); } }
Graphics Settings
#![allow(unused)] fn main() { world.resources.graphics.show_grid = true; world.resources.graphics.atmosphere = Atmosphere::Sky; world.resources.graphics.bloom_enabled = true; world.resources.graphics.ssao_enabled = true; world.resources.graphics.color_grading.tonemap_algorithm = TonemapAlgorithm::Aces; }
Active Camera
#![allow(unused)] fn main() { world.resources.active_camera = Some(camera_entity); if let Some(camera) = world.resources.active_camera { let transform = world.core.get_global_transform(camera); } }
World Commands
Operations that require GPU access or must be deferred are queued as WorldCommand values and processed during the render phase:
#![allow(unused)] fn main() { world.queue_command(WorldCommand::LoadTexture { name: "my_texture".to_string(), rgba_data: texture_bytes, width: 256, height: 256, }); world.queue_command(WorldCommand::DespawnRecursive { entity }); world.queue_command(WorldCommand::LoadHdrSkybox { hdr_data }); world.queue_command(WorldCommand::CaptureScreenshot { path: None }); }
For immediate recursive despawning without deferral:
#![allow(unused)] fn main() { despawn_recursive_immediate(world, entity); }