ursus_core/app/
context.rs1use crate::app::Plugin;
2use crate::assets::registry::AssetRegistry;
3use crate::assets::upload::GpuUploadRequest;
4use crate::render::extract::{ExtractSchedule, ExtractSystem};
5use crate::render::frame_pipeline::render_pipeline::RenderPipeline;
6use crate::render::frame_stats::FrameStats;
7use crate::render::thread::command::{PipelineFactory, RenderCommand};
8use crate::render::triple_buffer::TripleBuffer;
9use crate::render::world::{ExtractedRenderSettings, RWorld};
10use std::sync::mpsc::Sender;
11use std::sync::Arc;
12use ursus_ecs::tick::default_tick_schedule;
13use ursus_ecs::{TickSchedule, TickSystem, World};
14
15#[allow(clippy::enum_variant_names)]
16pub enum WindowCommand {
17 SetTitle(String),
18 SetSize(u32, u32),
19 SetFullscreen(bool), }
21
22pub struct EngineContext {
23 pub world: World,
24 pub asset_registry: AssetRegistry,
25 pub extract_schedule: ExtractSchedule,
26 pub tick_schedule: TickSchedule,
27
28 pub(crate) cmd_tx: Sender<RenderCommand>,
29 upload_tx: Sender<GpuUploadRequest>,
30 triple_buf: Arc<TripleBuffer<RWorld>>,
31 pub(crate) output_size: (f32, f32),
32 frame_stats: FrameStats,
33 pub(crate) window_cmd_tx: Sender<WindowCommand>,
34}
35
36impl EngineContext {
37 pub(crate) fn new(
38 cmd_tx: Sender<RenderCommand>,
39 upload_tx: Sender<GpuUploadRequest>,
40 triple_buf: Arc<TripleBuffer<RWorld>>,
41 output_size: (f32, f32),
42 frame_stats: FrameStats,
43 window_cmd_tx: Sender<WindowCommand>,
44 ) -> anyhow::Result<Self> {
45 Ok(Self {
46 world: World::new(),
47 asset_registry: AssetRegistry::default(),
48 extract_schedule: ExtractSchedule::default(),
49 tick_schedule: default_tick_schedule(),
50 cmd_tx,
51 upload_tx,
52 triple_buf,
53 output_size,
54 frame_stats,
55 window_cmd_tx,
56 })
57 }
58
59 pub fn frame_stats(&self) -> &FrameStats {
60 &self.frame_stats
61 }
62
63 pub fn send_render_cmd(&self, cmd: RenderCommand) {
64 let _ = self.cmd_tx.send(cmd);
65 }
66
67 pub fn set_pipeline<P>(&self)
68 where
69 P: RenderPipeline + Default + 'static,
70 {
71 self.send_render_cmd(RenderCommand::SetPipeline(PipelineFactory::of::<P>()));
72 }
73
74 pub(crate) fn publish_frame(&mut self, clear_color: [f32; 4], interpolation_alpha: f32) {
75 let write = self.triple_buf.write_slot();
76 write.clear();
77 write.insert(ExtractedRenderSettings {
78 clear_color,
79 output_size: self.output_size,
80 fsr_sharpness: 0.2,
81 exposure: 0.5,
82 interpolation_alpha,
83 });
84 self.extract_schedule.run(&self.world, write);
85 self.asset_registry.flush_uploads(&self.upload_tx);
86 self.triple_buf.publish();
87 }
88
89 pub fn set_window_title(&self, title: impl Into<String>) {
90 let _ = self.window_cmd_tx.send(WindowCommand::SetTitle(title.into()));
91 }
92 pub fn set_window_size(&self, width: u32, height: u32) {
93 let _ = self.window_cmd_tx.send(WindowCommand::SetSize(width, height));
94 }
95 pub fn set_fullscreen(&self, enabled: bool) {
96 let _ = self.window_cmd_tx.send(WindowCommand::SetFullscreen(enabled));
97 }
98
99 pub fn add_extract_system(&mut self, system: impl ExtractSystem + 'static) {
100 self.extract_schedule.add(system);
101 }
102
103 pub fn add_tick_system(&mut self, system: impl TickSystem + 'static) {
104 self.tick_schedule.add(system);
105 }
106
107 pub fn add_plugin(&mut self, plugin: impl Plugin) {
108 plugin.build(self);
109 }
110
111 pub fn add_plugins(&mut self, plugins: impl IntoIterator<Item = impl Plugin>) {
112 for p in plugins {
113 self.add_plugin(p);
114 }
115 }
116}