master
Mark 2024-02-03 12:01:12 -08:00
parent 5059e69cbb
commit 193feb5b92
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
4 changed files with 95 additions and 156 deletions

View File

@ -443,6 +443,7 @@ impl GPUState {
} }
} }
// Render utilities
impl GPUState { impl GPUState {
fn push_ships( fn push_ships(
&mut self, &mut self,

View File

@ -182,8 +182,8 @@ impl UiManager {
/// Draw all ui elements /// Draw all ui elements
pub fn draw(&mut self, input: Rc<RenderInput>, state: &mut RenderState) -> Result<()> { pub fn draw(&mut self, input: Rc<RenderInput>, state: &mut RenderState) -> Result<()> {
// Initialize start scene if we haven't yet
if self.current_scene.is_none() { if self.current_scene.is_none() {
// Initialize start scene if we haven't yet
self.set_scene( self.set_scene(
state, state,
input.clone(), input.clone(),
@ -191,13 +191,16 @@ impl UiManager {
)?; )?;
} }
// 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);
} }
// Check for player ship state changes let mut keep_doing_actions = true;
let player = input.player.ship;
let send_event = { // Send player state change events
if {
let player = input.player.ship;
if let Some(player) = player { if let Some(player) = player {
let ship = input.phys_img.get_ship(&PhysSimShipHandle(player)).unwrap(); let ship = input.phys_img.get_ship(&PhysSimShipHandle(player)).unwrap();
if self.last_player_state == 0 if self.last_player_state == 0
@ -213,10 +216,7 @@ impl UiManager {
self.last_player_state = 0; self.last_player_state = 0;
true true
} }
}; } {
let mut actions = Vec::new();
if send_event {
let action: Dynamic = self let action: Dynamic = self
.engine .engine
.call_fn( .call_fn(
@ -236,156 +236,108 @@ impl UiManager {
})?; })?;
if let Some(action) = action.try_cast::<SceneAction>() { if let Some(action) = action.try_cast::<SceneAction>() {
match action { keep_doing_actions = self.handle_action(state, input.clone(), action)?;
SceneAction::None => {}
_ => {
actions.push(action);
}
}
} }
} }
for e in &self.elements { for i in 0..self.elements.len() {
let action: Dynamic = { match &self.elements[i] {
if let Some(e) = e.sprite() { UiElement::Sprite(e) => {
let mut x = (*e).borrow_mut(); // Draw and update sprites
let event = x.check_mouse(&input, state); let mut sprite = (*e).borrow_mut();
x.step(&input, state); sprite.step(&input, state);
x.push_to_buffer(&input, state); sprite.push_to_buffer(&input, state);
drop(x);
if !keep_doing_actions {
continue;
}
let event = sprite.check_events(&input, state);
// we MUST drop here, since script calls mutate the sprite RefCell // we MUST drop here, since script calls mutate the sprite RefCell
drop(sprite);
match event { match event {
Event::None => Dynamic::from(SceneAction::None), Event::None => continue,
_ => {}
Event::MouseClick => self
.engine
.call_fn(
&mut self.scope,
&self
.ct
.get_config()
.ui_scenes
.get(self.current_scene.as_ref().unwrap())
.unwrap(),
"event",
(
State::new(input.clone()),
MouseClickEvent {
down: true,
element: SpriteElement::new(self.ct.clone(), e.clone()),
},
),
)
.with_context(|| format!("while handling click event"))
.with_context(|| {
format!("in ui scene `{}`", self.current_scene.as_ref().unwrap())
})?,
Event::MouseRelease => self
.engine
.call_fn(
&mut self.scope,
&self
.ct
.get_config()
.ui_scenes
.get(self.current_scene.as_ref().unwrap())
.unwrap(),
"event",
(
State::new(input.clone()),
MouseClickEvent {
down: false,
element: SpriteElement::new(self.ct.clone(), e.clone()),
},
),
)
.with_context(|| format!("while handling release event"))
.with_context(|| {
format!("in ui scene `{}`", self.current_scene.as_ref().unwrap())
})?,
Event::MouseHover => self
.engine
.call_fn(
&mut self.scope,
&self
.ct
.get_config()
.ui_scenes
.get(self.current_scene.as_ref().unwrap())
.unwrap(),
"event",
(
State::new(input.clone()),
MouseHoverEvent {
enter: true,
element: SpriteElement::new(self.ct.clone(), e.clone()),
},
),
)
.with_context(|| format!("while handling hover event"))
.with_context(|| {
format!("in ui scene `{}`", self.current_scene.as_ref().unwrap())
})?,
Event::MouseUnhover => self
.engine
.call_fn(
&mut self.scope,
&self
.ct
.get_config()
.ui_scenes
.get(self.current_scene.as_ref().unwrap())
.unwrap(),
"event",
(
State::new(input.clone()),
MouseHoverEvent {
enter: false,
element: SpriteElement::new(self.ct.clone(), e.clone()),
},
),
)
.with_context(|| format!("while handling unhover event"))
.with_context(|| {
format!("in ui scene `{}`", self.current_scene.as_ref().unwrap())
})?,
} }
} else if let Some(e) = e.radialbar() {
let event_arg = match event {
Event::None => unreachable!("this shouldn't happen"),
Event::MouseClick => Dynamic::from(MouseClickEvent {
down: true,
element: SpriteElement::new(self.ct.clone(), e.clone()),
}),
Event::MouseRelease => Dynamic::from(MouseClickEvent {
down: false,
element: SpriteElement::new(self.ct.clone(), e.clone()),
}),
Event::MouseHover => Dynamic::from(MouseHoverEvent {
enter: true,
element: SpriteElement::new(self.ct.clone(), e.clone()),
}),
Event::MouseUnhover => Dynamic::from(MouseHoverEvent {
enter: false,
element: SpriteElement::new(self.ct.clone(), e.clone()),
}),
};
let action: Dynamic = self
.engine
.call_fn(
&mut self.scope,
&self
.ct
.get_config()
.ui_scenes
.get(self.current_scene.as_ref().unwrap())
.unwrap(),
"event",
(State::new(input.clone()), event_arg),
)
.with_context(|| format!("while handling event `{:?}`", event))
.with_context(|| {
format!("in ui scene `{}`", self.current_scene.as_ref().unwrap())
})?;
if let Some(action) = action.try_cast::<SceneAction>() {
keep_doing_actions = self.handle_action(state, input.clone(), action)?;
}
}
UiElement::RadialBar(e) => {
// Draw and update radialbar
let mut x = (*e).borrow_mut(); let mut x = (*e).borrow_mut();
x.step(&input, state); x.step(&input, state);
x.push_to_buffer(&input, state); x.push_to_buffer(&input, state);
Dynamic::from(SceneAction::None)
} else {
Dynamic::from(SceneAction::None)
} }
};
if let Some(action) = action.try_cast::<SceneAction>() { UiElement::Text(..) => {}
match action {
SceneAction::None => {}
_ => {
actions.push(action);
}
}
}
}
for a in actions {
match a {
SceneAction::None => {}
SceneAction::GoTo(s) => {
self.set_scene(state, input.clone(), s.clone())?;
break;
}
} }
} }
return Ok(()); return Ok(());
} }
/// Do a SceneAction.
/// Returns true if we should execute the action that is next, and false otherwise.
fn handle_action(
&mut self,
state: &mut RenderState,
input: Rc<RenderInput>,
action: SceneAction,
) -> Result<bool> {
Ok(match action {
SceneAction::None => true,
SceneAction::GoTo(s) => {
self.set_scene(state, input.clone(), s.clone())?;
false
}
})
}
} }
impl<'a> UiManager { impl<'a> UiManager {

View File

@ -22,24 +22,10 @@ impl UiElement {
Self::Text(text) Self::Text(text)
} }
pub fn sprite(&self) -> Option<Rc<RefCell<Sprite>>> {
match self {
Self::Sprite(s) => Some(s.clone()),
_ => None,
}
}
pub fn text(&self) -> Option<&TextBox> { pub fn text(&self) -> Option<&TextBox> {
match self { match self {
Self::Text(t) => Some(t), Self::Text(t) => Some(t),
_ => None, _ => None,
} }
} }
pub fn radialbar(&self) -> Option<Rc<RefCell<RadialBar>>> {
match self {
Self::RadialBar(r) => Some(r.clone()),
_ => None,
}
}
} }

View File

@ -71,7 +71,7 @@ impl Sprite {
}); });
} }
pub fn check_mouse(&mut self, input: &RenderInput, state: &mut RenderState) -> Event { pub fn check_events(&mut self, input: &RenderInput, state: &mut RenderState) -> Event {
let r = self.rect.to_centered(state, input.ct.get_config().ui_scale); let r = self.rect.to_centered(state, input.ct.get_config().ui_scale);
if self.waiting_for_release && self.has_mouse && !input.player.input.pressed_leftclick() { if self.waiting_for_release && self.has_mouse && !input.player.input.pressed_leftclick() {