Added step() and bar updates

master
Mark 2024-02-03 18:35:32 -08:00
parent 62b8a4f2d3
commit e893da01bc
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
9 changed files with 120 additions and 18 deletions

View File

@ -25,7 +25,7 @@ fn init(state) {
SpriteAnchor::NorthEast SpriteAnchor::NorthEast
) )
); );
shield.set_progress(0.2); shield.set_progress(1.0);
let hull = RadialBuilder( let hull = RadialBuilder(
"hull", 2.5, "hull", 2.5,
@ -36,7 +36,7 @@ fn init(state) {
SpriteAnchor::NorthEast SpriteAnchor::NorthEast
) )
); );
hull.set_progress(0.4); hull.set_progress(1.0);
return [ return [
ring, ring,
@ -52,4 +52,15 @@ fn event(state, event) {
} }
return; 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()
);
} }

View File

@ -2,10 +2,11 @@ mod color;
mod config; mod config;
mod event; mod event;
mod radialbuilder; mod radialbuilder;
mod radialelement;
mod rect; mod rect;
mod sceneaction; mod sceneaction;
mod sprite;
mod spritebuilder; mod spritebuilder;
mod spriteelement;
mod state; mod state;
mod textboxbuilder; mod textboxbuilder;
mod util; mod util;
@ -14,10 +15,11 @@ pub use color::*;
pub use config::*; pub use config::*;
pub use event::*; pub use event::*;
pub use radialbuilder::*; pub use radialbuilder::*;
pub use radialelement::*;
pub use rect::*; pub use rect::*;
pub use sceneaction::*; pub use sceneaction::*;
pub use sprite::*;
pub use spritebuilder::*; pub use spritebuilder::*;
pub use spriteelement::*;
pub use state::*; pub use state::*;
pub use textboxbuilder::*; pub use textboxbuilder::*;
pub use util::*; pub use util::*;
@ -36,9 +38,11 @@ pub fn register_into_engine(engine: &mut Engine) {
.build_type::<SystemObjectState>() .build_type::<SystemObjectState>()
// Builders // Builders
.build_type::<RadialBuilder>() .build_type::<RadialBuilder>()
.build_type::<SpriteElement>()
.build_type::<SpriteBuilder>() .build_type::<SpriteBuilder>()
.build_type::<TextBoxBuilder>() .build_type::<TextBoxBuilder>()
// Elements
.build_type::<SpriteElement>()
.build_type::<RadialElement>()
// Events // Events
.build_type::<MouseClickEvent>() .build_type::<MouseClickEvent>()
.build_type::<MouseHoverEvent>() .build_type::<MouseHoverEvent>()

View File

@ -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<RefCell<RadialBar>>,
pub ct: Rc<Content>,
}
// TODO: remove this
unsafe impl Send for RadialElement {}
unsafe impl Sync for RadialElement {}
impl RadialElement {
pub fn new(ct: Rc<Content>, bar: Rc<RefCell<RadialBar>>) -> Self {
Self { ct, bar }
}
}
impl CustomType for RadialElement {
fn build(mut builder: TypeBuilder<Self>) {
builder
.with_name("RadialElement")
.with_fn("set_val", |s: &mut Self, val: f32| {
s.bar.borrow_mut().set_val(val)
});
}
}

View File

@ -81,7 +81,13 @@ impl CustomType for ShipState {
}) })
.with_fn("name", |s: &mut Self| s.get_content().name.clone()) .with_fn("name", |s: &mut Self| s.get_content().name.clone())
.with_fn("thumbnail", |s: &mut Self| s.get_content().thumb) .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());
} }
} }

View File

