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
)
);
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()
);
}

View File

@ -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::<SystemObjectState>()
// Builders
.build_type::<RadialBuilder>()
.build_type::<SpriteElement>()
.build_type::<SpriteBuilder>()
.build_type::<TextBoxBuilder>()
// Elements
.build_type::<SpriteElement>()
.build_type::<RadialElement>()
// Events
.build_type::<MouseClickEvent>()
.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("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 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<UiElement>,
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,
show_timings: bool,
fps_indicator: FpsIndicator,
@ -40,7 +45,7 @@ impl UiManager {
pub fn new(ct: Rc<Content>, 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);

View File

@ -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);

View File

@ -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
}
}

View File

@ -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;
}
}