2019-08-21 01:19:02 +00:00
|
|
|
mod cache;
|
2020-02-29 03:59:11 +00:00
|
|
|
pub mod load;
|
2019-08-21 01:19:02 +00:00
|
|
|
|
|
|
|
pub use cache::FigureModelCache;
|
|
|
|
pub use load::load_mesh; // TODO: Don't make this public.
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
anim::{
|
2019-10-26 02:20:38 +00:00
|
|
|
self, biped_large::BipedLargeSkeleton, bird_medium::BirdMediumSkeleton,
|
2020-01-26 00:22:48 +00:00
|
|
|
bird_small::BirdSmallSkeleton, character::CharacterSkeleton, critter::CritterSkeleton,
|
|
|
|
dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton,
|
|
|
|
object::ObjectSkeleton, quadruped_medium::QuadrupedMediumSkeleton,
|
|
|
|
quadruped_small::QuadrupedSmallSkeleton, Animation, Skeleton,
|
2019-08-21 01:19:02 +00:00
|
|
|
},
|
2020-03-21 03:23:46 +00:00
|
|
|
ecs::comp::Interpolated,
|
2019-09-25 12:00:00 +00:00
|
|
|
render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow},
|
2020-02-29 03:59:11 +00:00
|
|
|
scene::{
|
|
|
|
camera::{Camera, CameraMode},
|
|
|
|
SceneData,
|
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
};
|
|
|
|
use common::{
|
|
|
|
comp::{
|
2020-03-28 05:51:52 +00:00
|
|
|
item::ItemKind, Body, CharacterState, Last, Loadout, Ori, PhysicsState, Pos, Scale, Stats,
|
|
|
|
Vel,
|
2019-08-21 01:19:02 +00:00
|
|
|
},
|
2020-02-29 03:59:11 +00:00
|
|
|
state::State,
|
2020-03-25 05:37:09 +00:00
|
|
|
states::triple_strike,
|
common: Rework volume API
See the doc comments in `common/src/vol.rs` for more information on
the API itself.
The changes include:
* Consistent `Err`/`Error` naming.
* Types are named `...Error`.
* `enum` variants are named `...Err`.
* Rename `VolMap{2d, 3d}` -> `VolGrid{2d, 3d}`. This is in preparation
to an upcoming change where a “map” in the game related sense will
be added.
* Add volume iterators. There are two types of them:
* _Position_ iterators obtained from the trait `IntoPosIterator`
using the method
`fn pos_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `Vec3<i32>`.
* _Volume_ iterators obtained from the trait `IntoVolIterator`
using the method
`fn vol_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `(Vec3<i32>, &Self::Vox)`.
Those traits will usually be implemented by references to volume
types (i.e. `impl IntoVolIterator<'a> for &'a T` where `T` is some
type which usually implements several volume traits, such as `Chunk`).
* _Position_ iterators iterate over the positions valid for that
volume.
* _Volume_ iterators do the same but return not only the position
but also the voxel at that position, in each iteration.
* Introduce trait `RectSizedVol` for the use case which we have with
`Chonk`: A `Chonk` is sized only in x and y direction.
* Introduce traits `RasterableVol`, `RectRasterableVol`
* `RasterableVol` represents a volume that is compile-time sized and has
its lower bound at `(0, 0, 0)`. The name `RasterableVol` was chosen
because such a volume can be used with `VolGrid3d`.
* `RectRasterableVol` represents a volume that is compile-time sized at
least in x and y direction and has its lower bound at `(0, 0, z)`.
There's no requirement on he lower bound or size in z direction.
The name `RectRasterableVol` was chosen because such a volume can be
used with `VolGrid2d`.
2019-09-03 22:23:29 +00:00
|
|
|
terrain::TerrainChunk,
|
|
|
|
vol::RectRasterableVol,
|
2019-08-21 01:19:02 +00:00
|
|
|
};
|
|
|
|
use hashbrown::HashMap;
|
2019-10-15 14:06:37 +00:00
|
|
|
use log::trace;
|
2019-11-30 06:41:20 +00:00
|
|
|
use specs::{Entity as EcsEntity, Join, WorldExt};
|
2020-01-08 17:09:54 +00:00
|
|
|
use treeculler::{BVol, BoundingSphere};
|
2019-09-01 21:46:30 +00:00
|
|
|
use vek::*;
|
2019-08-21 01:19:02 +00:00
|
|
|
|
|
|
|
const DAMAGE_FADE_COEFFICIENT: f64 = 5.0;
|
2020-03-28 05:51:52 +00:00
|
|
|
const MOVING_THRESHOLD: f32 = 0.7;
|
|
|
|
const MOVING_THRESHOLD_SQR: f32 = MOVING_THRESHOLD * MOVING_THRESHOLD;
|
2019-08-21 01:19:02 +00:00
|
|
|
|
|
|
|
pub struct FigureMgr {
|
|
|
|
model_cache: FigureModelCache,
|
2020-01-26 00:22:48 +00:00
|
|
|
critter_model_cache: FigureModelCache<CritterSkeleton>,
|
|
|
|
quadruped_small_model_cache: FigureModelCache<QuadrupedSmallSkeleton>,
|
|
|
|
quadruped_medium_model_cache: FigureModelCache<QuadrupedMediumSkeleton>,
|
|
|
|
bird_medium_model_cache: FigureModelCache<BirdMediumSkeleton>,
|
|
|
|
bird_small_model_cache: FigureModelCache<BirdSmallSkeleton>,
|
|
|
|
dragon_model_cache: FigureModelCache<DragonSkeleton>,
|
|
|
|
fish_medium_model_cache: FigureModelCache<FishMediumSkeleton>,
|
|
|
|
fish_small_model_cache: FigureModelCache<FishSmallSkeleton>,
|
|
|
|
biped_large_model_cache: FigureModelCache<BipedLargeSkeleton>,
|
2019-08-21 01:19:02 +00:00
|
|
|
character_states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
|
2019-10-26 02:20:38 +00:00
|
|
|
quadruped_small_states: HashMap<EcsEntity, FigureState<QuadrupedSmallSkeleton>>,
|
2019-08-21 01:19:02 +00:00
|
|
|
quadruped_medium_states: HashMap<EcsEntity, FigureState<QuadrupedMediumSkeleton>>,
|
2019-10-23 02:56:45 +00:00
|
|
|
bird_medium_states: HashMap<EcsEntity, FigureState<BirdMediumSkeleton>>,
|
|
|
|
fish_medium_states: HashMap<EcsEntity, FigureState<FishMediumSkeleton>>,
|
2020-01-26 00:22:48 +00:00
|
|
|
critter_states: HashMap<EcsEntity, FigureState<CritterSkeleton>>,
|
2019-10-23 04:59:05 +00:00
|
|
|
dragon_states: HashMap<EcsEntity, FigureState<DragonSkeleton>>,
|
2019-10-24 01:10:26 +00:00
|
|
|
bird_small_states: HashMap<EcsEntity, FigureState<BirdSmallSkeleton>>,
|
|
|
|
fish_small_states: HashMap<EcsEntity, FigureState<FishSmallSkeleton>>,
|
|
|
|
biped_large_states: HashMap<EcsEntity, FigureState<BipedLargeSkeleton>>,
|
2019-08-21 01:19:02 +00:00
|
|
|
object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FigureMgr {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
model_cache: FigureModelCache::new(),
|
2020-01-26 00:22:48 +00:00
|
|
|
critter_model_cache: FigureModelCache::new(),
|
|
|
|
quadruped_small_model_cache: FigureModelCache::new(),
|
|
|
|
quadruped_medium_model_cache: FigureModelCache::new(),
|
|
|
|
bird_medium_model_cache: FigureModelCache::new(),
|
|
|
|
bird_small_model_cache: FigureModelCache::new(),
|
|
|
|
dragon_model_cache: FigureModelCache::new(),
|
|
|
|
fish_medium_model_cache: FigureModelCache::new(),
|
|
|
|
fish_small_model_cache: FigureModelCache::new(),
|
|
|
|
biped_large_model_cache: FigureModelCache::new(),
|
2019-08-21 01:19:02 +00:00
|
|
|
character_states: HashMap::new(),
|
2019-10-26 02:20:38 +00:00
|
|
|
quadruped_small_states: HashMap::new(),
|
2019-08-21 01:19:02 +00:00
|
|
|
quadruped_medium_states: HashMap::new(),
|
2019-10-23 02:56:45 +00:00
|
|
|
bird_medium_states: HashMap::new(),
|
|
|
|
fish_medium_states: HashMap::new(),
|
2020-01-26 00:22:48 +00:00
|
|
|
critter_states: HashMap::new(),
|
2019-10-23 04:59:05 +00:00
|
|
|
dragon_states: HashMap::new(),
|
2019-10-24 01:10:26 +00:00
|
|
|
bird_small_states: HashMap::new(),
|
|
|
|
fish_small_states: HashMap::new(),
|
|
|
|
biped_large_states: HashMap::new(),
|
2019-08-21 01:19:02 +00:00
|
|
|
object_states: HashMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clean(&mut self, tick: u64) {
|
|
|
|
self.model_cache.clean(tick);
|
2020-01-26 00:22:48 +00:00
|
|
|
self.critter_model_cache.clean(tick);
|
|
|
|
self.quadruped_small_model_cache.clean(tick);
|
|
|
|
self.quadruped_medium_model_cache.clean(tick);
|
|
|
|
self.bird_medium_model_cache.clean(tick);
|
|
|
|
self.bird_small_model_cache.clean(tick);
|
|
|
|
self.dragon_model_cache.clean(tick);
|
|
|
|
self.fish_medium_model_cache.clean(tick);
|
|
|
|
self.fish_small_model_cache.clean(tick);
|
|
|
|
self.biped_large_model_cache.clean(tick);
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
2020-02-29 03:59:11 +00:00
|
|
|
pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData, camera: &Camera) {
|
|
|
|
let state = scene_data.state;
|
|
|
|
let time = state.get_time();
|
|
|
|
let tick = scene_data.tick;
|
|
|
|
let ecs = state.ecs();
|
|
|
|
let view_distance = scene_data.view_distance;
|
|
|
|
let dt = state.get_delta_time();
|
|
|
|
let frustum = camera.frustum();
|
2019-08-21 01:19:02 +00:00
|
|
|
// Get player position.
|
|
|
|
let player_pos = ecs
|
|
|
|
.read_storage::<Pos>()
|
2020-02-29 03:59:11 +00:00
|
|
|
.get(scene_data.player_entity)
|
2019-08-21 01:19:02 +00:00
|
|
|
.map_or(Vec3::zero(), |pos| pos.0);
|
|
|
|
|
2020-03-14 21:33:20 +00:00
|
|
|
for (
|
|
|
|
entity,
|
|
|
|
pos,
|
2020-03-21 03:23:46 +00:00
|
|
|
interpolated,
|
2020-03-14 21:33:20 +00:00
|
|
|
vel,
|
|
|
|
scale,
|
|
|
|
body,
|
|
|
|
character,
|
|
|
|
last_character,
|
|
|
|
physics,
|
|
|
|
stats,
|
|
|
|
loadout,
|
|
|
|
) in (
|
2019-08-21 01:19:02 +00:00
|
|
|
&ecs.entities(),
|
|
|
|
&ecs.read_storage::<Pos>(),
|
2020-03-21 03:23:46 +00:00
|
|
|
ecs.read_storage::<Interpolated>().maybe(),
|
2020-01-21 22:54:32 +00:00
|
|
|
&ecs.read_storage::<Vel>(),
|
2019-08-21 01:19:02 +00:00
|
|
|
ecs.read_storage::<Scale>().maybe(),
|
|
|
|
&ecs.read_storage::<Body>(),
|
|
|
|
ecs.read_storage::<CharacterState>().maybe(),
|
|
|
|
ecs.read_storage::<Last<CharacterState>>().maybe(),
|
2020-01-21 22:54:32 +00:00
|
|
|
&ecs.read_storage::<PhysicsState>(),
|
2019-08-21 01:19:02 +00:00
|
|
|
ecs.read_storage::<Stats>().maybe(),
|
2020-03-14 21:33:20 +00:00
|
|
|
ecs.read_storage::<Loadout>().maybe(),
|
2019-08-21 01:19:02 +00:00
|
|
|
)
|
|
|
|
.join()
|
|
|
|
{
|
2020-04-04 19:36:55 +00:00
|
|
|
let is_player = scene_data.player_entity == entity;
|
|
|
|
|
2020-03-21 03:23:46 +00:00
|
|
|
let (pos, ori) = interpolated
|
2020-03-28 01:31:22 +00:00
|
|
|
.map(|i| (Pos(i.pos), *i.ori))
|
|
|
|
.unwrap_or((*pos, Vec3::unit_y()));
|
2020-01-25 12:27:36 +00:00
|
|
|
|
2019-08-21 01:19:02 +00:00
|
|
|
// Don't process figures outside the vd
|
common: Rework volume API
See the doc comments in `common/src/vol.rs` for more information on
the API itself.
The changes include:
* Consistent `Err`/`Error` naming.
* Types are named `...Error`.
* `enum` variants are named `...Err`.
* Rename `VolMap{2d, 3d}` -> `VolGrid{2d, 3d}`. This is in preparation
to an upcoming change where a “map” in the game related sense will
be added.
* Add volume iterators. There are two types of them:
* _Position_ iterators obtained from the trait `IntoPosIterator`
using the method
`fn pos_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `Vec3<i32>`.
* _Volume_ iterators obtained from the trait `IntoVolIterator`
using the method
`fn vol_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `(Vec3<i32>, &Self::Vox)`.
Those traits will usually be implemented by references to volume
types (i.e. `impl IntoVolIterator<'a> for &'a T` where `T` is some
type which usually implements several volume traits, such as `Chunk`).
* _Position_ iterators iterate over the positions valid for that
volume.
* _Volume_ iterators do the same but return not only the position
but also the voxel at that position, in each iteration.
* Introduce trait `RectSizedVol` for the use case which we have with
`Chonk`: A `Chonk` is sized only in x and y direction.
* Introduce traits `RasterableVol`, `RectRasterableVol`
* `RasterableVol` represents a volume that is compile-time sized and has
its lower bound at `(0, 0, 0)`. The name `RasterableVol` was chosen
because such a volume can be used with `VolGrid3d`.
* `RectRasterableVol` represents a volume that is compile-time sized at
least in x and y direction and has its lower bound at `(0, 0, z)`.
There's no requirement on he lower bound or size in z direction.
The name `RectRasterableVol` was chosen because such a volume can be
used with `VolGrid2d`.
2019-09-03 22:23:29 +00:00
|
|
|
let vd_frac = Vec2::from(pos.0 - player_pos)
|
|
|
|
.map2(TerrainChunk::RECT_SIZE, |d: f32, sz| {
|
|
|
|
d.abs() as f32 / sz as f32
|
|
|
|
})
|
2019-08-21 01:19:02 +00:00
|
|
|
.magnitude()
|
|
|
|
/ view_distance as f32;
|
|
|
|
// Keep from re-adding/removing entities on the border of the vd
|
|
|
|
if vd_frac > 1.2 {
|
|
|
|
match body {
|
|
|
|
Body::Humanoid(_) => {
|
|
|
|
self.character_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-26 02:20:38 +00:00
|
|
|
Body::QuadrupedSmall(_) => {
|
|
|
|
self.quadruped_small_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
Body::QuadrupedMedium(_) => {
|
|
|
|
self.quadruped_medium_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 02:56:45 +00:00
|
|
|
Body::BirdMedium(_) => {
|
|
|
|
self.bird_medium_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 02:56:45 +00:00
|
|
|
Body::FishMedium(_) => {
|
|
|
|
self.fish_medium_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-26 00:22:48 +00:00
|
|
|
Body::Critter(_) => {
|
|
|
|
self.critter_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 04:59:05 +00:00
|
|
|
Body::Dragon(_) => {
|
|
|
|
self.dragon_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-24 01:10:26 +00:00
|
|
|
Body::BirdSmall(_) => {
|
|
|
|
self.bird_small_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-24 01:10:26 +00:00
|
|
|
Body::FishSmall(_) => {
|
|
|
|
self.fish_small_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-24 01:10:26 +00:00
|
|
|
Body::BipedLarge(_) => {
|
|
|
|
self.biped_large_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
Body::Object(_) => {
|
|
|
|
self.object_states.remove(&entity);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
} else if vd_frac > 1.0 {
|
2019-11-24 20:53:47 +00:00
|
|
|
match body {
|
|
|
|
Body::Humanoid(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.character_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::QuadrupedSmall(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.quadruped_small_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::QuadrupedMedium(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.quadruped_medium_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::BirdMedium(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.bird_medium_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::FishMedium(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.fish_medium_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-26 00:22:48 +00:00
|
|
|
Body::Critter(_) => {
|
|
|
|
self.critter_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::Dragon(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.dragon_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::BirdSmall(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.bird_small_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::FishSmall(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.fish_small_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::BipedLarge(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.biped_large_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
Body::Object(_) => {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.object_states
|
|
|
|
.get_mut(&entity)
|
|
|
|
.map(|state| state.visible = false);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-11-24 20:53:47 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-11-19 23:29:34 +00:00
|
|
|
// Don't process figures outside the frustum spectrum
|
2020-01-08 17:09:54 +00:00
|
|
|
let (in_frustum, lpindex) =
|
|
|
|
BoundingSphere::new(pos.0.into_array(), scale.unwrap_or(&Scale(1.0)).0 * 2.0)
|
|
|
|
.coherent_test_against_frustum(
|
|
|
|
&frustum,
|
|
|
|
match body {
|
|
|
|
Body::Humanoid(_) => self
|
|
|
|
.character_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::QuadrupedSmall(_) => self
|
|
|
|
.quadruped_small_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::QuadrupedMedium(_) => self
|
|
|
|
.quadruped_medium_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::BirdMedium(_) => self
|
|
|
|
.bird_medium_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::FishMedium(_) => self
|
|
|
|
.fish_medium_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
2020-01-26 00:22:48 +00:00
|
|
|
Body::Critter(_) => {
|
|
|
|
self.critter_states.get(&entity).map(|state| state.lpindex)
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-08 17:09:54 +00:00
|
|
|
Body::Dragon(_) => {
|
|
|
|
self.dragon_states.get(&entity).map(|state| state.lpindex)
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-08 17:09:54 +00:00
|
|
|
Body::BirdSmall(_) => self
|
|
|
|
.bird_small_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::FishSmall(_) => self
|
|
|
|
.fish_small_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::BipedLarge(_) => self
|
|
|
|
.biped_large_states
|
|
|
|
.get(&entity)
|
|
|
|
.map(|state| state.lpindex),
|
|
|
|
Body::Object(_) => {
|
|
|
|
self.object_states.get(&entity).map(|state| state.lpindex)
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-08 17:09:54 +00:00
|
|
|
}
|
|
|
|
.unwrap_or(0),
|
|
|
|
);
|
2019-11-19 23:29:34 +00:00
|
|
|
|
2019-11-24 20:53:47 +00:00
|
|
|
if !in_frustum {
|
2020-01-07 16:40:06 +00:00
|
|
|
match body {
|
|
|
|
Body::Humanoid(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.character_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::QuadrupedSmall(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.quadruped_small_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::QuadrupedMedium(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.quadruped_medium_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::BirdMedium(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.bird_medium_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::FishMedium(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.fish_medium_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-26 00:22:48 +00:00
|
|
|
Body::Critter(_) => {
|
|
|
|
self.critter_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::Dragon(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.dragon_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::BirdSmall(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.bird_small_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::FishSmall(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.fish_small_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::BipedLarge(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.biped_large_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
Body::Object(_) => {
|
2020-01-09 19:07:55 +00:00
|
|
|
self.object_states.get_mut(&entity).map(|state| {
|
|
|
|
state.lpindex = lpindex;
|
|
|
|
state.visible = false
|
|
|
|
});
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-07 16:40:06 +00:00
|
|
|
}
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Change in health as color!
|
|
|
|
let col = stats
|
2019-10-17 20:59:36 +00:00
|
|
|
.map(|s| {
|
2019-08-21 01:19:02 +00:00
|
|
|
Rgba::broadcast(1.0)
|
2020-04-04 19:36:55 +00:00
|
|
|
+ Rgba::new(2.0, 2.0, 2., 0.00).map(|c| {
|
2019-10-17 20:59:36 +00:00
|
|
|
(c / (1.0 + DAMAGE_FADE_COEFFICIENT * s.health.last_change.0)) as f32
|
|
|
|
})
|
2019-08-21 01:19:02 +00:00
|
|
|
})
|
|
|
|
.unwrap_or(Rgba::broadcast(1.0));
|
|
|
|
|
|
|
|
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let mut state_animation_rate = 1.0;
|
2019-09-09 19:11:40 +00:00
|
|
|
|
2020-03-14 21:33:20 +00:00
|
|
|
let active_item_kind = loadout
|
|
|
|
.and_then(|l| l.active_item.as_ref())
|
2020-02-26 17:04:43 +00:00
|
|
|
.map(|i| &i.item.kind);
|
2020-03-14 21:33:20 +00:00
|
|
|
let active_tool_kind = if let Some(ItemKind::Tool(tool)) = active_item_kind {
|
|
|
|
Some(tool.kind)
|
2019-11-10 23:36:47 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2019-08-21 01:19:02 +00:00
|
|
|
match body {
|
|
|
|
Body::Humanoid(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-08-21 01:19:02 +00:00
|
|
|
let state = self
|
|
|
|
.character_states
|
|
|
|
.entry(entity)
|
|
|
|
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
2020-03-26 05:35:25 +00:00
|
|
|
(true, false, _) => anim::character::StandAnimation::update_skeleton(
|
2019-08-21 01:19:02 +00:00
|
|
|
&CharacterSkeleton::new(),
|
2019-11-10 23:36:47 +00:00
|
|
|
(active_tool_kind, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-08-21 01:19:02 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
2020-03-26 05:35:25 +00:00
|
|
|
(true, true, _) => anim::character::RunAnimation::update_skeleton(
|
2019-08-21 01:19:02 +00:00
|
|
|
&CharacterSkeleton::new(),
|
2020-03-28 01:31:22 +00:00
|
|
|
(active_tool_kind, vel.0, ori, state.last_ori, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-08-21 01:19:02 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::character::JumpAnimation::update_skeleton(
|
2019-08-21 01:19:02 +00:00
|
|
|
&CharacterSkeleton::new(),
|
2019-11-10 23:36:47 +00:00
|
|
|
(active_tool_kind, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-09-09 19:11:40 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Swim
|
2020-03-26 05:35:25 +00:00
|
|
|
(false, _, true) => anim::character::SwimAnimation::update_skeleton(
|
2019-09-09 19:11:40 +00:00
|
|
|
&CharacterSkeleton::new(),
|
2020-03-28 01:31:22 +00:00
|
|
|
(active_tool_kind, vel.0, ori.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-09-09 19:11:40 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
};
|
|
|
|
let target_bones = match &character {
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::Roll { .. } => {
|
|
|
|
anim::character::RollAnimation::update_skeleton(
|
|
|
|
&target_base,
|
2020-03-28 01:31:22 +00:00
|
|
|
(active_tool_kind, ori, state.last_ori, time),
|
2020-03-07 18:15:02 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
2020-03-16 11:32:57 +00:00
|
|
|
CharacterState::BasicMelee(_) => {
|
2020-03-27 03:51:55 +00:00
|
|
|
anim::character::AlphaAnimation::update_skeleton(
|
2020-03-16 11:32:57 +00:00
|
|
|
&target_base,
|
2020-03-25 04:15:06 +00:00
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
2020-03-16 11:32:57 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
2020-03-28 03:59:05 +00:00
|
|
|
CharacterState::BasicRanged(data) => {
|
|
|
|
if data.exhausted {
|
|
|
|
anim::character::ShootAnimation::update_skeleton(
|
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
anim::character::ChargeAnimation::update_skeleton(
|
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
}
|
2020-03-16 11:32:57 +00:00
|
|
|
},
|
|
|
|
CharacterState::Boost(_) => {
|
2020-03-27 03:51:55 +00:00
|
|
|
anim::character::AlphaAnimation::update_skeleton(
|
2019-08-21 01:19:02 +00:00
|
|
|
&target_base,
|
2020-03-25 04:15:06 +00:00
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-08-21 01:19:02 +00:00
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-03-16 15:34:53 +00:00
|
|
|
CharacterState::DashMelee(_) => {
|
2020-03-28 03:59:05 +00:00
|
|
|
anim::character::DashAnimation::update_skeleton(
|
2020-03-16 15:34:53 +00:00
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
2020-03-19 22:40:03 +00:00
|
|
|
CharacterState::TripleStrike(s) => match s.stage {
|
2020-03-25 05:37:09 +00:00
|
|
|
triple_strike::Stage::First => {
|
2020-03-27 03:51:55 +00:00
|
|
|
anim::character::AlphaAnimation::update_skeleton(
|
2020-03-25 05:37:09 +00:00
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
triple_strike::Stage::Second => {
|
|
|
|
anim::character::SpinAnimation::update_skeleton(
|
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
triple_strike::Stage::Third => {
|
2020-03-27 05:57:30 +00:00
|
|
|
anim::character::BetaAnimation::update_skeleton(
|
2020-03-25 05:37:09 +00:00
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
2020-03-19 22:40:03 +00:00
|
|
|
},
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::BasicBlock { .. } => {
|
2020-02-03 10:54:50 +00:00
|
|
|
anim::character::BlockIdleAnimation::update_skeleton(
|
2020-02-24 14:35:07 +00:00
|
|
|
&CharacterSkeleton::new(),
|
2019-12-26 14:43:59 +00:00
|
|
|
(active_tool_kind, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-12-26 14:43:59 +00:00
|
|
|
skeleton_attr,
|
2020-01-21 22:54:32 +00:00
|
|
|
)
|
2020-02-24 14:35:07 +00:00
|
|
|
},
|
|
|
|
/*
|
2020-02-03 10:54:50 +00:00
|
|
|
CharacterState::Charge(_) => {
|
|
|
|
anim::character::ChargeAnimation::update_skeleton(
|
2019-12-26 14:43:59 +00:00
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-12-26 14:43:59 +00:00
|
|
|
skeleton_attr,
|
2020-01-21 22:54:32 +00:00
|
|
|
)
|
|
|
|
}*/
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::Equipping { .. } => {
|
2020-03-25 05:22:07 +00:00
|
|
|
anim::character::EquipAnimation::update_skeleton(
|
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::Wielding { .. } => {
|
2020-03-26 05:35:25 +00:00
|
|
|
anim::character::WieldAnimation::update_skeleton(
|
|
|
|
&target_base,
|
|
|
|
(active_tool_kind, vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::Glide { .. } => {
|
2020-01-21 22:54:32 +00:00
|
|
|
anim::character::GlidingAnimation::update_skeleton(
|
|
|
|
&target_base,
|
2020-03-28 01:31:22 +00:00
|
|
|
(active_tool_kind, vel.0, ori, state.last_ori, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::Climb { .. } => {
|
2020-01-21 22:54:32 +00:00
|
|
|
anim::character::ClimbAnimation::update_skeleton(
|
|
|
|
&CharacterSkeleton::new(),
|
2020-03-28 01:31:22 +00:00
|
|
|
(active_tool_kind, vel.0, ori, time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-03-07 18:15:02 +00:00
|
|
|
CharacterState::Sit { .. } => {
|
|
|
|
anim::character::SitAnimation::update_skeleton(
|
|
|
|
&CharacterSkeleton::new(),
|
|
|
|
(active_tool_kind, time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
_ => target_base,
|
|
|
|
};
|
|
|
|
|
2019-12-03 06:30:08 +00:00
|
|
|
state.skeleton.interpolate(&target_bones, dt);
|
2019-09-09 19:11:40 +00:00
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-09-09 19:11:40 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-09-09 19:11:40 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-26 02:20:38 +00:00
|
|
|
Body::QuadrupedSmall(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.quadruped_small_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-08-21 01:19:02 +00:00
|
|
|
let state = self
|
2019-10-26 02:20:38 +00:00
|
|
|
.quadruped_small_states
|
2019-08-21 01:19:02 +00:00
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| {
|
|
|
|
FigureState::new(renderer, QuadrupedSmallSkeleton::new())
|
|
|
|
});
|
2019-08-21 01:19:02 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => {
|
|
|
|
anim::quadruped_small::IdleAnimation::update_skeleton(
|
|
|
|
&QuadrupedSmallSkeleton::new(),
|
|
|
|
time,
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => {
|
|
|
|
anim::quadruped_small::RunAnimation::update_skeleton(
|
|
|
|
&QuadrupedSmallSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::quadruped_small::JumpAnimation::update_skeleton(
|
2019-10-26 02:20:38 +00:00
|
|
|
&QuadrupedSmallSkeleton::new(),
|
2019-08-21 01:19:02 +00:00
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-08-21 01:19:02 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
2019-09-09 19:11:40 +00:00
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-09-09 19:11:40 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-09-09 19:11:40 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
Body::QuadrupedMedium(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.quadruped_medium_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-08-21 01:19:02 +00:00
|
|
|
let state = self
|
|
|
|
.quadruped_medium_states
|
|
|
|
.entry(entity)
|
|
|
|
.or_insert_with(|| {
|
|
|
|
FigureState::new(renderer, QuadrupedMediumSkeleton::new())
|
|
|
|
});
|
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => {
|
|
|
|
anim::quadruped_medium::IdleAnimation::update_skeleton(
|
|
|
|
&QuadrupedMediumSkeleton::new(),
|
|
|
|
time,
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => {
|
|
|
|
anim::quadruped_medium::RunAnimation::update_skeleton(
|
|
|
|
&QuadrupedMediumSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => {
|
|
|
|
anim::quadruped_medium::JumpAnimation::update_skeleton(
|
|
|
|
&QuadrupedMediumSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
|
|
|
skeleton_attr,
|
|
|
|
)
|
2020-02-03 21:02:32 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
2019-09-09 19:11:40 +00:00
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-09-09 19:11:40 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-09-09 19:11:40 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 02:56:45 +00:00
|
|
|
Body::BirdMedium(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.bird_medium_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-10-23 02:56:45 +00:00
|
|
|
let state = self
|
|
|
|
.bird_medium_states
|
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| FigureState::new(renderer, BirdMediumSkeleton::new()));
|
2019-10-23 02:56:45 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-10-23 02:56:45 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::bird_medium::IdleAnimation::update_skeleton(
|
2019-10-23 02:56:45 +00:00
|
|
|
&BirdMediumSkeleton::new(),
|
|
|
|
time,
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 02:56:45 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::bird_medium::RunAnimation::update_skeleton(
|
2019-10-23 02:56:45 +00:00
|
|
|
&BirdMediumSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 02:56:45 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::bird_medium::JumpAnimation::update_skeleton(
|
2019-10-23 02:56:45 +00:00
|
|
|
&BirdMediumSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 02:56:45 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-10-23 02:56:45 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-10-23 02:56:45 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 02:56:45 +00:00
|
|
|
Body::FishMedium(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.fish_medium_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-10-23 02:56:45 +00:00
|
|
|
let state = self
|
|
|
|
.fish_medium_states
|
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| FigureState::new(renderer, FishMediumSkeleton::new()));
|
2019-10-23 02:56:45 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-10-23 02:56:45 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::fish_medium::IdleAnimation::update_skeleton(
|
2019-10-23 02:56:45 +00:00
|
|
|
&FishMediumSkeleton::new(),
|
|
|
|
time,
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 02:56:45 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::fish_medium::RunAnimation::update_skeleton(
|
2019-10-23 02:56:45 +00:00
|
|
|
&FishMediumSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 02:56:45 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::fish_medium::JumpAnimation::update_skeleton(
|
2019-10-23 02:56:45 +00:00
|
|
|
&FishMediumSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 02:56:45 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-10-23 02:56:45 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-10-23 02:56:45 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 04:59:05 +00:00
|
|
|
Body::Dragon(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.dragon_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-10-23 04:59:05 +00:00
|
|
|
let state = self
|
|
|
|
.dragon_states
|
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| FigureState::new(renderer, DragonSkeleton::new()));
|
2019-10-23 04:59:05 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-10-23 04:59:05 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::dragon::IdleAnimation::update_skeleton(
|
2019-10-23 04:59:05 +00:00
|
|
|
&DragonSkeleton::new(),
|
|
|
|
time,
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 04:59:05 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::dragon::RunAnimation::update_skeleton(
|
2019-10-23 04:59:05 +00:00
|
|
|
&DragonSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 04:59:05 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::dragon::JumpAnimation::update_skeleton(
|
2019-10-23 04:59:05 +00:00
|
|
|
&DragonSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-23 04:59:05 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-10-23 04:59:05 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-10-23 04:59:05 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-26 00:22:48 +00:00
|
|
|
Body::Critter(_) => {
|
|
|
|
let skeleton_attr = &self
|
|
|
|
.critter_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
|
|
|
let state = self
|
|
|
|
.critter_states
|
|
|
|
.entry(entity)
|
|
|
|
.or_insert_with(|| FigureState::new(renderer, CritterSkeleton::new()));
|
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-02-03 21:02:32 +00:00
|
|
|
state.state_time = 0.0;
|
2020-01-26 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2020-02-03 21:02:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-02-03 21:02:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::critter::IdleAnimation::update_skeleton(
|
2020-01-26 00:22:48 +00:00
|
|
|
&CritterSkeleton::new(),
|
|
|
|
time,
|
2020-02-03 21:02:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2020-01-26 00:22:48 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-02-03 21:02:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::critter::RunAnimation::update_skeleton(
|
2020-01-26 00:22:48 +00:00
|
|
|
&CritterSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-02-03 21:02:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2020-01-26 00:22:48 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-02-03 21:02:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::critter::JumpAnimation::update_skeleton(
|
2020-01-26 00:22:48 +00:00
|
|
|
&CritterSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-02-03 21:02:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2020-01-26 00:22:48 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2020-01-26 00:22:48 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-02-03 21:02:32 +00:00
|
|
|
state_animation_rate,
|
2020-01-26 00:22:48 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2020-01-26 00:22:48 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-24 01:10:26 +00:00
|
|
|
Body::BirdSmall(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.bird_small_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-10-24 01:10:26 +00:00
|
|
|
let state = self
|
|
|
|
.bird_small_states
|
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| FigureState::new(renderer, BirdSmallSkeleton::new()));
|
2019-10-24 01:10:26 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-10-24 01:10:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::bird_small::IdleAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&BirdSmallSkeleton::new(),
|
|
|
|
time,
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::bird_small::RunAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&BirdSmallSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::bird_small::JumpAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&BirdSmallSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-10-24 01:10:26 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-10-24 01:10:26 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-24 01:10:26 +00:00
|
|
|
Body::FishSmall(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.fish_small_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-10-24 01:10:26 +00:00
|
|
|
let state = self
|
|
|
|
.fish_small_states
|
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| FigureState::new(renderer, FishSmallSkeleton::new()));
|
2019-10-24 01:10:26 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-10-24 01:10:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::fish_small::IdleAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&FishSmallSkeleton::new(),
|
|
|
|
time,
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::fish_small::RunAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&FishSmallSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::fish_small::JumpAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&FishSmallSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-10-24 01:10:26 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-10-24 01:10:26 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-24 01:10:26 +00:00
|
|
|
Body::BipedLarge(_) => {
|
2020-01-26 00:22:48 +00:00
|
|
|
let skeleton_attr = &self
|
|
|
|
.biped_large_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
CameraMode::default(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.1;
|
|
|
|
|
2019-10-24 01:10:26 +00:00
|
|
|
let state = self
|
|
|
|
.biped_large_states
|
|
|
|
.entry(entity)
|
2019-10-26 02:20:38 +00:00
|
|
|
.or_insert_with(|| FigureState::new(renderer, BipedLargeSkeleton::new()));
|
2019-10-24 01:10:26 +00:00
|
|
|
|
|
|
|
let (character, last_character) = match (character, last_character) {
|
|
|
|
(Some(c), Some(l)) => (c, l),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2020-03-22 12:46:09 +00:00
|
|
|
if !character.same_variant(&last_character.0) {
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time = 0.0;
|
2019-10-24 01:10:26 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
let target_base = match (
|
|
|
|
physics.on_ground,
|
2020-03-28 05:51:52 +00:00
|
|
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
|
|
|
physics.in_fluid, // In water
|
2020-01-21 22:54:32 +00:00
|
|
|
) {
|
|
|
|
// Standing
|
|
|
|
(true, false, false) => anim::biped_large::IdleAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&BipedLargeSkeleton::new(),
|
|
|
|
time,
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// Running
|
|
|
|
(true, true, false) => anim::biped_large::RunAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&BipedLargeSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
2020-01-21 22:54:32 +00:00
|
|
|
// In air
|
|
|
|
(false, _, false) => anim::biped_large::JumpAnimation::update_skeleton(
|
2019-10-24 01:10:26 +00:00
|
|
|
&BipedLargeSkeleton::new(),
|
|
|
|
(vel.0.magnitude(), time),
|
2020-01-21 22:54:32 +00:00
|
|
|
state.state_time,
|
|
|
|
&mut state_animation_rate,
|
2019-10-24 01:10:26 +00:00
|
|
|
skeleton_attr,
|
|
|
|
),
|
|
|
|
|
|
|
|
// TODO!
|
|
|
|
_ => state.skeleton_mut().clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
state.skeleton.interpolate(&target_base, dt);
|
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-10-24 01:10:26 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-10-24 01:10:26 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
Body::Object(_) => {
|
|
|
|
let state = self
|
|
|
|
.object_states
|
|
|
|
.entry(entity)
|
|
|
|
.or_insert_with(|| FigureState::new(renderer, ObjectSkeleton::new()));
|
|
|
|
|
|
|
|
state.skeleton = state.skeleton_mut().clone();
|
2019-09-09 19:11:40 +00:00
|
|
|
state.update(
|
|
|
|
renderer,
|
|
|
|
pos.0,
|
2020-03-28 01:31:22 +00:00
|
|
|
ori,
|
2019-09-09 19:11:40 +00:00
|
|
|
scale,
|
|
|
|
col,
|
|
|
|
dt,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex,
|
|
|
|
true,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player,
|
2019-09-09 19:11:40 +00:00
|
|
|
);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-29 03:59:11 +00:00
|
|
|
// Clear states that have deleted entities.
|
2019-08-21 01:19:02 +00:00
|
|
|
self.character_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
2019-10-26 02:20:38 +00:00
|
|
|
self.quadruped_small_states
|
2019-08-21 01:19:02 +00:00
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
|
|
|
self.quadruped_medium_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
2019-10-23 02:56:45 +00:00
|
|
|
self.bird_medium_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
|
|
|
self.fish_medium_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
2020-01-26 00:22:48 +00:00
|
|
|
self.critter_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
2019-10-23 04:59:05 +00:00
|
|
|
self.dragon_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
2019-10-24 01:10:26 +00:00
|
|
|
self.bird_small_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
|
|
|
self.fish_small_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
|
|
|
self.biped_large_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
2019-08-21 01:19:02 +00:00
|
|
|
self.object_states
|
|
|
|
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render(
|
|
|
|
&mut self,
|
|
|
|
renderer: &mut Renderer,
|
2020-02-29 03:59:11 +00:00
|
|
|
state: &State,
|
|
|
|
player_entity: EcsEntity,
|
|
|
|
tick: u64,
|
2019-08-21 01:19:02 +00:00
|
|
|
globals: &Consts<Globals>,
|
|
|
|
lights: &Consts<Light>,
|
2019-09-25 12:00:00 +00:00
|
|
|
shadows: &Consts<Shadow>,
|
2019-08-21 01:19:02 +00:00
|
|
|
camera: &Camera,
|
|
|
|
) {
|
2020-02-29 03:59:11 +00:00
|
|
|
let ecs = state.ecs();
|
2019-08-21 01:19:02 +00:00
|
|
|
|
2020-02-29 03:59:11 +00:00
|
|
|
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
|
|
|
let character_state = character_state_storage.get(player_entity);
|
2019-08-18 13:19:32 +00:00
|
|
|
|
2020-03-20 14:45:36 +00:00
|
|
|
for (entity, _, _, body, _, loadout, _) in (
|
2019-08-21 01:19:02 +00:00
|
|
|
&ecs.entities(),
|
|
|
|
&ecs.read_storage::<Pos>(),
|
2020-01-25 12:27:36 +00:00
|
|
|
ecs.read_storage::<Ori>().maybe(),
|
2019-08-21 01:19:02 +00:00
|
|
|
&ecs.read_storage::<Body>(),
|
|
|
|
ecs.read_storage::<Stats>().maybe(),
|
2020-03-14 21:33:20 +00:00
|
|
|
ecs.read_storage::<Loadout>().maybe(),
|
2019-08-21 01:19:02 +00:00
|
|
|
ecs.read_storage::<Scale>().maybe(),
|
|
|
|
)
|
|
|
|
.join()
|
2020-03-19 19:36:19 +00:00
|
|
|
// Don't render dead entities
|
2020-03-20 14:45:36 +00:00
|
|
|
.filter(|(_, _, _, _, stats, _, _)| stats.map_or(true, |s| !s.is_dead))
|
2019-08-21 01:19:02 +00:00
|
|
|
{
|
2020-02-29 03:59:11 +00:00
|
|
|
let is_player = entity == player_entity;
|
2020-04-04 19:36:55 +00:00
|
|
|
|
|
|
|
if !is_player {
|
|
|
|
self.render_figure(
|
|
|
|
renderer,
|
|
|
|
tick,
|
|
|
|
globals,
|
|
|
|
lights,
|
|
|
|
shadows,
|
|
|
|
camera,
|
|
|
|
character_state,
|
|
|
|
entity,
|
|
|
|
body,
|
|
|
|
loadout,
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn render_player(
|
|
|
|
&mut self,
|
|
|
|
renderer: &mut Renderer,
|
|
|
|
state: &State,
|
|
|
|
player_entity: EcsEntity,
|
|
|
|
tick: u64,
|
|
|
|
globals: &Consts<Globals>,
|
|
|
|
lights: &Consts<Light>,
|
|
|
|
shadows: &Consts<Shadow>,
|
|
|
|
camera: &Camera,
|
|
|
|
) {
|
|
|
|
let ecs = state.ecs();
|
|
|
|
|
|
|
|
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
|
|
|
let character_state = character_state_storage.get(player_entity);
|
|
|
|
|
|
|
|
if let Some(body) = ecs.read_storage::<Body>().get(player_entity) {
|
|
|
|
let loadout_storage = ecs.read_storage::<Loadout>();
|
|
|
|
let loadout = loadout_storage.get(player_entity);
|
|
|
|
|
|
|
|
self.render_figure(
|
|
|
|
renderer,
|
|
|
|
tick,
|
|
|
|
globals,
|
|
|
|
lights,
|
|
|
|
shadows,
|
|
|
|
camera,
|
|
|
|
character_state,
|
|
|
|
player_entity,
|
|
|
|
body,
|
|
|
|
loadout,
|
|
|
|
true,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_figure(
|
|
|
|
&mut self,
|
|
|
|
renderer: &mut Renderer,
|
|
|
|
tick: u64,
|
|
|
|
globals: &Consts<Globals>,
|
|
|
|
lights: &Consts<Light>,
|
|
|
|
shadows: &Consts<Shadow>,
|
|
|
|
camera: &Camera,
|
|
|
|
character_state: Option<&CharacterState>,
|
|
|
|
entity: EcsEntity,
|
|
|
|
body: &Body,
|
|
|
|
loadout: Option<&Loadout>,
|
|
|
|
is_player: bool,
|
|
|
|
) {
|
|
|
|
let player_camera_mode = if is_player {
|
|
|
|
camera.get_mode()
|
|
|
|
} else {
|
|
|
|
CameraMode::default()
|
|
|
|
};
|
|
|
|
let character_state = if is_player { character_state } else { None };
|
|
|
|
|
|
|
|
let FigureMgr {
|
|
|
|
model_cache,
|
|
|
|
critter_model_cache,
|
|
|
|
quadruped_small_model_cache,
|
|
|
|
quadruped_medium_model_cache,
|
|
|
|
bird_medium_model_cache,
|
|
|
|
bird_small_model_cache,
|
|
|
|
dragon_model_cache,
|
|
|
|
fish_medium_model_cache,
|
|
|
|
fish_small_model_cache,
|
|
|
|
biped_large_model_cache,
|
|
|
|
character_states,
|
|
|
|
quadruped_small_states,
|
|
|
|
quadruped_medium_states,
|
|
|
|
bird_medium_states,
|
|
|
|
fish_medium_states,
|
|
|
|
critter_states,
|
|
|
|
dragon_states,
|
|
|
|
bird_small_states,
|
|
|
|
fish_small_states,
|
|
|
|
biped_large_states,
|
|
|
|
object_states,
|
|
|
|
} = self;
|
|
|
|
if let Some((locals, bone_consts, model)) = match body {
|
|
|
|
Body::Humanoid(_) => character_states
|
|
|
|
.get(&entity)
|
|
|
|
.filter(|state| state.visible)
|
|
|
|
.map(|state| {
|
2020-01-26 00:22:48 +00:00
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
2020-03-15 18:44:47 +00:00
|
|
|
loadout,
|
2020-01-26 00:22:48 +00:00
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
2020-04-04 19:36:55 +00:00
|
|
|
Body::QuadrupedSmall(_) => quadruped_small_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&quadruped_small_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::QuadrupedMedium(_) => quadruped_medium_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&quadruped_medium_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::BirdMedium(_) => bird_medium_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&bird_medium_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::FishMedium(_) => fish_medium_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&fish_medium_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::Critter(_) => critter_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&critter_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::Dragon(_) => dragon_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&dragon_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::BirdSmall(_) => bird_small_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&bird_small_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::FishSmall(_) => fish_small_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&fish_small_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::BipedLarge(_) => biped_large_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&biped_large_model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
Body::Object(_) => object_states.get(&entity).map(|state| {
|
|
|
|
(
|
|
|
|
state.locals(),
|
|
|
|
state.bone_consts(),
|
|
|
|
&model_cache
|
|
|
|
.get_or_create_model(
|
|
|
|
renderer,
|
|
|
|
*body,
|
|
|
|
loadout,
|
|
|
|
tick,
|
|
|
|
player_camera_mode,
|
|
|
|
character_state,
|
|
|
|
)
|
|
|
|
.0,
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
} {
|
|
|
|
if is_player {
|
|
|
|
renderer.render_player(model, globals, locals, bone_consts, lights, shadows);
|
|
|
|
renderer.render_player_shadow(model, globals, locals, bone_consts, lights, shadows);
|
2019-08-21 01:19:02 +00:00
|
|
|
} else {
|
2020-04-04 19:36:55 +00:00
|
|
|
renderer.render_figure(model, globals, locals, bone_consts, lights, shadows);
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
2020-04-04 19:36:55 +00:00
|
|
|
} else {
|
|
|
|
trace!("Body has no saved figure");
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-19 15:13:33 +00:00
|
|
|
|
|
|
|
pub fn figure_count(&self) -> usize {
|
2019-11-19 23:29:34 +00:00
|
|
|
self.character_states.len()
|
2020-01-08 17:09:54 +00:00
|
|
|
+ self.quadruped_small_states.len()
|
|
|
|
+ self.character_states.len()
|
|
|
|
+ self.quadruped_medium_states.len()
|
|
|
|
+ self.bird_medium_states.len()
|
|
|
|
+ self.fish_medium_states.len()
|
2020-01-26 00:22:48 +00:00
|
|
|
+ self.critter_states.len()
|
2020-01-08 17:09:54 +00:00
|
|
|
+ self.dragon_states.len()
|
|
|
|
+ self.bird_small_states.len()
|
|
|
|
+ self.fish_small_states.len()
|
|
|
|
+ self.biped_large_states.len()
|
|
|
|
+ self.object_states.len()
|
2019-11-19 15:13:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn figure_count_visible(&self) -> usize {
|
2020-01-08 17:09:54 +00:00
|
|
|
self.character_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self
|
|
|
|
.quadruped_small_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self
|
|
|
|
.quadruped_medium_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self
|
|
|
|
.bird_medium_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self
|
2020-01-26 00:22:48 +00:00
|
|
|
.critter_states
|
2020-01-08 17:09:54 +00:00
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self.dragon_states.iter().filter(|(_, c)| c.visible).count()
|
2020-01-26 00:22:48 +00:00
|
|
|
+ self
|
|
|
|
.fish_medium_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
2020-01-08 17:09:54 +00:00
|
|
|
+ self
|
|
|
|
.bird_small_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self
|
|
|
|
.fish_small_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self
|
|
|
|
.biped_large_states
|
|
|
|
.iter()
|
|
|
|
.filter(|(_, c)| c.visible)
|
|
|
|
.count()
|
|
|
|
+ self.object_states.iter().filter(|(_, c)| c.visible).count()
|
2019-11-19 15:13:33 +00:00
|
|
|
}
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct FigureState<S: Skeleton> {
|
|
|
|
bone_consts: Consts<FigureBoneData>,
|
|
|
|
locals: Consts<FigureLocals>,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_time: f64,
|
2019-08-21 01:19:02 +00:00
|
|
|
skeleton: S,
|
2019-09-09 19:11:40 +00:00
|
|
|
last_ori: Vec3<f32>,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex: u8,
|
|
|
|
visible: bool,
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<S: Skeleton> FigureState<S> {
|
|
|
|
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
|
|
|
|
Self {
|
|
|
|
bone_consts: renderer
|
|
|
|
.create_consts(&skeleton.compute_matrices())
|
|
|
|
.unwrap(),
|
|
|
|
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
|
2020-01-21 22:54:32 +00:00
|
|
|
state_time: 0.0,
|
2019-08-21 01:19:02 +00:00
|
|
|
skeleton,
|
2019-09-09 19:11:40 +00:00
|
|
|
last_ori: Vec3::zero(),
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex: 0,
|
|
|
|
visible: false,
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update(
|
|
|
|
&mut self,
|
|
|
|
renderer: &mut Renderer,
|
|
|
|
pos: Vec3<f32>,
|
|
|
|
ori: Vec3<f32>,
|
|
|
|
scale: f32,
|
|
|
|
col: Rgba<f32>,
|
|
|
|
dt: f32,
|
2020-01-21 22:54:32 +00:00
|
|
|
state_animation_rate: f32,
|
2019-11-19 23:29:34 +00:00
|
|
|
lpindex: u8,
|
|
|
|
visible: bool,
|
2020-04-04 19:36:55 +00:00
|
|
|
is_player: bool,
|
2019-08-21 01:19:02 +00:00
|
|
|
) {
|
2019-11-19 23:29:34 +00:00
|
|
|
self.visible = visible;
|
|
|
|
self.lpindex = lpindex;
|
2020-03-21 03:23:46 +00:00
|
|
|
// What is going on here?
|
|
|
|
// (note: that ori is now the slerped ori)
|
2019-09-09 19:11:40 +00:00
|
|
|
self.last_ori = Lerp::lerp(self.last_ori, ori, 15.0 * dt);
|
|
|
|
|
2020-01-21 22:54:32 +00:00
|
|
|
self.state_time += (dt * state_animation_rate) as f64;
|
2019-09-09 19:11:40 +00:00
|
|
|
|
2019-08-21 01:19:02 +00:00
|
|
|
let mat = Mat4::<f32>::identity()
|
2020-03-21 03:23:46 +00:00
|
|
|
* Mat4::translation_3d(pos)
|
2019-08-21 01:19:02 +00:00
|
|
|
* Mat4::rotation_z(-ori.x.atan2(ori.y))
|
2019-10-06 20:03:29 +00:00
|
|
|
* Mat4::rotation_x(ori.z.atan2(Vec2::from(ori).magnitude()))
|
2019-08-21 01:19:02 +00:00
|
|
|
* Mat4::scaling_3d(Vec3::from(0.8 * scale));
|
|
|
|
|
2020-04-04 19:36:55 +00:00
|
|
|
let locals = FigureLocals::new(mat, col, is_player);
|
2019-08-21 01:19:02 +00:00
|
|
|
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
|
|
|
|
|
|
|
renderer
|
|
|
|
.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices())
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }
|
2019-08-21 01:19:02 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
pub fn bone_consts(&self) -> &Consts<FigureBoneData> { &self.bone_consts }
|
2019-08-21 01:19:02 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
pub fn skeleton_mut(&mut self) -> &mut S { &mut self.skeleton }
|
2019-08-21 01:19:02 +00:00
|
|
|
}
|