@ -3,7 +3,7 @@ use galactica_content::Content;
use galactica_system::phys::PhysSimShipHandle; use galactica_system::phys::PhysSimShipHandle;
use glyphon::TextArea; use glyphon::TextArea;
use log::{debug, error, trace}; 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 std::{collections::HashSet, num::NonZeroU32, rc::Rc};
use super::{ use super::{
@ -17,7 +17,7 @@ use super::{
}; };
use crate::{ use crate::{
ui::{ ui::{
api::{RadialBuilder, SpriteBuilder, State}, api::{RadialBuilder, RadialElement, SpriteBuilder, State},
util::Sprite, util::Sprite,
}, },
RenderInput, RenderState, RenderInput, RenderState,
@ -28,9 +28,14 @@ pub(crate) struct UiManager {
current_scene_config: SceneConfig, current_scene_config: SceneConfig,
engine: Engine, engine: Engine,
scope: Scope<'static>, scope: Scope<'static>,
elements: Vec<UiElement>,
ct: Rc<Content>, ct: Rc<Content>,
/// UI elements
elements: Vec<UiElement>,
/// Map of ui element name -> api handle.
/// Used for step() function.
element_index: Map,
last_player_state: u32, last_player_state: u32,
show_timings: bool, show_timings: bool,
fps_indicator: FpsIndicator, fps_indicator: FpsIndicator,
@ -40,7 +45,7 @@ impl UiManager {
pub fn new(ct: Rc<Content>, state: &mut RenderState) -> Self { pub fn new(ct: Rc<Content>, state: &mut RenderState) -> Self {
let scope = Scope::new(); let scope = Scope::new();
let mut engine = Engine::new(); let mut engine = Engine::new_raw();
api::register_into_engine(&mut engine); api::register_into_engine(&mut engine);
Self { Self {
@ -50,6 +55,7 @@ impl UiManager {
engine, engine,
scope, scope,
elements: Vec::new(), elements: Vec::new(),
element_index: Map::new(),
show_timings: true, show_timings: true,
fps_indicator: FpsIndicator::new(state), fps_indicator: FpsIndicator::new(state),
last_player_state: 0, last_player_state: 0,
@ -177,6 +183,25 @@ impl UiManager {
// TODO: better message // TODO: better message
error!("bad type in builder array") 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(()); 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 // Update timings if they're being displayed
if self.show_timings { if self.show_timings {
self.fps_indicator.step(&input, state); self.fps_indicator.step(&input, state);

View File

@ -27,10 +27,14 @@ impl RadialBar {
rect, rect,
stroke, stroke,
color, 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) { pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) {
let rect = self.rect.to_centered(state, input.ct.get_config().ui_scale); let rect = self.rect.to_centered(state, input.ct.get_config().ui_scale);

View File

@ -215,7 +215,7 @@ impl OutfitSet {
} }
/// Total shield strength /// Total shield strength
pub fn get_shield_strength(&self) -> f32 { pub fn get_total_shields(&self) -> f32 {
self.shield_strength self.shield_strength
} }
} }

View File

@ -179,7 +179,7 @@ impl ShipData {
/// Add an outfit to this ship /// Add an outfit to this ship
pub fn add_outfit(&mut self, o: &Outfit) -> super::OutfitAddResult { pub fn add_outfit(&mut self, o: &Outfit) -> super::OutfitAddResult {
let r = self.outfits.add(o); let r = self.outfits.add(o);
self.shields = self.outfits.get_shield_strength(); self.shields = self.outfits.get_total_shields();
return r; return r;
} }
@ -248,8 +248,8 @@ impl ShipData {
} }
// Regenerate shields // Regenerate shields
if self.shields != self.outfits.get_shield_strength() { if self.shields != self.outfits.get_total_shields() {
self.shields = self.outfits.get_shield_strength(); self.shields = self.outfits.get_total_shields();
} }
} }
@ -263,12 +263,12 @@ impl ShipData {
// Regenerate shields // Regenerate shields
let time_since = self.last_hit.elapsed().as_secs_f32(); 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() { for g in self.outfits.iter_shield_generators() {
if time_since >= g.delay { if time_since >= g.delay {
self.shields += g.generation * t; self.shields += g.generation * t;
if self.shields > self.outfits.get_shield_strength() { if self.shields > self.outfits.get_total_shields() {
self.shields = self.outfits.get_shield_strength(); self.shields = self.outfits.get_total_shields();
break; break;
} }
} }