Improve ecs ergonomics
This commit is contained in:
parent
d4997dff39
commit
52336040f2
15 changed files with 216 additions and 151 deletions
|
@ -2,6 +2,7 @@ use crate::prelude::*;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use super::validator::buttoninfo::{NeighbourDirection, NeighbourInfo};
|
use super::validator::buttoninfo::{NeighbourDirection, NeighbourInfo};
|
||||||
use super::validator::gridinfo::GridInfo;
|
use super::validator::gridinfo::GridInfo;
|
||||||
|
@ -178,10 +179,7 @@ impl GuiBuilder {
|
||||||
impl Functionality for GuiBuilder {
|
impl Functionality for GuiBuilder {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
functions: Vec<(
|
functions: Vec<(&str, Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>)>,
|
||||||
&str,
|
|
||||||
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
|
||||||
)>,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in functions {
|
for (function_name, callback) in functions {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -195,14 +193,20 @@ impl Functionality for GuiBuilder {
|
||||||
|
|
||||||
fn set_vec_callbacks(
|
fn set_vec_callbacks(
|
||||||
&self,
|
&self,
|
||||||
_functions: Vec<(&str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>,
|
_functions: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_select_callbacks(
|
fn set_select_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<CustomCallback<bool, ()>>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, bool) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in callbacks {
|
for (function_name, callback) in callbacks {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -216,7 +220,10 @@ impl Functionality for GuiBuilder {
|
||||||
|
|
||||||
fn set_custom_callbacks(
|
fn set_custom_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<CustomCallback<ControllerButton, bool>>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in callbacks {
|
for (function_name, callback) in callbacks {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -262,7 +269,7 @@ impl GuiElementTraits for GuiBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopGui for GuiBuilder {
|
impl TopGui for GuiBuilder {
|
||||||
fn decline(&self, _gui_handler: &mut GuiHandler) -> Result<()> {
|
fn decline(&self, _world: &mut World) -> Result<()> {
|
||||||
if let Some(decline_callback) = self.decline_callback.read().unwrap().as_ref() {
|
if let Some(decline_callback) = self.decline_callback.read().unwrap().as_ref() {
|
||||||
decline_callback()?;
|
decline_callback()?;
|
||||||
}
|
}
|
||||||
|
@ -270,11 +277,11 @@ impl TopGui for GuiBuilder {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tab(&self, _gui_handler: &mut GuiHandler, _: bool) -> Result<()> {
|
fn next_tab(&self, _world: &mut World, _: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous_tab(&self, _gui_handler: &mut GuiHandler, _: bool) -> Result<()> {
|
fn previous_tab(&self, _world: &mut World, _: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{any::Any, collections::HashMap, sync::Arc};
|
use std::{any::Any, collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use super::validator::{
|
use super::validator::{
|
||||||
buttoninfo::NeighbourInfo,
|
buttoninfo::NeighbourInfo,
|
||||||
|
@ -147,10 +148,7 @@ impl Gridable for GuiSnippet {
|
||||||
impl Functionality for GuiSnippet {
|
impl Functionality for GuiSnippet {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
functions: Vec<(
|
functions: Vec<(&str, Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>)>,
|
||||||
&str,
|
|
||||||
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
|
||||||
)>,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in functions {
|
for (function_name, callback) in functions {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -164,14 +162,20 @@ impl Functionality for GuiSnippet {
|
||||||
|
|
||||||
fn set_vec_callbacks(
|
fn set_vec_callbacks(
|
||||||
&self,
|
&self,
|
||||||
_functions: Vec<(&str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>,
|
_functions: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_select_callbacks(
|
fn set_select_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<CustomCallback<bool, ()>>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, bool) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in callbacks {
|
for (function_name, callback) in callbacks {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
@ -185,7 +189,10 @@ impl Functionality for GuiSnippet {
|
||||||
|
|
||||||
fn set_custom_callbacks(
|
fn set_custom_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<CustomCallback<ControllerButton, bool>>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (function_name, callback) in callbacks {
|
for (function_name, callback) in callbacks {
|
||||||
let suffix_less_function_name = handle_function_suffix(function_name);
|
let suffix_less_function_name = handle_function_suffix(function_name);
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
|
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
|
use ecs::World;
|
||||||
use utilities::prelude::*;
|
use utilities::prelude::*;
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
|
@ -314,23 +315,23 @@ impl Button {
|
||||||
|
|
||||||
pub fn set_callback<F>(&self, callback: F)
|
pub fn set_callback<F>(&self, callback: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut GuiHandler) -> Result<()> + Send + Sync + 'static,
|
F: Fn(&mut World) -> Result<()> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.click_executable
|
self.click_executable
|
||||||
.set_callback(move |gui_handler: &mut GuiHandler, _: ()| callback(gui_handler));
|
.set_callback(move |world: &mut World, _: ()| callback(world));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_select_callback<F>(&self, callback: F)
|
pub fn set_select_callback<F>(&self, callback: F)
|
||||||
where
|
where
|
||||||
F: Fn(bool) -> Result<()> + Send + Sync + 'static,
|
F: Fn(&mut World, bool) -> Result<()> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.on_select_executable
|
self.on_select_executable
|
||||||
.set_callback(move |_: &mut GuiHandler, select: bool| callback(select));
|
.set_callback(move |world: &mut World, select: bool| callback(world, select));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_custom_callback<F>(&self, callback: F)
|
pub fn set_custom_callback<F>(&self, callback: F)
|
||||||
where
|
where
|
||||||
F: Fn(ControllerButton) -> Result<bool> + Send + Sync + 'static,
|
F: Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.selectable.set_custom_callback(callback);
|
self.selectable.set_custom_callback(callback);
|
||||||
}
|
}
|
||||||
|
@ -578,8 +579,10 @@ impl Button {
|
||||||
fn create_selected_changed_callback(button: Arc<Button>) {
|
fn create_selected_changed_callback(button: Arc<Button>) {
|
||||||
let button_weak = Arc::downgrade(&button);
|
let button_weak = Arc::downgrade(&button);
|
||||||
|
|
||||||
let selected_changed = move |gui_handler: &mut GuiHandler, selected: bool| {
|
let selected_changed = move |world: &mut World, selected: bool| {
|
||||||
if let Some(button) = button_weak.upgrade() {
|
if let Some(button) = button_weak.upgrade() {
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
|
|
||||||
if selected {
|
if selected {
|
||||||
button.set_button_state(gui_handler, ButtonState::Selected)?;
|
button.set_button_state(gui_handler, ButtonState::Selected)?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use super::ControllerButton;
|
use super::ControllerButton;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -27,18 +28,21 @@ macro_rules! callbacks {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks!(ClickCallbacks, Fn(&mut GuiHandler) -> Result<()> + Send + Sync);
|
callbacks!(ClickCallbacks, Fn(&mut World, &mut GuiHandler) -> Result<()> + Send + Sync);
|
||||||
callbacks!(SelectCallbacks, Fn(bool) -> anyhow::Result<()> + Send + Sync);
|
callbacks!(SelectCallbacks, Fn(&mut World, &mut GuiHandler, bool) -> anyhow::Result<()> + Send + Sync);
|
||||||
callbacks!(CustomCallbacks, Fn(ControllerButton) -> anyhow::Result<bool> + Send + Sync);
|
callbacks!(CustomCallbacks, Fn(&mut World, &mut GuiHandler, ControllerButton) -> anyhow::Result<bool> + Send + Sync);
|
||||||
callbacks!(VecCallbacks, Fn(&dyn Any) -> Result<()> + Send + Sync);
|
callbacks!(
|
||||||
|
VecCallbacks,
|
||||||
|
Fn(&mut World, &mut GuiHandler, &dyn Any) -> Result<()> + Send + Sync
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
fn normal_fn() -> impl Fn(&mut GuiHandler) -> Result<()> + Send + Sync {
|
fn normal_fn() -> impl Fn(&mut World, &mut GuiHandler) -> Result<()> + Send + Sync {
|
||||||
|_| Ok(())
|
|_, _| Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -50,7 +54,7 @@ mod test {
|
||||||
&self,
|
&self,
|
||||||
_callbacks: Vec<(
|
_callbacks: Vec<(
|
||||||
&str,
|
&str,
|
||||||
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
Box<dyn Fn(&mut World, &mut GuiHandler) -> Result<()> + Send + Sync>,
|
||||||
)>,
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::sync::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
use ecs::World;
|
||||||
use utilities::prelude::*;
|
use utilities::prelude::*;
|
||||||
|
|
||||||
use super::fill_type::InnerFillType;
|
use super::fill_type::InnerFillType;
|
||||||
|
@ -96,9 +97,9 @@ impl MultiLineTextFieldBuilder {
|
||||||
multi_line_text_field.text_changed_exec.set_callback({
|
multi_line_text_field.text_changed_exec.set_callback({
|
||||||
let weak_tf = Arc::downgrade(&multi_line_text_field);
|
let weak_tf = Arc::downgrade(&multi_line_text_field);
|
||||||
|
|
||||||
move |gui_handler: &mut GuiHandler, _text| {
|
move |world: &mut World, _text| {
|
||||||
if let Some(tf) = weak_tf.upgrade() {
|
if let Some(tf) = weak_tf.upgrade() {
|
||||||
tf.update_text(gui_handler)?;
|
tf.update_text(world.resources.get_mut::<GuiHandler>())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{builder::validator::textfieldinfo::TextFieldInfo, prelude::*};
|
use crate::{builder::validator::textfieldinfo::TextFieldInfo, prelude::*};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
use utilities::prelude::*;
|
use utilities::prelude::*;
|
||||||
|
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
|
@ -169,7 +170,7 @@ impl TextField {
|
||||||
|
|
||||||
pub fn set_text_changed_callback<F>(&self, f: F)
|
pub fn set_text_changed_callback<F>(&self, f: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut GuiHandler, Option<String>) -> Result<()> + Send + Sync + 'static,
|
F: Fn(&mut World, Option<String>) -> Result<()> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.text_changed_executable.set_callback(f);
|
self.text_changed_executable.set_callback(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use std::{any::Any, collections::HashMap, sync::Arc};
|
use std::{any::Any, collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
@ -26,25 +27,31 @@ where
|
||||||
pub trait Functionality {
|
pub trait Functionality {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(
|
callbacks: Vec<(&str, Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>)>,
|
||||||
&str,
|
|
||||||
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
|
||||||
)>,
|
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
|
|
||||||
fn set_select_callbacks(
|
fn set_select_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<CustomCallback<bool, ()>>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, bool) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
|
|
||||||
fn set_custom_callbacks(
|
fn set_custom_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<CustomCallback<ControllerButton, bool>>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
|
|
||||||
fn set_vec_callbacks(
|
fn set_vec_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! `Executable` is a property to execute a closure
|
//! `Executable` is a property to execute a closure
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
@ -8,7 +9,7 @@ use crate::prelude::*;
|
||||||
|
|
||||||
/// `Executable` holds a closure which can be executed
|
/// `Executable` holds a closure which can be executed
|
||||||
pub struct Executable<I: Send + Sync> {
|
pub struct Executable<I: Send + Sync> {
|
||||||
callback: RwLock<Option<Arc<dyn Fn(&mut GuiHandler, I) -> Result<()> + Send + Sync>>>,
|
callback: RwLock<Option<Arc<dyn Fn(&mut World, I) -> Result<()> + Send + Sync>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Send + Sync + 'static> Executable<I> {
|
impl<I: Send + Sync + 'static> Executable<I> {
|
||||||
|
@ -26,7 +27,7 @@ impl<I: Send + Sync + 'static> Executable<I> {
|
||||||
/// * `callback` is a `Option<Callback>` closure
|
/// * `callback` is a `Option<Callback>` closure
|
||||||
pub fn set_callback<F>(&self, callback: impl Into<Option<F>>)
|
pub fn set_callback<F>(&self, callback: impl Into<Option<F>>)
|
||||||
where
|
where
|
||||||
F: Fn(&mut GuiHandler, I) -> Result<()> + Send + Sync + 'static,
|
F: Fn(&mut World, I) -> Result<()> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let mut function = self.callback.write().unwrap();
|
let mut function = self.callback.write().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use super::executable::Executable;
|
use super::executable::Executable;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
Arc, RwLock, Weak,
|
Arc, RwLock, Weak,
|
||||||
|
@ -39,7 +40,8 @@ pub struct Selectable {
|
||||||
on_select_executable: Arc<Executable<bool>>,
|
on_select_executable: Arc<Executable<bool>>,
|
||||||
|
|
||||||
// used for custom buttons
|
// used for custom buttons
|
||||||
custom_callback: RwLock<Option<Box<dyn Fn(ControllerButton) -> Result<bool> + Send + Sync>>>,
|
custom_callback:
|
||||||
|
RwLock<Option<Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Selectable {
|
impl Selectable {
|
||||||
|
@ -115,7 +117,7 @@ impl Selectable {
|
||||||
|
|
||||||
pub fn set_custom_callback<F>(&self, custom_callback: F)
|
pub fn set_custom_callback<F>(&self, custom_callback: F)
|
||||||
where
|
where
|
||||||
F: Fn(ControllerButton) -> Result<bool> + Send + Sync + 'static,
|
F: Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
*self.custom_callback.write().unwrap() = Some(Box::new(custom_callback));
|
*self.custom_callback.write().unwrap() = Some(Box::new(custom_callback));
|
||||||
}
|
}
|
||||||
|
@ -176,9 +178,13 @@ impl Selectable {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn custom_click_event(&self, button: ControllerButton) -> Result<bool> {
|
pub(crate) fn custom_click_event(
|
||||||
|
&self,
|
||||||
|
world: &mut World,
|
||||||
|
button: ControllerButton,
|
||||||
|
) -> Result<bool> {
|
||||||
if let Some(custom_callback) = self.custom_callback.read().unwrap().as_ref() {
|
if let Some(custom_callback) = self.custom_callback.read().unwrap().as_ref() {
|
||||||
if custom_callback(button)? {
|
if custom_callback(world, button)? {
|
||||||
#[cfg(feature = "audio")]
|
#[cfg(feature = "audio")]
|
||||||
{
|
{
|
||||||
if let Some(audible) = self.click_audible.read().unwrap().as_ref() {
|
if let Some(audible) = self.click_audible.read().unwrap().as_ref() {
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
/// A trait that is used by the gui handler as the target for input
|
/// A trait that is used by the gui handler as the target for input
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
pub trait TopGui: Send + Sync {
|
pub trait TopGui: Send + Sync {
|
||||||
/// Decline method which is executed on `InputMap::B` press
|
/// Decline method which is executed on `InputMap::B` press
|
||||||
fn decline(&self, gui_handler: &mut GuiHandler) -> Result<()>;
|
fn decline(&self, world: &mut World) -> Result<()>;
|
||||||
|
|
||||||
/// Method which is executed on `InputMap::RightButton` press
|
/// Method which is executed on `InputMap::RightButton` press
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
||||||
fn next_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()>;
|
fn next_tab(&self, world: &mut World, second_level: bool) -> Result<()>;
|
||||||
|
|
||||||
/// Method which is executed on `InputMap::LeftButton` press
|
/// Method which is executed on `InputMap::LeftButton` press
|
||||||
/// ///
|
/// ///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
/// * `second_level` adds support for multiple tab layers, e.g. RB and RT press on controller
|
||||||
fn previous_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()>;
|
fn previous_tab(&self, world: &mut World, second_level: bool) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::prelude::*;
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
|
|
||||||
|
use ecs::World;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use utilities::{impl_reprc, prelude::*};
|
use utilities::{impl_reprc, prelude::*};
|
||||||
use vulkan_rs::{prelude::*, render_target::sub_pass::InputAttachmentInfo};
|
use vulkan_rs::{prelude::*, render_target::sub_pass::InputAttachmentInfo};
|
||||||
|
@ -243,7 +244,7 @@ pub struct GuiHandler {
|
||||||
|
|
||||||
text_sample_count: VkSampleCountFlags,
|
text_sample_count: VkSampleCountFlags,
|
||||||
|
|
||||||
callback_list: Vec<Box<dyn FnOnce(&mut Self) -> Result<()> + Send + Sync>>,
|
callback_list: Vec<Box<dyn FnOnce(&mut World) -> Result<()> + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiHandler {
|
impl GuiHandler {
|
||||||
|
@ -726,9 +727,13 @@ impl GuiHandler {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn accept_custom_selection(&self, button: ControllerButton) -> Result<bool> {
|
pub fn accept_custom_selection(
|
||||||
|
&self,
|
||||||
|
world: &mut World,
|
||||||
|
button: ControllerButton,
|
||||||
|
) -> Result<bool> {
|
||||||
if let Some(current_selectable) = &self.current_selectable {
|
if let Some(current_selectable) = &self.current_selectable {
|
||||||
if current_selectable.custom_click_event(button)? {
|
if current_selectable.custom_click_event(world, button)? {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -736,36 +741,36 @@ impl GuiHandler {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decline_topgui(&mut self) -> Result<bool> {
|
pub fn decline_topgui(&mut self, world: &mut World) -> Result<bool> {
|
||||||
// workaround for unwanted borrowing behaviour inside decline function
|
// workaround for unwanted borrowing behaviour inside decline function
|
||||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||||
|
|
||||||
if let Some(topgui) = opt_topgui {
|
if let Some(topgui) = opt_topgui {
|
||||||
topgui.decline(self)?;
|
topgui.decline(world)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_tab_topgui(&mut self, second_level: bool) -> Result<bool> {
|
pub fn next_tab_topgui(&mut self, world: &mut World, second_level: bool) -> Result<bool> {
|
||||||
// workaround for unwanted borrowing behaviour inside decline function
|
// workaround for unwanted borrowing behaviour inside decline function
|
||||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||||
|
|
||||||
if let Some(topgui) = opt_topgui {
|
if let Some(topgui) = opt_topgui {
|
||||||
topgui.next_tab(self, second_level)?;
|
topgui.next_tab(world, second_level)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn previous_tab_topgui(&mut self, second_level: bool) -> Result<bool> {
|
pub fn previous_tab_topgui(&mut self, world: &mut World, second_level: bool) -> Result<bool> {
|
||||||
// workaround for unwanted borrowing behaviour inside decline function
|
// workaround for unwanted borrowing behaviour inside decline function
|
||||||
let opt_topgui = self.top_ui.as_ref().cloned();
|
let opt_topgui = self.top_ui.as_ref().cloned();
|
||||||
|
|
||||||
if let Some(topgui) = opt_topgui {
|
if let Some(topgui) = opt_topgui {
|
||||||
topgui.previous_tab(self, second_level)?;
|
topgui.previous_tab(world, second_level)?;
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,19 +865,19 @@ impl GuiHandler {
|
||||||
self.tooltip_ui = tooltip;
|
self.tooltip_ui = tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_callback<F: FnOnce(&mut Self) -> Result<()> + Send + Sync + 'static>(
|
pub(crate) fn add_callback<F: FnOnce(&mut World) -> Result<()> + Send + Sync + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
f: F,
|
f: F,
|
||||||
) {
|
) {
|
||||||
self.callback_list.push(Box::new(f));
|
self.callback_list.push(Box::new(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_callbacks(&mut self) -> Result<()> {
|
pub fn process_callbacks(&mut self, world: &mut World) -> Result<()> {
|
||||||
let callbacks = mem::take(&mut self.callback_list);
|
let callbacks = mem::take(&mut self.callback_list);
|
||||||
|
|
||||||
callbacks
|
callbacks
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|callback| callback(self))
|
.try_for_each(|callback| callback(world))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(
|
fn render(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecs::World;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -25,8 +26,9 @@ pub struct Keyboard {
|
||||||
|
|
||||||
mode: Arc<RwLock<KeyboardMode>>,
|
mode: Arc<RwLock<KeyboardMode>>,
|
||||||
|
|
||||||
decline_callback: Arc<RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>>,
|
decline_callback: Arc<RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>>,
|
||||||
accept_callback: Arc<RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>>,
|
accept_callback:
|
||||||
|
Arc<RwLock<Option<Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>>>>,
|
||||||
|
|
||||||
elements: HashMap<String, UiElement>,
|
elements: HashMap<String, UiElement>,
|
||||||
}
|
}
|
||||||
|
@ -39,11 +41,11 @@ impl Keyboard {
|
||||||
let text_field: Arc<TextField> = text_field_gui.element("field")?;
|
let text_field: Arc<TextField> = text_field_gui.element("field")?;
|
||||||
|
|
||||||
let decline_callback: Arc<
|
let decline_callback: Arc<
|
||||||
RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||||
> = Arc::new(RwLock::new(None));
|
> = Arc::new(RwLock::new(None));
|
||||||
|
|
||||||
let accept_callback: Arc<
|
let accept_callback: Arc<
|
||||||
RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>,
|
RwLock<Option<Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>>>,
|
||||||
> = Arc::new(RwLock::new(None));
|
> = Arc::new(RwLock::new(None));
|
||||||
|
|
||||||
let mode = Arc::new(RwLock::new(KeyboardMode::UpperCase));
|
let mode = Arc::new(RwLock::new(KeyboardMode::UpperCase));
|
||||||
|
@ -84,10 +86,10 @@ impl Keyboard {
|
||||||
gui_handler: &mut GuiHandler,
|
gui_handler: &mut GuiHandler,
|
||||||
textfield: Arc<TextField>,
|
textfield: Arc<TextField>,
|
||||||
mode: &Arc<RwLock<KeyboardMode>>,
|
mode: &Arc<RwLock<KeyboardMode>>,
|
||||||
decline_callback: Arc<
|
decline_callback: Arc<RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>>,
|
||||||
RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
accept_callback: Arc<
|
||||||
|
RwLock<Option<Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>>>,
|
||||||
>,
|
>,
|
||||||
accept_callback: Arc<RwLock<Option<Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>>>>,
|
|
||||||
) -> Result<(Arc<GuiBuilder>, Arc<GuiBuilder>, Arc<GuiBuilder>)> {
|
) -> Result<(Arc<GuiBuilder>, Arc<GuiBuilder>, Arc<GuiBuilder>)> {
|
||||||
let lower_case = GuiBuilder::from_str(gui_handler, include_str!("lower_case.xml"))?;
|
let lower_case = GuiBuilder::from_str(gui_handler, include_str!("lower_case.xml"))?;
|
||||||
let upper_case = GuiBuilder::from_str(gui_handler, include_str!("upper_case.xml"))?;
|
let upper_case = GuiBuilder::from_str(gui_handler, include_str!("upper_case.xml"))?;
|
||||||
|
@ -193,9 +195,9 @@ impl Keyboard {
|
||||||
Self::set_text_callback(&specials, ".", textfield.clone())?;
|
Self::set_text_callback(&specials, ".", textfield.clone())?;
|
||||||
Self::set_text_callback(&specials, "_", textfield.clone())?;
|
Self::set_text_callback(&specials, "_", textfield.clone())?;
|
||||||
|
|
||||||
let back = Box::new(move |gui_handler: &mut GuiHandler| {
|
let back = Box::new(move |world: &mut World| {
|
||||||
if let Some(callback) = decline_callback.read().unwrap().as_ref() {
|
if let Some(callback) = decline_callback.read().unwrap().as_ref() {
|
||||||
(callback)(gui_handler)?;
|
(callback)(world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -205,12 +207,12 @@ impl Keyboard {
|
||||||
let weak_textfield = Arc::downgrade(&textfield);
|
let weak_textfield = Arc::downgrade(&textfield);
|
||||||
let weak_accept = Arc::downgrade(&accept_callback);
|
let weak_accept = Arc::downgrade(&accept_callback);
|
||||||
|
|
||||||
Box::new(move |_: &mut GuiHandler| {
|
Box::new(move |world: &mut World| {
|
||||||
if let Some(textfield) = weak_textfield.upgrade() {
|
if let Some(textfield) = weak_textfield.upgrade() {
|
||||||
if let Some(accept_callback) = weak_accept.upgrade() {
|
if let Some(accept_callback) = weak_accept.upgrade() {
|
||||||
if let Some(text) = textfield.text() {
|
if let Some(text) = textfield.text() {
|
||||||
if let Some(callback) = accept_callback.read().unwrap().as_ref() {
|
if let Some(callback) = accept_callback.read().unwrap().as_ref() {
|
||||||
(callback)(&text)?;
|
(callback)(world, &text)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,13 +227,16 @@ impl Keyboard {
|
||||||
let weak_lower = Arc::downgrade(&lower_case);
|
let weak_lower = Arc::downgrade(&lower_case);
|
||||||
let weak_upper = Arc::downgrade(&upper_case);
|
let weak_upper = Arc::downgrade(&upper_case);
|
||||||
|
|
||||||
Box::new(move |gui_handler: &mut GuiHandler| {
|
Box::new(move |world: &mut World| {
|
||||||
if let Some(lower) = weak_lower.upgrade() {
|
if let Some(lower) = weak_lower.upgrade() {
|
||||||
if let Some(upper) = weak_upper.upgrade() {
|
if let Some(upper) = weak_upper.upgrade() {
|
||||||
let mut mode = mode.write().unwrap();
|
let mut mode = mode.write().unwrap();
|
||||||
|
|
||||||
if let KeyboardMode::LowerCase = mode.deref() {
|
if let KeyboardMode::LowerCase = mode.deref() {
|
||||||
*mode = KeyboardMode::UpperCase;
|
*mode = KeyboardMode::UpperCase;
|
||||||
|
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
|
|
||||||
lower.disable(gui_handler)?;
|
lower.disable(gui_handler)?;
|
||||||
upper.enable(gui_handler)?;
|
upper.enable(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
@ -247,13 +252,16 @@ impl Keyboard {
|
||||||
let weak_upper = Arc::downgrade(&upper_case);
|
let weak_upper = Arc::downgrade(&upper_case);
|
||||||
let weak_specials = Arc::downgrade(&specials);
|
let weak_specials = Arc::downgrade(&specials);
|
||||||
|
|
||||||
Box::new(move |gui_handler: &mut GuiHandler| {
|
Box::new(move |world: &mut World| {
|
||||||
if let Some(specials) = weak_specials.upgrade() {
|
if let Some(specials) = weak_specials.upgrade() {
|
||||||
if let Some(upper) = weak_upper.upgrade() {
|
if let Some(upper) = weak_upper.upgrade() {
|
||||||
let mut mode = mode.write().unwrap();
|
let mut mode = mode.write().unwrap();
|
||||||
|
|
||||||
if let KeyboardMode::UpperCase = mode.deref() {
|
if let KeyboardMode::UpperCase = mode.deref() {
|
||||||
*mode = KeyboardMode::Specials;
|
*mode = KeyboardMode::Specials;
|
||||||
|
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
|
|
||||||
upper.disable(gui_handler)?;
|
upper.disable(gui_handler)?;
|
||||||
specials.enable(gui_handler)?;
|
specials.enable(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
@ -269,13 +277,16 @@ impl Keyboard {
|
||||||
let weak_lower = Arc::downgrade(&lower_case);
|
let weak_lower = Arc::downgrade(&lower_case);
|
||||||
let weak_specials = Arc::downgrade(&specials);
|
let weak_specials = Arc::downgrade(&specials);
|
||||||
|
|
||||||
Box::new(move |gui_handler: &mut GuiHandler| {
|
Box::new(move |world: &mut World| {
|
||||||
if let Some(lower) = weak_lower.upgrade() {
|
if let Some(lower) = weak_lower.upgrade() {
|
||||||
if let Some(specials) = weak_specials.upgrade() {
|
if let Some(specials) = weak_specials.upgrade() {
|
||||||
let mut mode = mode.write().unwrap();
|
let mut mode = mode.write().unwrap();
|
||||||
|
|
||||||
if let KeyboardMode::Specials = mode.deref() {
|
if let KeyboardMode::Specials = mode.deref() {
|
||||||
*mode = KeyboardMode::LowerCase;
|
*mode = KeyboardMode::LowerCase;
|
||||||
|
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
|
|
||||||
specials.disable(gui_handler)?;
|
specials.disable(gui_handler)?;
|
||||||
lower.enable(gui_handler)?;
|
lower.enable(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
@ -289,8 +300,9 @@ impl Keyboard {
|
||||||
let space_bar = {
|
let space_bar = {
|
||||||
let weak_textfield = Arc::downgrade(&textfield);
|
let weak_textfield = Arc::downgrade(&textfield);
|
||||||
|
|
||||||
Box::new(move |gui_handler: &mut GuiHandler| {
|
Box::new(move |world: &mut World| {
|
||||||
if let Some(text_field) = weak_textfield.upgrade() {
|
if let Some(text_field) = weak_textfield.upgrade() {
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
text_field.add_letter(gui_handler, ' ')?;
|
text_field.add_letter(gui_handler, ' ')?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,10 +342,11 @@ impl Keyboard {
|
||||||
let weak_textfield = Arc::downgrade(&textfield);
|
let weak_textfield = Arc::downgrade(&textfield);
|
||||||
let weak_button = Arc::downgrade(&button_ref);
|
let weak_button = Arc::downgrade(&button_ref);
|
||||||
|
|
||||||
button_ref.set_callback(Box::new(move |gui_handler: &mut GuiHandler| {
|
button_ref.set_callback(Box::new(move |world: &mut World| {
|
||||||
if let Some(textfield) = weak_textfield.upgrade() {
|
if let Some(textfield) = weak_textfield.upgrade() {
|
||||||
if let Some(button) = weak_button.upgrade() {
|
if let Some(button) = weak_button.upgrade() {
|
||||||
if let Some(text) = button.text()? {
|
if let Some(text) = button.text()? {
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
textfield.add_letter(gui_handler, text.as_bytes()[0] as char)?;
|
textfield.add_letter(gui_handler, text.as_bytes()[0] as char)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,21 +360,22 @@ impl Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopGui for Keyboard {
|
impl TopGui for Keyboard {
|
||||||
fn decline(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
fn decline(&self, world: &mut World) -> Result<()> {
|
||||||
if let Some(callback) = self.decline_callback.read().unwrap().as_ref() {
|
if let Some(callback) = self.decline_callback.read().unwrap().as_ref() {
|
||||||
(callback)(gui_handler)?;
|
(callback)(world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tab(&self, _gui_handler: &mut GuiHandler, _: bool) -> Result<()> {
|
fn next_tab(&self, _world: &mut World, _: bool) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()> {
|
fn previous_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||||
// abuse event
|
// abuse event
|
||||||
if !second_level {
|
if !second_level {
|
||||||
|
let gui_handler = world.resources.get_mut::<GuiHandler>();
|
||||||
self.text_field.remove_last(gui_handler)?;
|
self.text_field.remove_last(gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,21 +463,22 @@ impl TopLevelGui for Keyboard {
|
||||||
impl Functionality for Keyboard {
|
impl Functionality for Keyboard {
|
||||||
fn set_click_callbacks(
|
fn set_click_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(
|
callbacks: Vec<(&str, Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>)>,
|
||||||
&str,
|
|
||||||
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
|
||||||
)>,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (name, callback) in callbacks {
|
if let Some((_, callback)) = callbacks.into_iter().find(|(name, _)| *name == "decline") {
|
||||||
if name == "decline" {
|
*self.decline_callback.write().unwrap() = Some(callback);
|
||||||
*self.decline_callback.write().unwrap() = Some(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_select_callbacks(&self, _: Vec<(&str, Box<CustomCallback<bool, ()>>)>) -> Result<()> {
|
fn set_select_callbacks(
|
||||||
|
&self,
|
||||||
|
_: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, bool) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +486,7 @@ impl Functionality for Keyboard {
|
||||||
&self,
|
&self,
|
||||||
_: Vec<(
|
_: Vec<(
|
||||||
&str,
|
&str,
|
||||||
Box<dyn Fn(ControllerButton) -> Result<bool> + Send + Sync>,
|
Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>,
|
||||||
)>,
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -479,7 +494,10 @@ impl Functionality for Keyboard {
|
||||||
|
|
||||||
fn set_vec_callbacks(
|
fn set_vec_callbacks(
|
||||||
&self,
|
&self,
|
||||||
callbacks: Vec<(&str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>,
|
callbacks: Vec<(
|
||||||
|
&str,
|
||||||
|
Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for (name, callback) in callbacks {
|
for (name, callback) in callbacks {
|
||||||
if name == "accept" {
|
if name == "accept" {
|
||||||
|
|
|
@ -13,5 +13,3 @@ mod element_creator;
|
||||||
mod gui_direction;
|
mod gui_direction;
|
||||||
mod mouse_button;
|
mod mouse_button;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
|
||||||
pub type CustomCallback<I, O> = dyn Fn(I) -> anyhow::Result<O> + Send + Sync;
|
|
||||||
|
|
|
@ -9,5 +9,3 @@ pub use super::keyboard::Keyboard;
|
||||||
pub use super::mouse_button::MouseButton;
|
pub use super::mouse_button::MouseButton;
|
||||||
pub use super::states::*;
|
pub use super::states::*;
|
||||||
pub use super::tab_control::TabControl;
|
pub use super::tab_control::TabControl;
|
||||||
|
|
||||||
pub use super::CustomCallback;
|
|
||||||
|
|
116
src/states.rs
116
src/states.rs
|
@ -1,18 +1,20 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
|
use ecs::World;
|
||||||
|
use utilities::prelude::remove_life_time_mut;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, RwLock, Weak};
|
use std::sync::{Arc, Mutex, RwLock, Weak};
|
||||||
|
|
||||||
pub trait FutureStateChange: Fn(&mut GuiHandler) -> Result<()> + Send + Sync {
|
pub trait FutureStateChange: Fn(&mut World) -> Result<()> + Send + Sync {
|
||||||
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
fn as_fn(&self) -> &(dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync)
|
fn as_fn(&self) -> &(dyn Fn(&mut World) -> Result<()> + Send + Sync)
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -21,7 +23,7 @@ pub trait FutureStateChange: Fn(&mut GuiHandler) -> Result<()> + Send + Sync {
|
||||||
|
|
||||||
fn as_static(
|
fn as_static(
|
||||||
&'static self,
|
&'static self,
|
||||||
) -> &'static (dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync + 'static)
|
) -> &'static (dyn Fn(&mut World) -> Result<()> + Send + Sync + 'static)
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -29,7 +31,7 @@ pub trait FutureStateChange: Fn(&mut GuiHandler) -> Result<()> + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Fn(&mut GuiHandler) -> Result<()> + Clone + Send + Sync> FutureStateChange for F {
|
impl<F: Fn(&mut World) -> Result<()> + Clone + Send + Sync> FutureStateChange for F {
|
||||||
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
fn clone_box<'a>(&self) -> Box<dyn 'a + FutureStateChange>
|
||||||
where
|
where
|
||||||
Self: 'a,
|
Self: 'a,
|
||||||
|
@ -49,12 +51,12 @@ struct State {
|
||||||
|
|
||||||
top_level_gui: Arc<dyn TopLevelGui>,
|
top_level_gui: Arc<dyn TopLevelGui>,
|
||||||
|
|
||||||
on_activate: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
on_activate: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||||
on_deactivate: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
on_deactivate: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||||
|
|
||||||
next_tab: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
next_tab: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||||
previous_tab: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
previous_tab: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||||
decline: RwLock<Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>>,
|
decline: RwLock<Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opaque handle for a State
|
/// Opaque handle for a State
|
||||||
|
@ -150,36 +152,46 @@ impl GetElement<ProgressBar> for StateHandle {
|
||||||
/// Update type
|
/// Update type
|
||||||
pub enum StateUpdateType<'a> {
|
pub enum StateUpdateType<'a> {
|
||||||
/// Updates the callback which is executed on next tab event
|
/// Updates the callback which is executed on next tab event
|
||||||
NextTab(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
NextTab(Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates the callback which is executed on previous tab event
|
/// Updates the callback which is executed on previous tab event
|
||||||
PreviousTab(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
PreviousTab(Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates the callback which is executed on decline event
|
/// Updates the callback which is executed on decline event
|
||||||
Decline(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
Decline(Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates callbacks by identifier
|
/// Updates callbacks by identifier
|
||||||
ClickCallbacks(
|
ClickCallbacks(Vec<(&'a str, Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>)>),
|
||||||
|
|
||||||
|
/// Updates callbacks by identifier
|
||||||
|
SelectCallbacks(
|
||||||
Vec<(
|
Vec<(
|
||||||
&'a str,
|
&'a str,
|
||||||
Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>,
|
Box<dyn Fn(&mut World, bool) -> Result<()> + Send + Sync>,
|
||||||
)>,
|
)>,
|
||||||
),
|
),
|
||||||
|
|
||||||
/// Updates callbacks by identifier
|
/// Updates callbacks by identifier
|
||||||
SelectCallbacks(Vec<(&'a str, Box<CustomCallback<bool, ()>>)>),
|
CustomClickCallbacks(
|
||||||
|
Vec<(
|
||||||
/// Updates callbacks by identifier
|
&'a str,
|
||||||
CustomClickCallbacks(Vec<(&'a str, Box<CustomCallback<ControllerButton, bool>>)>),
|
Box<dyn Fn(&mut World, ControllerButton) -> Result<bool> + Send + Sync>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
|
||||||
/// Updates callbacks by identifier with input parameters
|
/// Updates callbacks by identifier with input parameters
|
||||||
VecCallbacks(Vec<(&'a str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>),
|
VecCallbacks(
|
||||||
|
Vec<(
|
||||||
|
&'a str,
|
||||||
|
Box<dyn Fn(&mut World, &dyn Any) -> Result<()> + Send + Sync>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
|
|
||||||
/// Updates the callback which is executed when this state gets activated on state change
|
/// Updates the callback which is executed when this state gets activated on state change
|
||||||
OnActivate(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
OnActivate(Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>),
|
||||||
|
|
||||||
/// Updates the callback which is executed when this state gets deactivated on state change
|
/// Updates the callback which is executed when this state gets deactivated on state change
|
||||||
OnDeactivate(Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>),
|
OnDeactivate(Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type of the state to be created
|
/// Type of the state to be created
|
||||||
|
@ -274,14 +286,13 @@ impl States {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `id` - Set state with the given identifier or None
|
/// * `id` - Set state with the given identifier or None
|
||||||
pub fn set_state<'b>(
|
pub fn set_state<'b>(&self, world: &mut World, id: impl Into<Option<&'b str>>) -> Result<()> {
|
||||||
&self,
|
let gui_handler = unsafe { remove_life_time_mut(world.resources.get_mut::<GuiHandler>()) };
|
||||||
gui_handler: &mut GuiHandler,
|
|
||||||
id: impl Into<Option<&'b str>>,
|
|
||||||
) -> Result<()> {
|
|
||||||
Self::_set_state(
|
Self::_set_state(
|
||||||
id.into().map(|id| self.get_state(id)).transpose()?,
|
id.into().map(|id| self.get_state(id)).transpose()?,
|
||||||
&mut *self.current_state.lock().unwrap(),
|
&mut *self.current_state.lock().unwrap(),
|
||||||
|
world,
|
||||||
gui_handler,
|
gui_handler,
|
||||||
self.log_state_change,
|
self.log_state_change,
|
||||||
)
|
)
|
||||||
|
@ -290,6 +301,7 @@ impl States {
|
||||||
fn _set_state(
|
fn _set_state(
|
||||||
state: Option<Arc<State>>,
|
state: Option<Arc<State>>,
|
||||||
current: &mut Option<Arc<State>>,
|
current: &mut Option<Arc<State>>,
|
||||||
|
world: &mut World,
|
||||||
gui_handler: &mut GuiHandler,
|
gui_handler: &mut GuiHandler,
|
||||||
logging: bool,
|
logging: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -302,13 +314,13 @@ impl States {
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute deactivate on old state
|
// execute deactivate on old state
|
||||||
old_state.deactivate(gui_handler)?;
|
old_state.deactivate(world, gui_handler)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set new state, either no state or requested state
|
// set new state, either no state or requested state
|
||||||
match state {
|
match state {
|
||||||
Some(state) => {
|
Some(state) => {
|
||||||
state.activate(gui_handler)?;
|
state.activate(world, gui_handler)?;
|
||||||
gui_handler.set_top_gui(Some(state.clone()));
|
gui_handler.set_top_gui(Some(state.clone()));
|
||||||
|
|
||||||
if logging {
|
if logging {
|
||||||
|
@ -354,11 +366,15 @@ impl States {
|
||||||
let weak_current_state = Arc::downgrade(&self.current_state);
|
let weak_current_state = Arc::downgrade(&self.current_state);
|
||||||
let logging = self.log_state_change;
|
let logging = self.log_state_change;
|
||||||
|
|
||||||
Ok(Box::new(move |gui_handler: &mut GuiHandler| {
|
Ok(Box::new(move |world: &mut World| {
|
||||||
if let Some(current) = weak_current_state.upgrade() {
|
if let Some(current) = weak_current_state.upgrade() {
|
||||||
|
let gui_handler =
|
||||||
|
unsafe { remove_life_time_mut(world.resources.get_mut::<GuiHandler>()) };
|
||||||
|
|
||||||
Self::_set_state(
|
Self::_set_state(
|
||||||
weak_state.as_ref().map(|w| w.upgrade()).flatten(),
|
weak_state.as_ref().map(|w| w.upgrade()).flatten(),
|
||||||
&mut *current.lock().unwrap(),
|
&mut *current.lock().unwrap(),
|
||||||
|
world,
|
||||||
gui_handler,
|
gui_handler,
|
||||||
logging,
|
logging,
|
||||||
)?;
|
)?;
|
||||||
|
@ -429,21 +445,21 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
fn activate(&self, world: &mut World, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.top_level_gui.enable(gui_handler)?;
|
self.top_level_gui.enable(gui_handler)?;
|
||||||
|
|
||||||
if let Some(activate) = self.on_activate.read().unwrap().as_ref() {
|
if let Some(activate) = self.on_activate.read().unwrap().as_ref() {
|
||||||
(activate)(gui_handler)?;
|
(activate)(world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
fn deactivate(&self, world: &mut World, gui_handler: &mut GuiHandler) -> Result<()> {
|
||||||
self.top_level_gui.disable(gui_handler)?;
|
self.top_level_gui.disable(gui_handler)?;
|
||||||
|
|
||||||
if let Some(deactivate) = self.on_deactivate.read().unwrap().as_ref() {
|
if let Some(deactivate) = self.on_deactivate.read().unwrap().as_ref() {
|
||||||
(deactivate)(gui_handler)?;
|
(deactivate)(world)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -451,49 +467,43 @@ impl State {
|
||||||
|
|
||||||
fn set_on_activate(
|
fn set_on_activate(
|
||||||
&self,
|
&self,
|
||||||
on_activate: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
on_activate: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||||
) {
|
) {
|
||||||
*self.on_activate.write().unwrap() = on_activate;
|
*self.on_activate.write().unwrap() = on_activate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_on_deactivate(
|
fn set_on_deactivate(
|
||||||
&self,
|
&self,
|
||||||
on_deactivate: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
on_deactivate: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||||
) {
|
) {
|
||||||
*self.on_deactivate.write().unwrap() = on_deactivate;
|
*self.on_deactivate.write().unwrap() = on_deactivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_previous_tab(
|
fn set_previous_tab(
|
||||||
&self,
|
&self,
|
||||||
previous_tab: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
previous_tab: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>,
|
||||||
) {
|
) {
|
||||||
*self.previous_tab.write().unwrap() = previous_tab;
|
*self.previous_tab.write().unwrap() = previous_tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_next_tab(
|
fn set_next_tab(&self, next_tab: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>) {
|
||||||
&self,
|
|
||||||
next_tab: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
|
||||||
) {
|
|
||||||
*self.next_tab.write().unwrap() = next_tab;
|
*self.next_tab.write().unwrap() = next_tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_decline(
|
fn set_decline(&self, decline: Option<Box<dyn Fn(&mut World) -> Result<()> + Send + Sync>>) {
|
||||||
&self,
|
|
||||||
decline: Option<Box<dyn Fn(&mut GuiHandler) -> Result<()> + Send + Sync>>,
|
|
||||||
) {
|
|
||||||
*self.decline.write().unwrap() = decline;
|
*self.decline.write().unwrap() = decline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopGui for State {
|
impl TopGui for State {
|
||||||
fn decline(&self, gui_handler: &mut GuiHandler) -> Result<()> {
|
fn decline(&self, world: &mut World) -> Result<()> {
|
||||||
match self.decline.read().unwrap().as_ref() {
|
match self.decline.read().unwrap().as_ref() {
|
||||||
Some(decline) => {
|
Some(decline) => {
|
||||||
(decline)(gui_handler)?;
|
(decline)(world)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||||
top_gui.decline(gui_handler)?;
|
top_gui.decline(world)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,14 +511,14 @@ impl TopGui for State {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()> {
|
fn next_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||||
match self.next_tab.read().unwrap().as_ref() {
|
match self.next_tab.read().unwrap().as_ref() {
|
||||||
Some(next_tab) => {
|
Some(next_tab) => {
|
||||||
(next_tab)(gui_handler)?;
|
(next_tab)(world)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||||
top_gui.next_tab(gui_handler, second_level)?;
|
top_gui.next_tab(world, second_level)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,14 +526,14 @@ impl TopGui for State {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous_tab(&self, gui_handler: &mut GuiHandler, second_level: bool) -> Result<()> {
|
fn previous_tab(&self, world: &mut World, second_level: bool) -> Result<()> {
|
||||||
match self.previous_tab.read().unwrap().as_ref() {
|
match self.previous_tab.read().unwrap().as_ref() {
|
||||||
Some(previous_tab) => {
|
Some(previous_tab) => {
|
||||||
(previous_tab)(gui_handler)?;
|
(previous_tab)(world)?;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
if let Some(top_gui) = self.top_level_gui.top_gui() {
|
||||||
top_gui.previous_tab(gui_handler, second_level)?;
|
top_gui.previous_tab(world, second_level)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue