From e893da01bc542f8eacf612482512067601d31752 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 3 Feb 2024 18:35:32 -0800 Subject: [PATCH] Added step() and bar updates --- content/ui/flying.rhai | 15 +++++- crates/render/src/ui/api/mod.rs | 10 ++-- crates/render/src/ui/api/radialelement.rs | 31 +++++++++++ .../ui/api/{sprite.rs => spriteelement.rs} | 0 crates/render/src/ui/api/state.rs | 8 ++- crates/render/src/ui/manager.rs | 54 +++++++++++++++++-- crates/render/src/ui/util/radialbar.rs | 6 ++- crates/system/src/data/ship/outfitset.rs | 2 +- crates/system/src/data/ship/ship.rs | 12 ++--- 9 files changed, 120 insertions(+), 18 deletions(-) create mode 100644 crates/render/src/ui/api/radialelement.rs rename crates/render/src/ui/api/{sprite.rs => spriteelement.rs} (100%) diff --git a/content/ui/flying.rhai b/content/ui/flying.rhai index 5962157..9b337df 100644 --- a/content/ui/flying.rhai +++ b/content/ui/flying.rhai @@ -25,7 +25,7 @@ fn init(state) { SpriteAnchor::NorthEast ) ); - shield.set_progress(0.2); + shield.set_progress(1.0); let hull = RadialBuilder( "hull", 2.5, @@ -36,7 +36,7 @@ fn init(state) { SpriteAnchor::NorthEast ) ); - hull.set_progress(0.4); + hull.set_progress(1.0); return [ ring, @@ -52,4 +52,15 @@ fn event(state, event) { } return; } +} + +fn step(state, elements) { + elements["shield"].set_val( + state.player_ship().get_shields() + / state.player_ship().get_total_shields() + ); + elements["hull"].set_val( + state.player_ship().get_hull() + / state.player_ship().get_total_hull() + ); } \ No newline at end of file diff --git a/crates/render/src/ui/api/mod.rs b/crates/render/src/ui/api/mod.rs index 68064c0..2029067 100644 --- a/crates/render/src/ui/api/mod.rs +++ b/crates/render/src/ui/api/mod.rs @@ -2,10 +2,11 @@ mod color; mod config; mod event; mod radialbuilder; +mod radialelement; mod rect; mod sceneaction; -mod sprite; mod spritebuilder; +mod spriteelement; mod state; mod textboxbuilder; mod util; @@ -14,10 +15,11 @@ pub use color::*; pub use config::*; pub use event::*; pub use radialbuilder::*; +pub use radialelement::*; pub use rect::*; pub use sceneaction::*; -pub use sprite::*; pub use spritebuilder::*; +pub use spriteelement::*; pub use state::*; pub use textboxbuilder::*; pub use util::*; @@ -36,9 +38,11 @@ pub fn register_into_engine(engine: &mut Engine) { .build_type::() // Builders .build_type::() - .build_type::() .build_type::() .build_type::() + // Elements + .build_type::() + .build_type::() // Events .build_type::() .build_type::() diff --git a/crates/render/src/ui/api/radialelement.rs b/crates/render/src/ui/api/radialelement.rs new file mode 100644 index 0000000..21d2f66 --- /dev/null +++ b/crates/render/src/ui/api/radialelement.rs @@ -0,0 +1,31 @@ +use galactica_content::Content; +use rhai::{CustomType, TypeBuilder}; +use std::{cell::RefCell, rc::Rc}; + +use crate::ui::util::RadialBar; + +#[derive(Debug, Clone)] +pub struct RadialElement { + pub bar: Rc>, + pub ct: Rc, +} + +// TODO: remove this +unsafe impl Send for RadialElement {} +unsafe impl Sync for RadialElement {} + +impl RadialElement { + pub fn new(ct: Rc, bar: Rc>) -> Self { + Self { ct, bar } + } +} + +impl CustomType for RadialElement { + fn build(mut builder: TypeBuilder) { + builder + .with_name("RadialElement") + .with_fn("set_val", |s: &mut Self, val: f32| { + s.bar.borrow_mut().set_val(val) + }); + } +} diff --git a/crates/render/src/ui/api/sprite.rs b/crates/render/src/ui/api/spriteelement.rs similarity index 100% rename from crates/render/src/ui/api/sprite.rs rename to crates/render/src/ui/api/spriteelement.rs diff --git a/crates/render/src/ui/api/state.rs b/crates/render/src/ui/api/state.rs index 3fdaf35..a8ac112 100644 --- a/crates/render/src/ui/api/state.rs +++ b/crates/render/src/ui/api/state.rs @@ -81,7 +81,13 @@ impl CustomType for ShipState { }) .with_fn("name", |s: &mut Self| s.get_content().name.clone()) .with_fn("thumbnail", |s: &mut Self| s.get_content().thumb) - .with_fn("landed_on", |s: &mut Self| s.landed_on()); + .with_fn("landed_on", |s: &mut Self| s.landed_on()) + .with_fn("get_shields", |s: &mut Self| s.get_data().get_shields()) + .with_fn("get_total_shields", |s: &mut Self| { + s.get_data().get_outfits().get_total_shields() + }) + .with_fn("get_total_hull", |s: &mut Self| s.get_content().hull) + .with_fn("get_hull", |s: &mut Self| s.get_data().get_hull()); } } diff --git a/crates/render/src/ui/manager.rs b/crates/render/src/ui/manager.rs index cae0933..c7405fe 100644 --- a/crates/render/src/ui/manager.rs +++ b/crates/render/src/ui/manager.rs @@ -3,7 +3,7 @@ use galactica_content::Content; use galactica_system::phys::PhysSimShipHandle; use glyphon::TextArea; use log::{debug, error, trace}; -use rhai::{Array, Dynamic, Engine, Scope}; +use rhai::{Array, Dynamic, Engine, Map, Scope}; use std::{collections::HashSet, num::NonZeroU32, rc::Rc}; use super::{ @@ -17,7 +17,7 @@ use super::{ }; use crate::{ ui::{ - api::{RadialBuilder, SpriteBuilder, State}, + api::{RadialBuilder, RadialElement, SpriteBuilder, State}, util::Sprite, }, RenderInput, RenderState, @@ -28,9 +28,14 @@ pub(crate) struct UiManager { current_scene_config: SceneConfig, engine: Engine, scope: Scope<'static>, - elements: Vec, ct: Rc, + /// UI elements + elements: Vec, + /// Map of ui element name -> api handle. + /// Used for step() function. + element_index: Map, + last_player_state: u32, show_timings: bool, fps_indicator: FpsIndicator, @@ -40,7 +45,7 @@ impl UiManager { pub fn new(ct: Rc, state: &mut RenderState) -> Self { let scope = Scope::new(); - let mut engine = Engine::new(); + let mut engine = Engine::new_raw(); api::register_into_engine(&mut engine); Self { @@ -50,6 +55,7 @@ impl UiManager { engine, scope, elements: Vec::new(), + element_index: Map::new(), show_timings: true, fps_indicator: FpsIndicator::new(state), last_player_state: 0, @@ -177,6 +183,25 @@ impl UiManager { // TODO: better message error!("bad type in builder array") } + + self.element_index.clear(); + for e in &self.elements { + match e { + UiElement::Text(_) => {} + UiElement::RadialBar(r) => { + self.element_index.insert( + (&r).borrow().name.clone().into(), + Dynamic::from(RadialElement::new(self.ct.clone(), r.clone())), + ); + } + UiElement::Sprite(s) => { + self.element_index.insert( + (&s).borrow().name.clone().into(), + Dynamic::from(SpriteElement::new(self.ct.clone(), s.clone())), + ); + } + } + } } return Ok(()); } @@ -192,6 +217,27 @@ impl UiManager { )?; } + // Run step() (if it is defined) + let ast = &self + .ct + .get_config() + .ui_scenes + .get(self.current_scene.as_ref().unwrap()) + .unwrap(); + if ast.iter_functions().any(|x| x.name == "step") { + self.engine + .call_fn( + &mut self.scope, + ast, + "step", + (State::new(input.clone()), self.element_index.clone()), + ) + .with_context(|| format!("while handling player state change event")) + .with_context(|| { + format!("in ui scene `{}`", self.current_scene.as_ref().unwrap()) + })?; + } + // Update timings if they're being displayed if self.show_timings { self.fps_indicator.step(&input, state); diff --git a/crates/render/src/ui/util/radialbar.rs b/crates/render/src/ui/util/radialbar.rs index d4747e4..5cc8277 100644 --- a/crates/render/src/ui/util/radialbar.rs +++ b/crates/render/src/ui/util/radialbar.rs @@ -27,10 +27,14 @@ impl RadialBar { rect, stroke, color, - progress, + progress: progress.clamp(0.0, 1.0), } } + pub fn set_val(&mut self, val: f32) { + self.progress = val.clamp(0.0, 1.0); + } + pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) { let rect = self.rect.to_centered(state, input.ct.get_config().ui_scale); diff --git a/crates/system/src/data/ship/outfitset.rs b/crates/system/src/data/ship/outfitset.rs index 1237ac0..0cb3c67 100644 --- a/crates/system/src/data/ship/outfitset.rs +++ b/crates/system/src/data/ship/outfitset.rs @@ -215,7 +215,7 @@ impl OutfitSet { } /// Total shield strength - pub fn get_shield_strength(&self) -> f32 { + pub fn get_total_shields(&self) -> f32 { self.shield_strength } } diff --git a/crates/system/src/data/ship/ship.rs b/crates/system/src/data/ship/ship.rs index 8bc6d20..e27a9fa 100644 --- a/crates/system/src/data/ship/ship.rs +++ b/crates/system/src/data/ship/ship.rs @@ -179,7 +179,7 @@ impl ShipData { /// Add an outfit to this ship pub fn add_outfit(&mut self, o: &Outfit) -> super::OutfitAddResult { let r = self.outfits.add(o); - self.shields = self.outfits.get_shield_strength(); + self.shields = self.outfits.get_total_shields(); return r; } @@ -248,8 +248,8 @@ impl ShipData { } // Regenerate shields - if self.shields != self.outfits.get_shield_strength() { - self.shields = self.outfits.get_shield_strength(); + if self.shields != self.outfits.get_total_shields() { + self.shields = self.outfits.get_total_shields(); } } @@ -263,12 +263,12 @@ impl ShipData { // Regenerate shields let time_since = self.last_hit.elapsed().as_secs_f32(); - if self.shields != self.outfits.get_shield_strength() { + if self.shields != self.outfits.get_total_shields() { for g in self.outfits.iter_shield_generators() { if time_since >= g.delay { self.shields += g.generation * t; - if self.shields > self.outfits.get_shield_strength() { - self.shields = self.outfits.get_shield_strength(); + if self.shields > self.outfits.get_total_shields() { + self.shields = self.outfits.get_total_shields(); break; } }