Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions engine/pill_engine/src/app_config.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
use std::collections::HashMap;

use pill_core::Result;
use std::str::FromStr;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CompileMode {
Debug,
Release,
HotReload,
}

impl CompileMode {
pub(crate) fn from_env_value(value: &str) -> Result<Self> {
match value {
"debug" => Ok(Self::Debug),
"release" => Ok(Self::Release),
"hot-reload" => Ok(Self::HotReload),
other => Err(format!("Invalid compile mode: {other}").into()),
}
}

pub(crate) fn as_str(&self) -> &'static str {
match self {
CompileMode::Debug => "debug",
CompileMode::Release => "release",
CompileMode::HotReload => "hot-reload",
}
}
}

#[derive(Clone)]
pub enum BuildTarget {
Native,
Web,
}

impl BuildTarget {
pub(crate) fn as_str(&self) -> &'static str {
match self {
BuildTarget::Web => "web",
BuildTarget::Native => "native",
}
}
}

#[derive(Default, Clone)]
pub struct EngineConfig {
values: HashMap<String, String>,
}

#[derive(Clone)]
pub struct EngineProcessInfo {
pub(crate) mode: CompileMode,
pub(crate) target: BuildTarget,
}

impl EngineConfig {
pub fn from_ini(input: &str) -> Self {
let mut values = HashMap::new();
Expand Down Expand Up @@ -56,3 +104,13 @@ impl EngineConfig {
}
}
}

