diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index fb34afefd5..18141d0331 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -2,7 +2,7 @@ use specs::{Component, FlaggedStorage, HashMapStorage}; use specs_idvs::IDVStorage; use std::time::Duration; -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] pub enum MovementState { Stand, Run, @@ -22,7 +22,7 @@ impl MovementState { } } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] pub enum ActionState { Idle, Wield { time_left: Duration }, @@ -57,7 +57,7 @@ impl ActionState { } } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] pub struct CharacterState { pub movement: MovementState, pub action: ActionState, diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index 03d9a761cf..6607c17b29 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -164,8 +164,8 @@ impl Scene { Body::Humanoid(body), Some(equipment), client.get_tick(), - false, - false, + None, + None, ) .0; diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index c8a7077f56..e922bd090f 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -12,12 +12,18 @@ const THIRD_PERSON_INTERP_TIME: f32 = 0.1; pub const MIN_ZOOM: f32 = 0.1; // Possible TODO: Add more modes -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq, Clone, Copy, Eq, Hash)] pub enum CameraMode { FirstPerson, ThirdPerson, } +impl Default for CameraMode { + fn default() -> Self { + Self::ThirdPerson + } +} + pub struct Camera { tgt_focus: Vec3, focus: Vec3, diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index f5153b1bf3..1df51fdb90 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -2,17 +2,23 @@ use super::load::*; use crate::{ anim::SkeletonAttr, render::{FigurePipeline, Mesh, Model, Renderer}, + scene::camera::CameraMode, }; use common::{ assets::watch::ReloadIndicator, - comp::{Body, Equipment}, + comp::{ActionState, Body, CharacterState, Equipment}, }; use hashbrown::HashMap; #[derive(PartialEq, Eq, Hash, Clone)] enum FigureKey { Simple(Body), - Complex(Body, Option, bool, bool), + Complex( + Body, + Option, + Option, + Option, + ), } pub struct FigureModelCache { @@ -34,11 +40,16 @@ impl FigureModelCache { body: Body, equipment: Option<&Equipment>, tick: u64, - first_person: bool, - gliding: bool, + camera_mode: Option, + character_state: Option<&CharacterState>, ) -> &(Model, SkeletonAttr) { let key = if equipment.is_some() { - FigureKey::Complex(body, equipment.cloned(), first_person, gliding) + FigureKey::Complex( + body, + equipment.cloned(), + camera_mode, + character_state.cloned(), + ) } else { FigureKey::Simple(body) }; @@ -56,36 +67,69 @@ impl FigureModelCache { HumHeadSpec::load_watched(&mut self.manifest_indicator); let bone_meshes = match body { Body::Humanoid(body) => [ - -if !first_person { - - Some(humanoid_head_spec.mesh_head( - body.race, - body.body_type, - body.hair_color, - body.hair_style, - body.beard, - body.eye_color, - body.skin, - body.eyebrows, - body.accessory, - )) - - } else { -None - } - - , - Some(mesh_chest(body.chest)), - Some(mesh_belt(body.belt)), - Some(mesh_pants(body.pants)), + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => { + Some(humanoid_head_spec.mesh_head( + body.race, + body.body_type, + body.hair_color, + body.hair_style, + body.beard, + body.eye_color, + body.skin, + body.eyebrows, + body.accessory, + )) + } + CameraMode::FirstPerson => None, + }, + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => Some(mesh_chest(body.chest)), + CameraMode::FirstPerson => None, + }, + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => Some(mesh_belt(body.belt)), + CameraMode::FirstPerson => None, + }, + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => Some(mesh_pants(body.pants)), + CameraMode::FirstPerson => None, + }, Some(mesh_left_hand(body.hand)), Some(mesh_right_hand(body.hand)), - Some(mesh_left_foot(body.foot)), - Some(mesh_right_foot(body.foot)), - Some(mesh_main(equipment.and_then(|e| e.main.as_ref()))), - Some(mesh_left_shoulder(body.shoulder)), - Some(mesh_right_shoulder(body.shoulder)), + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => Some(mesh_left_foot(body.foot)), + CameraMode::FirstPerson => None, + }, + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => Some(mesh_right_foot(body.foot)), + CameraMode::FirstPerson => None, + }, + if camera_mode.unwrap_or_default() != CameraMode::FirstPerson + || character_state + .map(|cs| { + cs.action.is_attack() + || cs.action.is_block() + || cs.action.is_wield() + }) + .unwrap_or_default() + { + Some(mesh_main(equipment.and_then(|e| e.main.as_ref()))) + } else { + None + }, + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => { + Some(mesh_left_shoulder(body.shoulder)) + } + CameraMode::FirstPerson => None, + }, + match camera_mode.unwrap_or_default() { + CameraMode::ThirdPerson => { + Some(mesh_right_shoulder(body.shoulder)) + } + CameraMode::FirstPerson => None, + }, Some(mesh_draw()), None, None, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index c759b0fcee..f516df3a51 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -116,7 +116,14 @@ impl FigureMgr { let skeleton_attr = &self .model_cache - .get_or_create_model(renderer, *body, stats.map(|s| &s.equipment), tick, false, false) + .get_or_create_model( + renderer, + *body, + stats.map(|s| &s.equipment), + tick, + None, + None, + ) .1; match body { @@ -382,25 +389,33 @@ impl FigureMgr { .map(|state| (state.locals(), state.bone_consts())), } { // Don't render the player's body while in first person mode - let fp = - camera.get_mode() == CameraMode::FirstPerson - && client - .state() - .read_storage::() - .get(client.entity()) - .is_some() - && entity == client.entity(); - - let gliding = client + let player_camera_mode = if client .state() - .read_storage::() + .read_storage::() .get(client.entity()) - .unwrap_or(&common::comp::CharacterState::default()) - .movement == common::comp::MovementState::Glide; + .is_some() + && entity == client.entity() + { + Some(camera.get_mode()) + } else { + None + }; + + let character_state_storage = client + .state() + .read_storage::(); + let character_state = character_state_storage.get(client.entity()); let model = &self .model_cache - .get_or_create_model(renderer, *body, stats.map(|s| &s.equipment), tick, fp, gliding) + .get_or_create_model( + renderer, + *body, + stats.map(|s| &s.equipment), + tick, + player_camera_mode, + character_state, + ) .0; renderer.render_figure(model, globals, locals, bone_consts, lights);