mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'anim' into 'master'
Animation States See merge request veloren/veloren!31 Former-commit-id: 4f59aa8df9dbbcb9e89696a3b76b17a77a0f706a
This commit is contained in:
commit
19d6b7b38a
@ -160,6 +160,9 @@ impl Client {
|
|||||||
self.state.write_component(self.player, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY) * 0.1));
|
self.state.write_component(self.player, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY) * 0.1));
|
||||||
if input.move_dir.magnitude() > 0.01 {
|
if input.move_dir.magnitude() > 0.01 {
|
||||||
self.state.write_component(self.player, comp::phys::Dir(input.move_dir.normalized().into()));
|
self.state.write_component(self.player, comp::phys::Dir(input.move_dir.normalized().into()));
|
||||||
|
self.state.write_component(self.player, comp::Animation::Run);
|
||||||
|
} else {
|
||||||
|
self.state.write_component(self.player, comp::Animation::Idle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +181,11 @@ impl Client {
|
|||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the server about the player's currently playing animation
|
||||||
|
if let Some(animation) = self.state.read_storage().get(self.player).cloned() {
|
||||||
|
self.postbox.send_message(ClientMsg::PlayerAnimation(animation));
|
||||||
|
}
|
||||||
|
|
||||||
// Request chunks from the server
|
// Request chunks from the server
|
||||||
if let Some(pos) = self.state.read_storage::<comp::phys::Pos>().get(self.player) {
|
if let Some(pos) = self.state.read_storage::<comp::phys::Pos>().get(self.player) {
|
||||||
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
|
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
|
||||||
@ -234,6 +242,12 @@ impl Client {
|
|||||||
},
|
},
|
||||||
None => {},
|
None => {},
|
||||||
},
|
},
|
||||||
|
ServerMsg::EntityAnimation { entity, animation } => match self.state.ecs().entity_from_uid(entity) {
|
||||||
|
Some(entity) => {
|
||||||
|
self.state.write_component(entity, animation);
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
|
},
|
||||||
ServerMsg::TerrainChunkUpdate { key, chunk } => {
|
ServerMsg::TerrainChunkUpdate { key, chunk } => {
|
||||||
self.state.insert_chunk(key, *chunk);
|
self.state.insert_chunk(key, *chunk);
|
||||||
self.pending_chunks.remove(&key);
|
self.pending_chunks.remove(&key);
|
||||||
|
@ -18,6 +18,12 @@ pub enum Gender {
|
|||||||
Unspecified,
|
Unspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum Animation {
|
||||||
|
Idle,
|
||||||
|
Run,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Character {
|
pub struct Character {
|
||||||
race: Race,
|
race: Race,
|
||||||
@ -27,6 +33,7 @@ pub struct Character {
|
|||||||
belt: (),
|
belt: (),
|
||||||
arms: (),
|
arms: (),
|
||||||
feet: (),
|
feet: (),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Character {
|
impl Character {
|
||||||
@ -47,3 +54,7 @@ impl Character {
|
|||||||
impl Component for Character {
|
impl Component for Character {
|
||||||
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Component for Animation {
|
||||||
|
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
||||||
|
}
|
||||||
|
@ -5,3 +5,4 @@ pub mod phys;
|
|||||||
// Reexports
|
// Reexports
|
||||||
pub use character::Character;
|
pub use character::Character;
|
||||||
pub use player::Player;
|
pub use player::Player;
|
||||||
|
pub use character::Animation;
|
||||||
|
@ -6,10 +6,12 @@ pub enum ClientMsg {
|
|||||||
Connect {
|
Connect {
|
||||||
player: comp::Player,
|
player: comp::Player,
|
||||||
character: Option<comp::Character>,
|
character: Option<comp::Character>,
|
||||||
|
|
||||||
},
|
},
|
||||||
Ping,
|
Ping,
|
||||||
Pong,
|
Pong,
|
||||||
Chat(String),
|
Chat(String),
|
||||||
|
PlayerAnimation(comp::character::Animation),
|
||||||
PlayerPhysics {
|
PlayerPhysics {
|
||||||
pos: comp::phys::Pos,
|
pos: comp::phys::Pos,
|
||||||
vel: comp::phys::Vel,
|
vel: comp::phys::Vel,
|
||||||
|
@ -23,6 +23,10 @@ pub enum ServerMsg {
|
|||||||
vel: comp::phys::Vel,
|
vel: comp::phys::Vel,
|
||||||
dir: comp::phys::Dir,
|
dir: comp::phys::Dir,
|
||||||
},
|
},
|
||||||
|
EntityAnimation {
|
||||||
|
entity: u64,
|
||||||
|
animation: comp::Animation,
|
||||||
|
},
|
||||||
TerrainChunkUpdate {
|
TerrainChunkUpdate {
|
||||||
key: Vec3<i32>,
|
key: Vec3<i32>,
|
||||||
chunk: Box<TerrainChunk>,
|
chunk: Box<TerrainChunk>,
|
||||||
|
@ -100,6 +100,7 @@ impl State {
|
|||||||
ecs.internal_mut().register::<comp::phys::Pos>();
|
ecs.internal_mut().register::<comp::phys::Pos>();
|
||||||
ecs.internal_mut().register::<comp::phys::Vel>();
|
ecs.internal_mut().register::<comp::phys::Vel>();
|
||||||
ecs.internal_mut().register::<comp::phys::Dir>();
|
ecs.internal_mut().register::<comp::phys::Dir>();
|
||||||
|
ecs.internal_mut().register::<comp::Animation>();
|
||||||
|
|
||||||
// Register resources used by the ECS
|
// Register resources used by the ECS
|
||||||
ecs.internal_mut().add_resource(TimeOfDay(0.0));
|
ecs.internal_mut().add_resource(TimeOfDay(0.0));
|
||||||
|
@ -234,6 +234,7 @@ impl Server {
|
|||||||
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
|
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
|
||||||
if let Some(character) = character {
|
if let Some(character) = character {
|
||||||
state.write_component(entity, character);
|
state.write_component(entity, character);
|
||||||
|
|
||||||
}
|
}
|
||||||
state.write_component(entity, comp::phys::ForceUpdate);
|
state.write_component(entity, comp::phys::ForceUpdate);
|
||||||
|
|
||||||
@ -257,6 +258,7 @@ impl Server {
|
|||||||
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
|
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
|
||||||
ClientMsg::Pong => {},
|
ClientMsg::Pong => {},
|
||||||
ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)),
|
ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)),
|
||||||
|
ClientMsg::PlayerAnimation(animation) => state.write_component(entity, animation),
|
||||||
ClientMsg::PlayerPhysics { pos, vel, dir } => {
|
ClientMsg::PlayerPhysics { pos, vel, dir } => {
|
||||||
state.write_component(entity, pos);
|
state.write_component(entity, pos);
|
||||||
state.write_component(entity, vel);
|
state.write_component(entity, vel);
|
||||||
@ -347,11 +349,25 @@ impl Server {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match force_update {
|
match force_update {
|
||||||
|
|
||||||
|
|
||||||
Some(_) => self.clients.notify_connected(msg),
|
Some(_) => self.clients.notify_connected(msg),
|
||||||
None => self.clients.notify_connected_except(entity, msg),
|
None => self.clients.notify_connected_except(entity, msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync animation states
|
||||||
|
for (entity, &uid, &animation) in (
|
||||||
|
&self.state.ecs().internal().entities(),
|
||||||
|
&self.state.ecs().internal().read_storage::<Uid>(),
|
||||||
|
&self.state.ecs().internal().read_storage::<comp::Animation>(),
|
||||||
|
).join() {
|
||||||
|
self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation {
|
||||||
|
entity: uid.into(),
|
||||||
|
animation,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Remove all force flags
|
// Remove all force flags
|
||||||
self.state.ecs_mut().internal_mut().write_storage::<comp::phys::ForceUpdate>().clear();
|
self.state.ecs_mut().internal_mut().write_storage::<comp::phys::ForceUpdate>().clear();
|
||||||
}
|
}
|
||||||
|
48
voxygen/src/anim/character/idle.rs
Normal file
48
voxygen/src/anim/character/idle.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Standard
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
// Library
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
// Local
|
||||||
|
use super::{
|
||||||
|
CharacterSkeleton,
|
||||||
|
super::Animation,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct IdleAnimation;
|
||||||
|
|
||||||
|
//TODO: Make it actually good, possibly add the head rotating slightly, add breathing, etc.
|
||||||
|
impl Animation for IdleAnimation {
|
||||||
|
type Skeleton = CharacterSkeleton;
|
||||||
|
type Dependency = f64;
|
||||||
|
|
||||||
|
fn update_skeleton(
|
||||||
|
skeleton: &mut Self::Skeleton,
|
||||||
|
time: f64,
|
||||||
|
) {
|
||||||
|
skeleton.head.offset = Vec3::unit_z() * 13.0 / 11.0;
|
||||||
|
skeleton.head.ori = Quaternion::rotation_z(0.0);
|
||||||
|
|
||||||
|
skeleton.chest.offset = Vec3::unit_z() * 9.0 / 11.0;
|
||||||
|
skeleton.chest.ori = Quaternion::rotation_z(0.0);
|
||||||
|
|
||||||
|
skeleton.belt.offset = Vec3::unit_z() * 7.0 / 11.0;
|
||||||
|
skeleton.belt.ori = Quaternion::rotation_z(0.0);
|
||||||
|
|
||||||
|
skeleton.shorts.offset = Vec3::unit_z() * 4.0 / 11.0;
|
||||||
|
skeleton.shorts.ori = Quaternion::rotation_z(0.0);
|
||||||
|
|
||||||
|
skeleton.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / 11.0;
|
||||||
|
skeleton.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / 11.0;
|
||||||
|
|
||||||
|
skeleton.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / 11.0;
|
||||||
|
skeleton.l_foot.ori = Quaternion::rotation_x(0.0);
|
||||||
|
skeleton.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / 11.0;
|
||||||
|
skeleton.r_foot.ori = Quaternion::rotation_x(0.0);
|
||||||
|
|
||||||
|
skeleton.back.offset = Vec3::new(-9.0, 5.0, 18.0);
|
||||||
|
skeleton.back.ori = Quaternion::rotation_y(2.5);
|
||||||
|
skeleton.back.scale = Vec3::one();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
pub mod run;
|
pub mod run;
|
||||||
|
pub mod idle;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use self::run::RunAnimation;
|
pub use self::run::RunAnimation;
|
||||||
|
pub use self::idle::IdleAnimation;
|
||||||
|
|
||||||
// Crate
|
// Crate
|
||||||
use crate::render::FigureBoneData;
|
use crate::render::FigureBoneData;
|
||||||
|
@ -22,10 +22,10 @@ pub struct ClientInit {
|
|||||||
impl ClientInit {
|
impl ClientInit {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
connection_args: (String, u16, bool),
|
connection_args: (String, u16, bool),
|
||||||
client_args: (comp::Player, Option<comp::Character>, u64),
|
client_args: (comp::Player, Option<comp::Character>, Option<comp::Animation>, u64),
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (server_address, default_port, prefer_ipv6) = connection_args;
|
let (server_address, default_port, prefer_ipv6) = connection_args;
|
||||||
let (player, character, view_distance) = client_args;
|
let (player, character, animation, view_distance) = client_args;
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ impl PlayState for MainMenuState {
|
|||||||
(
|
(
|
||||||
comp::Player::new(username.clone()),
|
comp::Player::new(username.clone()),
|
||||||
Some(comp::Character::test()),
|
Some(comp::Character::test()),
|
||||||
|
Some(comp::Animation::Idle),
|
||||||
300,
|
300,
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
|
@ -8,6 +8,7 @@ use client::Client;
|
|||||||
use common::{
|
use common::{
|
||||||
comp,
|
comp,
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
|
msg
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
@ -27,6 +28,7 @@ use crate::{
|
|||||||
character::{
|
character::{
|
||||||
CharacterSkeleton,
|
CharacterSkeleton,
|
||||||
RunAnimation,
|
RunAnimation,
|
||||||
|
IdleAnimation,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mesh::Meshable,
|
mesh::Meshable,
|
||||||
@ -81,17 +83,21 @@ impl Figures {
|
|||||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
||||||
let time = client.state().get_time();
|
let time = client.state().get_time();
|
||||||
let ecs = client.state_mut().ecs_mut().internal_mut();
|
let ecs = client.state_mut().ecs_mut().internal_mut();
|
||||||
for (entity, pos, dir, character) in (
|
for (entity, pos, dir, character, animation) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<comp::phys::Pos>(),
|
&ecs.read_storage::<comp::phys::Pos>(),
|
||||||
&ecs.read_storage::<comp::phys::Dir>(),
|
&ecs.read_storage::<comp::phys::Dir>(),
|
||||||
&ecs.read_storage::<comp::Character>(),
|
&ecs.read_storage::<comp::Character>(),
|
||||||
|
&ecs.read_storage::<comp::Animation>(),
|
||||||
).join() {
|
).join() {
|
||||||
let state = self.states
|
let state = self.states
|
||||||
.entry(entity)
|
.entry(entity)
|
||||||
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
|
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
|
||||||
|
|
||||||
RunAnimation::update_skeleton(&mut state.skeleton, time);
|
match animation {
|
||||||
|
comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time),
|
||||||
|
comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time),
|
||||||
|
}
|
||||||
|
|
||||||
state.update(renderer, pos.0, dir.0);
|
state.update(renderer, pos.0, dir.0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user