From 314f19380429f47a2bd3116e57c517a246290fc7 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 16 Jan 2026 16:40:59 +0000 Subject: [PATCH] added small animations --- crates/prometeu-core/src/firmware/firmware.rs | 95 +++++++++++++++---- .../src/firmware/firmware_state.rs | 22 +++-- .../firmware/firmware_step_crash_screen.rs | 41 +++++--- .../src/firmware/firmware_step_hub_home.rs | 26 +++-- .../src/firmware/firmware_step_init_app.rs | 24 +++-- .../src/firmware/firmware_step_launch_hub.rs | 22 +++-- .../src/firmware/firmware_step_reset.rs | 21 ++-- .../src/firmware/firmware_step_run_app.rs | 18 +++- .../firmware/firmware_step_splash_screen.rs | 88 +++++++++-------- crates/prometeu-core/src/firmware/mod.rs | 25 +++-- .../src/prometeu_hub/prometeu_hub.rs | 19 +++- 11 files changed, 278 insertions(+), 123 deletions(-) diff --git a/crates/prometeu-core/src/firmware/firmware.rs b/crates/prometeu-core/src/firmware/firmware.rs index f6483b47..f0945318 100644 --- a/crates/prometeu-core/src/firmware/firmware.rs +++ b/crates/prometeu-core/src/firmware/firmware.rs @@ -1,5 +1,5 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::firmware::{firmware_step_crash_screen, firmware_step_hub_home, firmware_step_init_app, firmware_step_launch_hub, firmware_step_reset, firmware_step_run_app, firmware_step_splash_screen}; +use crate::firmware::firmware_state::{FirmwareState, InitAppStep, ResetStep}; +use crate::firmware::FirmwareRequest; use crate::hardware::{HardwareBridge, InputSignals}; use crate::model::Cartridge; use crate::prometeu_hub::PrometeuHub; @@ -9,6 +9,7 @@ pub struct Firmware { pub os: PrometeuOS, pub hub: PrometeuHub, pub state: FirmwareState, + state_initialized: bool, } impl Firmware { @@ -16,30 +17,88 @@ impl Firmware { Self { os: PrometeuOS::new(), hub: PrometeuHub::new(), - state: FirmwareState::Reset, + state: FirmwareState::Reset(ResetStep), + state_initialized: false, } } pub fn step_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { - let os = &mut self.os; - let next_state = match &mut self.state { - FirmwareState::Reset => firmware_step_reset::step_reset(&mut self.os), - FirmwareState::SplashScreen(frame) => { - firmware_step_splash_screen::step_splash_screen(frame, os, signals, hw) - }, - FirmwareState::LaunchHub => firmware_step_launch_hub::launch_hub(&mut self.os, &mut self.hub), - FirmwareState::HubHome => firmware_step_hub_home::step_hub_home(&mut self.hub, &mut self.os, hw), - FirmwareState::LoadApp(cartridge) => firmware_step_init_app::step_init_app(&mut self.os, signals, hw, cartridge), - FirmwareState::AppRunning => firmware_step_run_app::step_run_app(&mut self.os, signals, hw), - FirmwareState::AppCrashes(_error) => firmware_step_crash_screen::step_crash_screen(signals, hw), - }; + if !self.state_initialized { + self.on_enter(signals, hw); + self.state_initialized = true; + } - if let Some(new_state) = next_state { - self.state = new_state; + if let Some(next_state) = self.on_update(signals, hw) { + self.change_state(next_state, signals, hw); + } + } + + pub fn change_state(&mut self, new_state: FirmwareState, signals: &InputSignals, hw: &mut dyn HardwareBridge) { + self.on_exit(signals, hw); + self.state = new_state; + self.state_initialized = false; + + // Entra no novo estado imediatamente + self.on_enter(signals, hw); + self.state_initialized = true; + } + + fn on_enter(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { + let mut req = FirmwareRequest { + os: &mut self.os, + hub: &mut self.hub, + signals, + hw, + }; + match &mut self.state { + FirmwareState::Reset(s) => s.on_enter(&mut req), + FirmwareState::SplashScreen(s) => s.on_enter(&mut req), + FirmwareState::LaunchHub(s) => s.on_enter(&mut req), + FirmwareState::HubHome(s) => s.on_enter(&mut req), + FirmwareState::LoadApp(s) => s.on_enter(&mut req), + FirmwareState::AppRunning(s) => s.on_enter(&mut req), + FirmwareState::AppCrashes(s) => s.on_enter(&mut req), + } + } + + fn on_update(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option { + let mut req = FirmwareRequest { + os: &mut self.os, + hub: &mut self.hub, + signals, + hw, + }; + match &mut self.state { + FirmwareState::Reset(s) => s.on_update(&mut req), + FirmwareState::SplashScreen(s) => s.on_update(&mut req), + FirmwareState::LaunchHub(s) => s.on_update(&mut req), + FirmwareState::HubHome(s) => s.on_update(&mut req), + FirmwareState::LoadApp(s) => s.on_update(&mut req), + FirmwareState::AppRunning(s) => s.on_update(&mut req), + FirmwareState::AppCrashes(s) => s.on_update(&mut req), + } + } + + fn on_exit(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { + let mut req = FirmwareRequest { + os: &mut self.os, + hub: &mut self.hub, + signals, + hw, + }; + match &mut self.state { + FirmwareState::Reset(s) => s.on_exit(&mut req), + FirmwareState::SplashScreen(s) => s.on_exit(&mut req), + FirmwareState::LaunchHub(s) => s.on_exit(&mut req), + FirmwareState::HubHome(s) => s.on_exit(&mut req), + FirmwareState::LoadApp(s) => s.on_exit(&mut req), + FirmwareState::AppRunning(s) => s.on_exit(&mut req), + FirmwareState::AppCrashes(s) => s.on_exit(&mut req), } } pub fn load_cartridge(&mut self, cartridge: Cartridge) { - self.state = FirmwareState::LoadApp(cartridge); // change state + self.state = FirmwareState::LoadApp(InitAppStep { cartridge }); + self.state_initialized = false; } } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_state.rs b/crates/prometeu-core/src/firmware/firmware_state.rs index 91c1028a..cc466e52 100644 --- a/crates/prometeu-core/src/firmware/firmware_state.rs +++ b/crates/prometeu-core/src/firmware/firmware_state.rs @@ -1,12 +1,18 @@ -use crate::model::Cartridge; +pub use crate::firmware::firmware_step_reset::ResetStep; +pub use crate::firmware::firmware_step_splash_screen::SplashScreenStep; +pub use crate::firmware::firmware_step_launch_hub::LaunchHubStep; +pub use crate::firmware::firmware_step_hub_home::HubHomeStep; +pub use crate::firmware::firmware_step_init_app::InitAppStep; +pub use crate::firmware::firmware_step_run_app::RunAppStep; +pub use crate::firmware::firmware_step_crash_screen::AppCrashesStep; #[derive(Debug, Clone)] pub enum FirmwareState { - Reset, - SplashScreen(u32), - LaunchHub, - HubHome, - LoadApp(Cartridge), - AppRunning, - AppCrashes(String), + Reset(ResetStep), + SplashScreen(SplashScreenStep), + LaunchHub(LaunchHubStep), + HubHome(HubHomeStep), + AppRunning(RunAppStep), + LoadApp(InitAppStep), + AppCrashes(AppCrashesStep), } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_step_crash_screen.rs b/crates/prometeu-core/src/firmware/firmware_step_crash_screen.rs index 103fc987..0a58cfd5 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_crash_screen.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_crash_screen.rs @@ -1,21 +1,32 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::hardware::{HardwareBridge, InputSignals}; +use crate::firmware::firmware_state::{FirmwareState, LaunchHubStep}; +use crate::firmware::FirmwareRequest; use crate::model::Color; -pub fn step_crash_screen(signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option { - // Atualiza periféricos para input na tela de crash - hw.pad_mut().begin_frame(signals); +#[derive(Debug, Clone)] +pub struct AppCrashesStep { + pub error: String, +} - // Tela de erro: fundo vermelho, texto branco - hw.gfx_mut().clear(Color::RED); - // Por enquanto apenas logamos ou mostramos algo simples - // No futuro, usar draw_text - hw.gfx_mut().present(); +impl AppCrashesStep { + pub fn on_enter(&mut self, _req: &mut FirmwareRequest) {} - // Se apertar START, volta pro Hub - if hw.pad().start.down { - return Some(FirmwareState::LaunchHub); + pub fn on_update(&mut self, req: &mut FirmwareRequest) -> Option { + // Atualiza periféricos para input na tela de crash + req.hw.pad_mut().begin_frame(req.signals); + + // Tela de erro: fundo vermelho, texto branco + req.hw.gfx_mut().clear(Color::RED); + // Por enquanto apenas logamos ou mostramos algo simples + // No futuro, usar draw_text + req.hw.gfx_mut().present(); + + // Se apertar START, volta pro Hub + if req.hw.pad().start.down { + return Some(FirmwareState::LaunchHub(LaunchHubStep)); + } + + None } - - None + + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_step_hub_home.rs b/crates/prometeu-core/src/firmware/firmware_step_hub_home.rs index ca6509cf..cf96a66c 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_hub_home.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_hub_home.rs @@ -1,13 +1,21 @@ use crate::firmware::firmware_state::FirmwareState; -use crate::hardware::HardwareBridge; +use crate::firmware::FirmwareRequest; use crate::model::Color; -use crate::prometeu_hub::PrometeuHub; -use crate::prometeu_os::PrometeuOS; -pub fn step_hub_home(hub: &mut PrometeuHub, os: &mut PrometeuOS, hw: &mut dyn HardwareBridge) -> Option { -hw.gfx_mut().clear(Color::INDIGO); -hub.gui_update(os); -hw.gfx_mut().present(); - - None +#[derive(Debug, Clone)] +pub struct HubHomeStep; + +impl HubHomeStep { + pub fn on_enter(&mut self, _req: &mut FirmwareRequest) {} + + pub fn on_update(&mut self, req: &mut FirmwareRequest) -> Option { + // req.hw.gfx_mut().clear(Color::BLACK); + req.hw.pad_mut().begin_frame(req.signals); + req.hub.gui_update(req.os, req.hw); + req.hw.gfx_mut().present(); + + None + } + + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_step_init_app.rs b/crates/prometeu-core/src/firmware/firmware_step_init_app.rs index 7c19a967..f11731ab 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_init_app.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_init_app.rs @@ -1,10 +1,20 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::hardware::{HardwareBridge, InputSignals}; +use crate::firmware::firmware_state::{FirmwareState, RunAppStep}; +use crate::firmware::FirmwareRequest; use crate::model::Cartridge; -use crate::prometeu_os::PrometeuOS; -pub fn step_init_app(os: &mut PrometeuOS, _signals: &InputSignals, _hw: &mut dyn HardwareBridge, cartridge: &Cartridge) -> Option { - os.initialize_vm(cartridge); - - Some(FirmwareState::AppRunning) +#[derive(Debug, Clone)] +pub struct InitAppStep { + pub cartridge: Cartridge, +} + +impl InitAppStep { + pub fn on_enter(&mut self, req: &mut FirmwareRequest) { + req.os.initialize_vm(&self.cartridge); + } + + pub fn on_update(&mut self, _req: &mut FirmwareRequest) -> Option { + Some(FirmwareState::AppRunning(RunAppStep)) + } + + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_step_launch_hub.rs b/crates/prometeu-core/src/firmware/firmware_step_launch_hub.rs index 96a85e77..57d583ef 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_launch_hub.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_launch_hub.rs @@ -1,9 +1,17 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::prometeu_hub::PrometeuHub; -use crate::prometeu_os::PrometeuOS; +use crate::firmware::firmware_state::{FirmwareState, HubHomeStep}; +use crate::firmware::FirmwareRequest; -pub fn launch_hub(_os: &mut PrometeuOS, hub: &mut PrometeuHub) -> Option { - hub.init(); - - Some(FirmwareState::HubHome) +#[derive(Debug, Clone)] +pub struct LaunchHubStep; + +impl LaunchHubStep { + pub fn on_enter(&mut self, req: &mut FirmwareRequest) { + req.hub.init(); + } + + pub fn on_update(&mut self, _req: &mut FirmwareRequest) -> Option { + Some(FirmwareState::HubHome(HubHomeStep)) + } + + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_step_reset.rs b/crates/prometeu-core/src/firmware/firmware_step_reset.rs index 4f19948f..5fdd1fa7 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_reset.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_reset.rs @@ -1,8 +1,17 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::prometeu_os::PrometeuOS; +use crate::firmware::firmware_state::{FirmwareState, SplashScreenStep}; +use crate::firmware::FirmwareRequest; -pub fn step_reset(os: &mut PrometeuOS) -> Option { - os.reset(); - - Some(FirmwareState::SplashScreen(0)) +#[derive(Debug, Clone)] +pub struct ResetStep; + +impl ResetStep { + pub fn on_enter(&mut self, req: &mut FirmwareRequest) { + req.os.reset(); + } + + pub fn on_update(&mut self, _req: &mut FirmwareRequest) -> Option { + Some(FirmwareState::SplashScreen(SplashScreenStep { frame: 0 })) + } + + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/firmware_step_run_app.rs b/crates/prometeu-core/src/firmware/firmware_step_run_app.rs index edc988f1..fc0eb9eb 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_run_app.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_run_app.rs @@ -1,7 +1,15 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::hardware::{HardwareBridge, InputSignals}; -use crate::prometeu_os::PrometeuOS; +use crate::firmware::firmware_state::{AppCrashesStep, FirmwareState}; +use crate::firmware::FirmwareRequest; -pub fn step_run_app(os: &mut PrometeuOS, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option { - os.step_frame(signals, hw).map(FirmwareState::AppCrashes) +#[derive(Debug, Clone)] +pub struct RunAppStep; + +impl RunAppStep { + pub fn on_enter(&mut self, _req: &mut FirmwareRequest) {} + + pub fn on_update(&mut self, req: &mut FirmwareRequest) -> Option { + req.os.step_frame(req.signals, req.hw).map(|err| FirmwareState::AppCrashes(AppCrashesStep { error: err })) + } + + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } diff --git a/crates/prometeu-core/src/firmware/firmware_step_splash_screen.rs b/crates/prometeu-core/src/firmware/firmware_step_splash_screen.rs index df1d8c13..74017826 100644 --- a/crates/prometeu-core/src/firmware/firmware_step_splash_screen.rs +++ b/crates/prometeu-core/src/firmware/firmware_step_splash_screen.rs @@ -1,51 +1,61 @@ -use crate::firmware::firmware_state::FirmwareState; -use crate::hardware::{HardwareBridge, InputSignals, LoopMode}; +use crate::firmware::firmware_state::{FirmwareState, LaunchHubStep}; +use crate::firmware::FirmwareRequest; +use crate::hardware::LoopMode; use crate::model::Color; -use crate::prometeu_os::PrometeuOS; -pub fn step_splash_screen(frame: &mut u32, os: &mut PrometeuOS, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option { - const ANIMATION_DURATION: u32 = 60; // 1 segundo a 60fps - const TOTAL_DURATION: u32 = 240; // 4 segundos totais +#[derive(Debug, Clone)] +pub struct SplashScreenStep { + pub frame: u32, +} - // Atualiza periféricos para input - hw.pad_mut().begin_frame(signals); - - // Tocar som no primeiro frame - if *frame == 0 { - if let Some(sample) = os.sample_square.clone() { - hw.audio_mut().play(sample, 0, 255, 127, 1.0, 0, LoopMode::Off); +impl SplashScreenStep { + pub fn on_enter(&mut self, req: &mut FirmwareRequest) { + // Tocar som no enter + if let Some(sample) = req.os.sample_square.clone() { + req.hw.audio_mut().play(sample, 0, 255, 127, 1.0, 0, LoopMode::Off); } } - // Limpar tela - hw.gfx_mut().clear(Color::BLACK); + pub fn on_update(&mut self, req: &mut FirmwareRequest) -> Option { + const ANIMATION_DURATION: u32 = 60; // 1 segundo a 60fps + const TOTAL_DURATION: u32 = 240; // 2 segundos totais (conforme requisito anterior) - // Desenhar quadrado aumentando - let (sw, sh) = hw.gfx().size(); - let max_size = (sw.min(sh) as i32 / 2).max(1); - - let current_size = if *frame < ANIMATION_DURATION { - (max_size * (*frame as i32 + 1)) / ANIMATION_DURATION as i32 - } else { - max_size - }; + // Atualiza periféricos para input + req.hw.pad_mut().begin_frame(req.signals); - let x = (sw as i32 - current_size) / 2; - let y = (sh as i32 - current_size) / 2; - - hw.gfx_mut().fill_rect(x, y, current_size, current_size, Color::WHITE); - hw.gfx_mut().present(); + // Limpar tela + req.hw.gfx_mut().clear(Color::BLACK); - // Lógica de transição - // Caso o botão start seja pressionado a qualquer momento depois da animação terminar - if *frame >= ANIMATION_DURATION && hw.pad().any() { - return Some(FirmwareState::LaunchHub); + // Desenhar quadrado aumentando + let (sw, sh) = req.hw.gfx().size(); + let max_size = (sw.min(sh) as i32 / 2).max(1); + + let current_size = if self.frame < ANIMATION_DURATION { + (max_size * (self.frame as i32 + 1)) / ANIMATION_DURATION as i32 + } else { + max_size + }; + + let x = (sw as i32 - current_size) / 2; + let y = (sh as i32 - current_size) / 2; + + req.hw.gfx_mut().fill_rect(x, y, current_size, current_size, Color::WHITE); + req.hw.gfx_mut().present(); + + // Lógica de transição + // Caso o botão start seja pressionado a qualquer momento depois da animação terminar + if self.frame >= ANIMATION_DURATION && req.hw.pad().any() { + return Some(FirmwareState::LaunchHub(LaunchHubStep)); + } + + if self.frame >= TOTAL_DURATION { + return Some(FirmwareState::LaunchHub(LaunchHubStep)); + } + + self.frame += 1; + + None } - if *frame >= TOTAL_DURATION { - return Some(FirmwareState::LaunchHub); - } - - *frame += 1; - None + pub fn on_exit(&mut self, _req: &mut FirmwareRequest) {} } \ No newline at end of file diff --git a/crates/prometeu-core/src/firmware/mod.rs b/crates/prometeu-core/src/firmware/mod.rs index a0c74c6e..0143f6cf 100644 --- a/crates/prometeu-core/src/firmware/mod.rs +++ b/crates/prometeu-core/src/firmware/mod.rs @@ -1,12 +1,23 @@ mod firmware; pub mod firmware_state; -mod firmware_step_reset; -mod firmware_step_splash_screen; -mod firmware_step_launch_hub; -mod firmware_step_hub_home; -mod firmware_step_init_app; -mod firmware_step_run_app; -mod firmware_step_crash_screen; +pub(crate) mod firmware_step_reset; +pub(crate) mod firmware_step_splash_screen; +pub(crate) mod firmware_step_launch_hub; +pub(crate) mod firmware_step_hub_home; +pub(crate) mod firmware_step_init_app; +pub(crate) mod firmware_step_run_app; +pub(crate) mod firmware_step_crash_screen; pub use firmware::Firmware; + +use crate::hardware::{HardwareBridge, InputSignals}; +use crate::prometeu_hub::PrometeuHub; +use crate::prometeu_os::PrometeuOS; + +pub struct FirmwareRequest<'a> { + pub os: &'a mut PrometeuOS, + pub hub: &'a mut PrometeuHub, + pub signals: &'a InputSignals, + pub hw: &'a mut dyn HardwareBridge, +} diff --git a/crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs b/crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs index 33baac74..d26b627f 100644 --- a/crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs +++ b/crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs @@ -19,12 +19,14 @@ impl WindowSystem { /// PrometeuHub: Launcher e ambiente de UI do sistema. pub struct PrometeuHub { pub window_system: WindowSystem, + pub color: Color, } impl PrometeuHub { pub fn new() -> Self { Self { window_system: WindowSystem::new(), + color: Color::BLACK, } } @@ -32,8 +34,21 @@ impl PrometeuHub { // Inicializa o Window System e lista apps } - pub fn gui_update(&mut self, _os: &mut PrometeuOS) { - // Atualiza a UI do Window System + pub fn gui_update(&mut self, os: &mut PrometeuOS, hw: &mut dyn HardwareBridge) { + if hw.pad().a.down { + self.color = Color::GREEN; + } + if hw.pad().b.down { + self.color = Color::INDIGO; + } + if hw.pad().x.down { + self.color = Color::YELLOW; + } + if hw.pad().y.down { + self.color = Color::RED; + } + + hw.gfx_mut().clear(self.color); } pub fn render(&mut self, _os: &mut PrometeuOS, _hw: &mut dyn HardwareBridge) {