impl EngineProcessInfo {
pub fn new(mode: &str, target: BuildTarget) -> Self {
let translated = CompileMode::from_env_value(mode).unwrap();
Self {
target,
mode: translated,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#![cfg(feature = "debug_ui")]

use std::collections::HashMap;

use crate::{
ecs::{
components::{GlobalComponent, GlobalComponentStorage},
UpdatePhase,
},
engine::Engine,
};

use egui::Ui;
use pill_core::{PillTypeMapKey, Timer, TimerRecord};

use pill_core::{ErrorContext, Result};

#[derive(Copy, Clone)]
pub enum BuildStatus {
Pass,
Fail,
Warning,
}

// display the build type + target
// also display the last hot-reload status (compiled the code and reloaded or failed) with red/green
// light indicator
// updated every time we try hot-reloading and build_game
pub struct BuildStatusIndicatorComponent {
pub(crate) last_build_status: BuildStatus,
}

impl Default for BuildStatusIndicatorComponent {
fn default() -> Self {
Self {
last_build_status: BuildStatus::Pass,
}
}
}

impl PillTypeMapKey for BuildStatusIndicatorComponent {
type Storage = GlobalComponentStorage<BuildStatusIndicatorComponent>;
}

impl GlobalComponent for BuildStatusIndicatorComponent {}
40 changes: 37 additions & 3 deletions engine/pill_engine/src/ecs/components/egui_manager_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ use std::collections::HashMap;
use crate::{
ecs::{
components::{GlobalComponent, GlobalComponentStorage},
UpdatePhase,
BuildStatus, BuildStatusIndicatorComponent, UpdatePhase,
},
engine::Engine,
internal::CompileMode,
};

use egui::Ui;
use egui::{Color32, Ui};
use pill_core::{PillTypeMapKey, Timer, TimerRecord};

use pill_core::{ErrorContext, Result};
Expand All @@ -25,6 +26,7 @@ impl Default for EguiManagerComponent {
}
}

// TODO: add the build type/status
impl EguiManagerComponent {
pub fn new() -> Self {
Self {
Expand Down Expand Up @@ -75,18 +77,50 @@ impl EguiManagerComponent {
.sum::<f32>();
let frame_delta_time = engine.frame_delta_time;

let build_mode = engine.process.mode.as_str();
let build_target = engine.process.target.as_str();
let build_status = engine
.get_global_component::<BuildStatusIndicatorComponent>()
.unwrap()
.last_build_status;

let ui = Box::new(move |ui: &egui::Context| {
egui::Window::new("Pill Engine")
.default_open(false)
.default_open(true)
.resizable(true)
.anchor(egui::Align2::LEFT_TOP, [0.0, 0.0])
.show(ui, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
ui.add(egui::Label::new(format!("Mode: {}", build_mode)));
ui.add(egui::Label::new(format!("Target: {}", build_target)));
if build_mode == CompileMode::HotReload.as_str() {
ui.add(egui::Label::new("Build Status:"));
let color = match build_status {
BuildStatus::Pass => Color32::GREEN,
BuildStatus::Fail => Color32::RED,
BuildStatus::Warning => Color32::YELLOW,
};
let (rect, _) = ui
.allocate_exact_size(egui::vec2(24.0, 24.0), egui::Sense::hover());
ui.painter().circle_filled(rect.center(), 12.0, color);
}
});
});

egui::Window::new("Details")
.default_open(false)
.resizable(true)
//.anchor(egui::Align2::LEFT_TOP, [0.0, 0.0]) // TODO: how to make it below the
// previous
.show(ui, |ui| {
egui::ScrollArea::vertical()
.auto_shrink([false; 2]) // optional: prevent auto shrink
.show(ui, |ui| {
if ui.add(egui::Button::new("Click me")).clicked() {
println!("PRESSED");
}
ui.add(egui::Label::new(format!("Mode: {}", build_mode)));
ui.add(egui::Label::new(format!("Target: {}", build_target)));
ui.add(egui::Label::new(format!(
"FPS {}",
1000.0 / frame_delta_time
Expand Down
2 changes: 2 additions & 0 deletions engine/pill_engine/src/ecs/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub(crate) mod audio_listener_component;
pub(crate) mod audio_manager_component;
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod audio_source_component;
#[cfg(feature = "debug_ui")]
pub(crate) mod build_status_indicator_component;
pub(crate) mod camera_component;
mod component;
mod component_storage;
Expand Down
8 changes: 8 additions & 0 deletions engine/pill_engine/src/ecs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ pub use components::audio_source_component::AudioSourceComponent;
#[cfg(feature = "debug_ui")]
pub use components::egui_manager_component::EguiManagerComponent;

#[cfg(feature = "debug_ui")]
pub use components::build_status_indicator_component::{
BuildStatus, BuildStatusIndicatorComponent,
};

pub use components::deferred_update_component::{
DeferredUpdateComponent, DeferredUpdateComponentRequest, DeferredUpdateManagerPointer,
DeferredUpdateRequest, DeferredUpdateResourceRequest,
Expand Down Expand Up @@ -81,6 +86,9 @@ pub use systems::networking_system::{
NetworkEntityAction, NetworkUpdatePayload,
};

#[cfg(feature = "debug_ui")]
pub use systems::build_status_system::build_status_system;

// - Other

pub use entity::{Entity, EntityBuilder, EntityHandle};
Expand Down
24 changes: 24 additions & 0 deletions engine/pill_engine/src/ecs/systems/build_status_system.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![cfg(feature = "debug_ui")]
use crate::{
ecs::{BuildStatus, BuildStatusIndicatorComponent},
engine::Engine,
};
use pill_core::{Matrix3f, Vector3f};

use pill_core::Result;

pub fn build_status_system(engine: &mut Engine) -> Result<()> {
let build_status_component =
engine.get_global_component_mut::<BuildStatusIndicatorComponent>()?;

let status_env = std::env::var("PILL_HOT_RELOAD_STATUS")
.map_err(|_| "PILL_HOT_RELOAD_STATUS is not set!")?;
let status = match status_env.as_str() {
"fail" => BuildStatus::Fail,
"warn" => BuildStatus::Warning,
"pass" => BuildStatus::Pass,
_ => BuildStatus::Fail,
};
build_status_component.last_build_status = status;
Ok(())
}
2 changes: 2 additions & 0 deletions engine/pill_engine/src/ecs/systems/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod audio_system;
#[cfg(feature = "debug_ui")]
pub(crate) mod build_status_system;
pub(crate) mod deferred_update_system;
pub(crate) mod input_system;
#[cfg(not(target_arch = "wasm32"))]
Expand Down
19 changes: 17 additions & 2 deletions engine/pill_engine/src/engine.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::app_config::EngineProcessInfo;
use crate::{app_config::EngineConfig, config::*, ecs::*, graphics::*, resources::*};

use pill_core::{
Expand Down Expand Up @@ -25,6 +26,7 @@ pub trait PillGame {
/// Heart of Pill Engine
pub struct Engine {
pub(crate) config: EngineConfig,
pub(crate) process: EngineProcessInfo,
pub(crate) game: Option<Game>,
pub(crate) renderer: Box<dyn PillRenderer>,
pub(crate) scene_manager: SceneManager,
Expand All @@ -49,13 +51,15 @@ impl Engine {
game_resources_directory_path: std::path::PathBuf,
renderer: Box<dyn PillRenderer>,
config: EngineConfig,
process: EngineProcessInfo,
) -> Self {
let max_entity_count = config
.get_int("MAX_ENTITIES")
.unwrap_or(MAX_ENTITIES as i64) as usize;

Self {
config,
process,
game: Some(game),
renderer,
scene_manager: SceneManager::new(max_entity_count),
Expand All @@ -71,14 +75,15 @@ impl Engine {
}

#[cfg(feature = "headless")]
pub fn new(game: Box<dyn PillGame>, config: EngineConfig) -> Self {
pub fn new(game: Box<dyn PillGame>, config: EngineConfig, process: EngineProcessInfo) -> Self {
let max_entity_count = config
.get_int("MAX_ENTITIES")
.unwrap_or(MAX_ENTITIES as i64) as usize;
let dummy_renderer = Box::new(DummyRenderer) as Box<dyn PillRenderer>;

Self {
config,
process,
game: Some(game),
renderer: dummy_renderer,
scene_manager: SceneManager::new(max_entity_count),
Expand Down Expand Up @@ -303,7 +308,10 @@ impl Engine {
self.add_global_component(TimeComponent::new())?;
self.add_global_component(DeferredUpdateComponent::new())?;
#[cfg(feature = "debug_ui")]
self.add_global_component(EguiManagerComponent::new())?;
{
self.add_global_component(EguiManagerComponent::new())?;
self.add_global_component(BuildStatusIndicatorComponent::default())?;
}

#[cfg(not(feature = "headless"))]
{
Expand Down Expand Up @@ -358,6 +366,13 @@ impl Engine {
)?;
}

#[cfg(feature = "debug_ui")]
self.system_manager.add_system(
"build_status_system",
build_status_system,
UpdatePhase::PostGame,
)?;

// Create default resources
self.create_default_resources()
.context("Failed to create default resources")?;
Expand Down
4 changes: 2 additions & 2 deletions engine/pill_engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub mod game {

#[cfg(not(target_arch = "wasm32"))]
mod internal_mod {
pub use crate::app_config::EngineConfig;
pub use crate::app_config::{BuildTarget, CompileMode, EngineConfig, EngineProcessInfo};
pub use crate::{
config::*,
ecs::{
Expand Down Expand Up @@ -120,7 +120,7 @@ mod internal_mod {

#[cfg(target_arch = "wasm32")]
mod internal_mod {
pub use crate::app_config::EngineConfig;
pub use crate::app_config::{BuildTarget, CompileMode, EngineConfig, EngineProcessInfo};
pub use crate::{
config::*,
ecs::{
Expand Down
Loading
Loading