dialog WIP paths consolidation and rendering

This commit is contained in:
Jonas H
2026-03-28 10:34:19 +01:00
parent 4c3ebca96e
commit 11b31169b1
70 changed files with 2658 additions and 485 deletions

View File

@@ -1,28 +1,30 @@
use std::any::{Any, TypeId};
use std::any::TypeId;
use std::collections::HashMap;
use crate::world::World;
use crate::entity::EntityHandle;
use crate::world::{Storage, World};
pub trait StateAgent {}
pub trait State: Any
pub trait PlayerState
{
fn get_state_name(&self) -> &'static str;
fn on_state_enter(&mut self, world: &mut World) {}
fn on_state_exit(&mut self, world: &mut World) {}
fn on_state_update(&mut self, world: &mut World, delta: f32) {}
fn on_state_physics_update(&mut self, world: &mut World, delta: f32) {}
fn tick_time(&mut self, _delta: f32) {}
fn on_enter(&mut self, _world: &mut World, _entity: EntityHandle) {}
fn on_exit(&mut self, _world: &mut World, _entity: EntityHandle) {}
fn on_update(&mut self, _world: &mut World, _entity: EntityHandle, _delta: f32) {}
fn on_physics_update(&mut self, _world: &mut World, _entity: EntityHandle, _delta: f32) {}
}
impl dyn State
struct StateOps
{
fn dyn_type_id(&self) -> std::any::TypeId
{
Any::type_id(self)
}
name: &'static str,
remove: Box<dyn Fn(&mut World, EntityHandle)>,
insert_default: Box<dyn Fn(&mut World, EntityHandle)>,
on_enter: Box<dyn Fn(&mut World, EntityHandle)>,
on_exit: Box<dyn Fn(&mut World, EntityHandle)>,
tick: Box<dyn Fn(&mut World, EntityHandle, f32)>,
physics_tick: Box<dyn Fn(&mut World, EntityHandle, f32)>,
}
pub struct StateTransition
struct StateTransition
{
to_state_id: TypeId,
condition: Box<dyn Fn(&World) -> bool>,
@@ -30,42 +32,93 @@ pub struct StateTransition
pub struct StateMachine
{
state_ops: HashMap<TypeId, StateOps>,
state_transitions: HashMap<TypeId, Vec<StateTransition>>,
current_state_id: TypeId,
states: HashMap<TypeId, Box<dyn State>>,
pub time_in_state: f32,
}
fn short_type_name<T: 'static>() -> &'static str
{
let full = std::any::type_name::<T>();
full.rsplit("::").next().unwrap_or(full)
}
impl StateMachine
{
pub fn new(enter_state: Box<dyn State>) -> Self
pub fn new<S: 'static>() -> Self
{
let state_id = enter_state.dyn_type_id();
let mut states = HashMap::new();
states.insert(state_id, enter_state);
Self {
state_ops: HashMap::new(),
state_transitions: HashMap::new(),
current_state_id: state_id,
states,
time_in_state: 0.0,
current_state_id: TypeId::of::<S>(),
}
}
pub fn update(&mut self, world: &mut World, delta: f32)
pub fn register_state<S: PlayerState + Default + 'static>(
&mut self,
storage: fn(&mut World) -> &mut Storage<S>,
)
{
let ops = StateOps {
name: short_type_name::<S>(),
remove: Box::new(move |world, entity| {
storage(world).components.remove(&entity);
}),
insert_default: Box::new(move |world, entity| {
storage(world).insert(entity, S::default());
}),
on_enter: Box::new(move |world, entity| {
if let Some(mut state) = storage(world).components.remove(&entity)
{
state.on_enter(world, entity);
storage(world).insert(entity, state);
}
}),
on_exit: Box::new(move |world, entity| {
if let Some(mut state) = storage(world).components.remove(&entity)
{
state.on_exit(world, entity);
storage(world).insert(entity, state);
}
}),
tick: Box::new(move |world, entity, delta| {
if let Some(mut state) = storage(world).components.remove(&entity)
{
state.tick_time(delta);
state.on_update(world, entity, delta);
storage(world).insert(entity, state);
}
}),
physics_tick: Box::new(move |world, entity, delta| {
if let Some(mut state) = storage(world).components.remove(&entity)
{
state.on_physics_update(world, entity, delta);
storage(world).insert(entity, state);
}
}),
};
self.state_ops.insert(TypeId::of::<S>(), ops);
}
pub fn update(&mut self, world: &mut World, entity: EntityHandle, delta: f32)
{
if let Some(next_state_id) = self.get_transition_state_id(world)
{
self.time_in_state = 0.0;
self.transition_to(world, next_state_id);
self.apply_transition(world, entity, next_state_id);
}
if let Some(current_state) = self.states.get_mut(&self.current_state_id)
if let Some(ops) = self.state_ops.get(&self.current_state_id)
{
current_state.on_state_update(world, delta);
(ops.tick)(world, entity, delta);
}
}
self.time_in_state += delta;
pub fn physics_update(&mut self, world: &mut World, entity: EntityHandle, delta: f32)
{
if let Some(ops) = self.state_ops.get(&self.current_state_id)
{
(ops.physics_tick)(world, entity, delta);
}
}
fn get_transition_state_id(&self, world: &World) -> Option<TypeId>
@@ -83,47 +136,30 @@ impl StateMachine
None
}
fn transition_to(&mut self, world: &mut World, new_state_id: TypeId)
fn apply_transition(&mut self, world: &mut World, entity: EntityHandle, next_id: TypeId)
{
if let Some(current_state) = self.states.get_mut(&self.current_state_id)
if let Some(ops) = self.state_ops.get(&self.current_state_id)
{
current_state.on_state_exit(world);
(ops.on_exit)(world, entity);
(ops.remove)(world, entity);
}
self.current_state_id = new_state_id;
self.current_state_id = next_id;
if let Some(new_state) = self.states.get_mut(&self.current_state_id)
if let Some(ops) = self.state_ops.get(&next_id)
{
new_state.on_state_enter(world);
(ops.insert_default)(world, entity);
(ops.on_enter)(world, entity);
}
}
pub fn get_current_state(&self) -> Option<&dyn State>
{
self.states.get(&self.current_state_id).map(|b| b.as_ref())
}
pub fn get_current_state_mut(&mut self) -> Option<&mut dyn State>
{
self.states
.get_mut(&self.current_state_id)
.map(|b| b.as_mut())
}
pub fn add_state<T: State + 'static>(&mut self, state: T)
{
let state_id = TypeId::of::<T>();
self.states.insert(state_id, Box::new(state));
}
pub fn add_transition<TFrom: State + 'static, TTo: State + 'static>(
pub fn add_transition<TFrom: 'static, TTo: 'static>(
&mut self,
condition: impl Fn(&World) -> bool + 'static,
)
{
let from_id = TypeId::of::<TFrom>();
let to_id = TypeId::of::<TTo>();
let transitions = self.state_transitions.entry(from_id).or_default();
transitions.push(StateTransition {
to_state_id: to_id,
@@ -131,11 +167,11 @@ impl StateMachine
});
}
pub fn get_available_transitions_count(&self) -> usize
pub fn get_current_state_name(&self) -> &'static str
{
self.state_transitions
self.state_ops
.get(&self.current_state_id)
.map(|transitions| transitions.len())
.unwrap_or(0)
.map(|ops| ops.name)
.unwrap_or("Unknown")
}
}