mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Addressed comments
This commit is contained in:
parent
2e8ac0688c
commit
6713ac935f
@ -87,8 +87,8 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
|
|||||||
NpcKind::Pig => &self.quadruped_small.body,
|
NpcKind::Pig => &self.quadruped_small.body,
|
||||||
NpcKind::Wolf => &self.quadruped_medium.body,
|
NpcKind::Wolf => &self.quadruped_medium.body,
|
||||||
NpcKind::Duck => &self.bird_medium.body,
|
NpcKind::Duck => &self.bird_medium.body,
|
||||||
NpcKind::Clownfish => &self.fish_medium.body,
|
NpcKind::Marlin => &self.fish_medium.body,
|
||||||
NpcKind::Marlin => &self.fish_small.body,
|
NpcKind::Clownfish => &self.fish_small.body,
|
||||||
NpcKind::Ogre => &self.biped_large.body,
|
NpcKind::Ogre => &self.biped_large.body,
|
||||||
NpcKind::StoneGolem => &self.golem.body,
|
NpcKind::StoneGolem => &self.golem.body,
|
||||||
NpcKind::Archaeos => &self.theropod.body,
|
NpcKind::Archaeos => &self.theropod.body,
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
use super::{super::Animation, FishMediumSkeleton, SkeletonAttr};
|
use super::{
|
||||||
//use std::{f32::consts::PI, ops::Mul};
|
super::{vek::*, Animation},
|
||||||
use super::super::vek::*;
|
FishMediumSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
pub struct IdleAnimation;
|
pub struct IdleAnimation;
|
||||||
|
|
||||||
|
type IdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
|
||||||
|
|
||||||
impl Animation for IdleAnimation {
|
impl Animation for IdleAnimation {
|
||||||
type Dependency = f64;
|
type Dependency = IdleAnimationDependency;
|
||||||
type Skeleton = FishMediumSkeleton;
|
type Skeleton = FishMediumSkeleton;
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
#[cfg(feature = "use-dyn-lib")]
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_medium_idle\0";
|
const UPDATE_FN: &'static [u8] = b"fish_medium_idle\0";
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_idle")]
|
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_idle")]
|
||||||
|
|
||||||
fn update_skeleton_inner(
|
fn update_skeleton_inner(
|
||||||
skeleton: &Self::Skeleton,
|
skeleton: &Self::Skeleton,
|
||||||
_global_time: Self::Dependency,
|
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
|
||||||
anim_time: f64,
|
anim_time: f64,
|
||||||
_rate: &mut f32,
|
_rate: &mut f32,
|
||||||
s_a: &SkeletonAttr,
|
s_a: &SkeletonAttr,
|
||||||
@ -31,7 +35,6 @@ impl Animation for IdleAnimation {
|
|||||||
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1);
|
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1);
|
||||||
|
|
||||||
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
||||||
next.jaw.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
||||||
next.chest_front.orientation = Quaternion::rotation_x(0.0);
|
next.chest_front.orientation = Quaternion::rotation_x(0.0);
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
use super::{super::Animation, FishMediumSkeleton, SkeletonAttr};
|
|
||||||
//use std::f32::consts::PI;
|
|
||||||
use super::super::vek::*;
|
|
||||||
|
|
||||||
pub struct JumpAnimation;
|
|
||||||
|
|
||||||
impl Animation for JumpAnimation {
|
|
||||||
type Dependency = (f32, f64);
|
|
||||||
type Skeleton = FishMediumSkeleton;
|
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_medium_jump\0";
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_jump")]
|
|
||||||
fn update_skeleton_inner(
|
|
||||||
skeleton: &Self::Skeleton,
|
|
||||||
_global_time: Self::Dependency,
|
|
||||||
_anim_time: f64,
|
|
||||||
_rate: &mut f32,
|
|
||||||
s_a: &SkeletonAttr,
|
|
||||||
) -> Self::Skeleton {
|
|
||||||
let mut next = (*skeleton).clone();
|
|
||||||
|
|
||||||
next.chest_front.scale = Vec3::one() / 11.0;
|
|
||||||
|
|
||||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
|
||||||
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
|
||||||
next.jaw.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
|
||||||
next.chest_front.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
|
|
||||||
next.chest_back.orientation = Quaternion::rotation_z(0.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
|
||||||
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_l.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_r.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,8 @@
|
|||||||
pub mod idle;
|
pub mod idle;
|
||||||
pub mod jump;
|
|
||||||
pub mod run;
|
|
||||||
pub mod swim;
|
pub mod swim;
|
||||||
pub mod swimidle;
|
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use self::{
|
pub use self::{idle::IdleAnimation, swim::SwimAnimation};
|
||||||
idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation, swim::SwimAnimation,
|
|
||||||
swimidle::SwimIdleAnimation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
||||||
use common::comp::{self};
|
use common::comp::{self};
|
||||||
@ -64,6 +58,8 @@ pub struct SkeletonAttr {
|
|||||||
chest_back: (f32, f32),
|
chest_back: (f32, f32),
|
||||||
tail: (f32, f32),
|
tail: (f32, f32),
|
||||||
fin: (f32, f32, f32),
|
fin: (f32, f32, f32),
|
||||||
|
tempo: f32,
|
||||||
|
amplitude: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
|
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
|
||||||
@ -86,6 +82,8 @@ impl Default for SkeletonAttr {
|
|||||||
chest_back: (0.0, 0.0),
|
chest_back: (0.0, 0.0),
|
||||||
tail: (0.0, 0.0),
|
tail: (0.0, 0.0),
|
||||||
fin: (0.0, 0.0, 0.0),
|
fin: (0.0, 0.0, 0.0),
|
||||||
|
tempo: 0.0,
|
||||||
|
amplitude: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,6 +110,12 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
|||||||
fin: match (body.species, body.body_type) {
|
fin: match (body.species, body.body_type) {
|
||||||
(Marlin, _) => (2.5, 1.0, 3.5),
|
(Marlin, _) => (2.5, 1.0, 3.5),
|
||||||
},
|
},
|
||||||
|
tempo: match (body.species, body.body_type) {
|
||||||
|
(Marlin, _) => 4.0,
|
||||||
|
},
|
||||||
|
amplitude: match (body.species, body.body_type) {
|
||||||
|
(Marlin, _) => 4.0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
use super::{super::Animation, FishMediumSkeleton, SkeletonAttr};
|
|
||||||
//use std::f32::consts::PI;
|
|
||||||
use super::super::vek::*;
|
|
||||||
|
|
||||||
pub struct RunAnimation;
|
|
||||||
|
|
||||||
impl Animation for RunAnimation {
|
|
||||||
type Dependency = (f32, f64);
|
|
||||||
type Skeleton = FishMediumSkeleton;
|
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_medium_run\0";
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_run")]
|
|
||||||
fn update_skeleton_inner(
|
|
||||||
skeleton: &Self::Skeleton,
|
|
||||||
_global_time: Self::Dependency,
|
|
||||||
_anim_time: f64,
|
|
||||||
_rate: &mut f32,
|
|
||||||
s_a: &SkeletonAttr,
|
|
||||||
) -> Self::Skeleton {
|
|
||||||
let mut next = (*skeleton).clone();
|
|
||||||
|
|
||||||
next.chest_front.scale = Vec3::one() / 11.0;
|
|
||||||
|
|
||||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
|
||||||
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
|
||||||
next.jaw.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
|
||||||
next.chest_front.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
|
|
||||||
next.chest_back.orientation = Quaternion::rotation_z(0.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
|
||||||
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_l.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_r.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,15 +20,15 @@ impl Animation for SwimAnimation {
|
|||||||
fn update_skeleton_inner(
|
fn update_skeleton_inner(
|
||||||
skeleton: &Self::Skeleton,
|
skeleton: &Self::Skeleton,
|
||||||
(velocity, orientation, last_ori, _global_time, avg_vel, acc_vel): Self::Dependency,
|
(velocity, orientation, last_ori, _global_time, avg_vel, acc_vel): Self::Dependency,
|
||||||
anim_time: f64,
|
_anim_time: f64,
|
||||||
_rate: &mut f32,
|
_rate: &mut f32,
|
||||||
s_a: &SkeletonAttr,
|
s_a: &SkeletonAttr,
|
||||||
) -> Self::Skeleton {
|
) -> Self::Skeleton {
|
||||||
let mut next = (*skeleton).clone();
|
let mut next = (*skeleton).clone();
|
||||||
|
|
||||||
let slowalt = (anim_time as f32 * 2.5 + PI + 0.2).sin();
|
let slowalt = (acc_vel as f32 * s_a.tempo / 1.5 + PI + 0.2).sin();
|
||||||
let fast = (acc_vel * 4.0 + PI).sin();
|
let fast = (acc_vel * s_a.tempo + PI).sin();
|
||||||
let fastalt = (acc_vel * 4.0 + PI + 0.2).sin();
|
let fastalt = (acc_vel * s_a.tempo + PI + 0.2).sin();
|
||||||
|
|
||||||
let ori: Vec2<f32> = Vec2::from(orientation);
|
let ori: Vec2<f32> = Vec2::from(orientation);
|
||||||
let last_ori = Vec2::from(last_ori);
|
let last_ori = Vec2::from(last_ori);
|
||||||
@ -43,10 +43,9 @@ impl Animation for SwimAnimation {
|
|||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
} * 1.3;
|
} * 1.3;
|
||||||
let abstilt = tilt.abs();
|
|
||||||
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude());
|
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude());
|
||||||
|
let vel = (velocity.magnitude()).min(s_a.amplitude);
|
||||||
println!("{}", acc_vel);
|
let slowvel = vel * 0.1;
|
||||||
|
|
||||||
next.chest_front.scale = Vec3::one() / 11.0;
|
next.chest_front.scale = Vec3::one() / 11.0;
|
||||||
|
|
||||||
@ -54,28 +53,22 @@ impl Animation for SwimAnimation {
|
|||||||
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1 + tilt * -2.0);
|
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1 + tilt * -2.0);
|
||||||
|
|
||||||
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
||||||
next.jaw.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
||||||
next.chest_front.orientation =
|
next.chest_front.orientation = Quaternion::rotation_x(velocity.z.abs() * -0.005 + x_tilt)
|
||||||
Quaternion::rotation_x(velocity.z.abs() * -0.005 + abstilt * 1.0 + x_tilt)
|
* Quaternion::rotation_z(fast * vel * -0.02);
|
||||||
* Quaternion::rotation_z(fast * velocity.magnitude() * -0.02);
|
|
||||||
|
|
||||||
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
|
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
|
||||||
next.chest_back.orientation =
|
next.chest_back.orientation = Quaternion::rotation_z(fastalt * slowvel + tilt * 2.0);
|
||||||
Quaternion::rotation_z(fastalt * velocity.magnitude() * 0.1 + tilt * 2.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
||||||
next.tail.orientation =
|
next.tail.orientation = Quaternion::rotation_z(fast * slowvel + tilt * 2.0);
|
||||||
Quaternion::rotation_z(fast * velocity.magnitude() * 0.1 + tilt * 2.0);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
||||||
next.fin_l.orientation =
|
next.fin_l.orientation = Quaternion::rotation_z(fast * slowvel - 0.1 + tilt * -0.5);
|
||||||
Quaternion::rotation_z(fast * velocity.magnitude() * 0.1 - 0.1 + tilt * -0.5);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
||||||
next.fin_r.orientation =
|
next.fin_r.orientation = Quaternion::rotation_z(fast * -slowvel + 0.1 + tilt * -0.5);
|
||||||
Quaternion::rotation_z(fast * velocity.magnitude() * -0.1 + 0.1 + tilt * -0.5);
|
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
use super::{
|
|
||||||
super::{vek::*, Animation},
|
|
||||||
FishMediumSkeleton, SkeletonAttr,
|
|
||||||
};
|
|
||||||
use std::f32::consts::PI;
|
|
||||||
|
|
||||||
pub struct SwimIdleAnimation;
|
|
||||||
|
|
||||||
type SwimIdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
|
|
||||||
|
|
||||||
impl Animation for SwimIdleAnimation {
|
|
||||||
type Dependency = SwimIdleAnimationDependency;
|
|
||||||
type Skeleton = FishMediumSkeleton;
|
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_medium_swimidle\0";
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_swimidle")]
|
|
||||||
|
|
||||||
fn update_skeleton_inner(
|
|
||||||
skeleton: &Self::Skeleton,
|
|
||||||
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
|
|
||||||
anim_time: f64,
|
|
||||||
_rate: &mut f32,
|
|
||||||
s_a: &SkeletonAttr,
|
|
||||||
) -> Self::Skeleton {
|
|
||||||
let mut next = (*skeleton).clone();
|
|
||||||
|
|
||||||
let slow = (anim_time as f32 * 3.5 + PI).sin();
|
|
||||||
let slowalt = (anim_time as f32 * 3.5 + PI + 0.2).sin();
|
|
||||||
|
|
||||||
next.chest_front.scale = Vec3::one() / 11.0;
|
|
||||||
|
|
||||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
|
||||||
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1);
|
|
||||||
|
|
||||||
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
|
|
||||||
next.jaw.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
|
|
||||||
next.chest_front.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
|
|
||||||
next.chest_back.orientation = Quaternion::rotation_z(slowalt * 0.1);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
|
||||||
next.tail.orientation = Quaternion::rotation_z(slow * 0.1);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_l.orientation = Quaternion::rotation_z(slow * 0.1 - 0.1);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_r.orientation = Quaternion::rotation_z(-slow * 0.1 + 0.1);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +1,45 @@
|
|||||||
use super::{super::Animation, FishSmallSkeleton, SkeletonAttr};
|
use super::{
|
||||||
//use std::{f32::consts::PI, ops::Mul};
|
super::{vek::*, Animation},
|
||||||
use super::super::vek::*;
|
FishSmallSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
pub struct IdleAnimation;
|
pub struct IdleAnimation;
|
||||||
|
|
||||||
|
type IdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
|
||||||
|
|
||||||
impl Animation for IdleAnimation {
|
impl Animation for IdleAnimation {
|
||||||
type Dependency = f64;
|
type Dependency = IdleAnimationDependency;
|
||||||
type Skeleton = FishSmallSkeleton;
|
type Skeleton = FishSmallSkeleton;
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
#[cfg(feature = "use-dyn-lib")]
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_small_idle\0";
|
const UPDATE_FN: &'static [u8] = b"fish_small_idle\0";
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_idle")]
|
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_idle")]
|
||||||
|
|
||||||
fn update_skeleton_inner(
|
fn update_skeleton_inner(
|
||||||
skeleton: &Self::Skeleton,
|
skeleton: &Self::Skeleton,
|
||||||
_global_time: Self::Dependency,
|
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
|
||||||
_anim_time: f64,
|
anim_time: f64,
|
||||||
_rate: &mut f32,
|
_rate: &mut f32,
|
||||||
s_a: &SkeletonAttr,
|
s_a: &SkeletonAttr,
|
||||||
) -> Self::Skeleton {
|
) -> Self::Skeleton {
|
||||||
let mut next = (*skeleton).clone();
|
let mut next = (*skeleton).clone();
|
||||||
|
|
||||||
|
let slow = (anim_time as f32 * 3.5 + PI).sin();
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / 13.0;
|
next.chest.scale = Vec3::one() / 13.0;
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
||||||
next.chest.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
||||||
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
next.tail.orientation = Quaternion::rotation_z(slow * 0.1);
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
||||||
next.fin_l.orientation = Quaternion::rotation_y(0.0);
|
next.fin_l.orientation = Quaternion::rotation_z(slow * 0.1 - 0.1);
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
||||||
next.fin_r.orientation = Quaternion::rotation_y(0.0);
|
next.fin_r.orientation = Quaternion::rotation_z(-slow * 0.1 + 0.1);
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
use super::{super::Animation, FishSmallSkeleton, SkeletonAttr};
|
|
||||||
//use std::f32::consts::PI;
|
|
||||||
use super::super::vek::*;
|
|
||||||
|
|
||||||
pub struct JumpAnimation;
|
|
||||||
|
|
||||||
impl Animation for JumpAnimation {
|
|
||||||
type Dependency = (f32, f64);
|
|
||||||
type Skeleton = FishSmallSkeleton;
|
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_small_jump\0";
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_jump")]
|
|
||||||
fn update_skeleton_inner(
|
|
||||||
skeleton: &Self::Skeleton,
|
|
||||||
_global_time: Self::Dependency,
|
|
||||||
_anim_time: f64,
|
|
||||||
_rate: &mut f32,
|
|
||||||
s_a: &SkeletonAttr,
|
|
||||||
) -> Self::Skeleton {
|
|
||||||
let mut next = (*skeleton).clone();
|
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / 13.0;
|
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
|
||||||
next.chest.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
|
||||||
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_l.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_r.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,8 @@
|
|||||||
pub mod idle;
|
pub mod idle;
|
||||||
pub mod jump;
|
|
||||||
pub mod run;
|
|
||||||
pub mod swim;
|
pub mod swim;
|
||||||
pub mod swimidle;
|
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use self::{
|
pub use self::{idle::IdleAnimation, swim::SwimAnimation};
|
||||||
idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation, swim::SwimAnimation,
|
|
||||||
swimidle::SwimIdleAnimation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
||||||
use common::comp::{self};
|
use common::comp::{self};
|
||||||
@ -53,6 +47,8 @@ pub struct SkeletonAttr {
|
|||||||
chest: (f32, f32),
|
chest: (f32, f32),
|
||||||
tail: (f32, f32),
|
tail: (f32, f32),
|
||||||
fin: (f32, f32, f32),
|
fin: (f32, f32, f32),
|
||||||
|
tempo: f32,
|
||||||
|
amplitude: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
|
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
|
||||||
@ -72,6 +68,8 @@ impl Default for SkeletonAttr {
|
|||||||
chest: (0.0, 0.0),
|
chest: (0.0, 0.0),
|
||||||
tail: (0.0, 0.0),
|
tail: (0.0, 0.0),
|
||||||
fin: (0.0, 0.0, 0.0),
|
fin: (0.0, 0.0, 0.0),
|
||||||
|
tempo: 0.0,
|
||||||
|
amplitude: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,6 +87,12 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
|||||||
fin: match (body.species, body.body_type) {
|
fin: match (body.species, body.body_type) {
|
||||||
(Clownfish, _) => (2.0, 0.5, 1.0),
|
(Clownfish, _) => (2.0, 0.5, 1.0),
|
||||||
},
|
},
|
||||||
|
tempo: match (body.species, body.body_type) {
|
||||||
|
(Clownfish, _) => 5.0,
|
||||||
|
},
|
||||||
|
amplitude: match (body.species, body.body_type) {
|
||||||
|
(Clownfish, _) => 4.0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
use super::{super::Animation, FishSmallSkeleton, SkeletonAttr};
|
|
||||||
//use std::{f32::consts::PI, ops::Mul};
|
|
||||||
use super::super::vek::*;
|
|
||||||
|
|
||||||
pub struct RunAnimation;
|
|
||||||
|
|
||||||
impl Animation for RunAnimation {
|
|
||||||
type Dependency = (f32, f64);
|
|
||||||
type Skeleton = FishSmallSkeleton;
|
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_small_run\0";
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_run")]
|
|
||||||
fn update_skeleton_inner(
|
|
||||||
skeleton: &Self::Skeleton,
|
|
||||||
(_velocity, _global_time): Self::Dependency,
|
|
||||||
_anim_time: f64,
|
|
||||||
_rate: &mut f32,
|
|
||||||
s_a: &SkeletonAttr,
|
|
||||||
) -> Self::Skeleton {
|
|
||||||
let mut next = (*skeleton).clone();
|
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / 13.0;
|
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
|
||||||
next.chest.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
|
||||||
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_l.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_r.orientation = Quaternion::rotation_y(0.0);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,7 @@ impl Animation for SwimAnimation {
|
|||||||
) -> Self::Skeleton {
|
) -> Self::Skeleton {
|
||||||
let mut next = (*skeleton).clone();
|
let mut next = (*skeleton).clone();
|
||||||
|
|
||||||
let fast = (acc_vel * 5.0 + PI).sin();
|
let fast = (acc_vel * s_a.tempo + PI).sin();
|
||||||
|
|
||||||
let ori: Vec2<f32> = Vec2::from(orientation);
|
let ori: Vec2<f32> = Vec2::from(orientation);
|
||||||
let last_ori = Vec2::from(last_ori);
|
let last_ori = Vec2::from(last_ori);
|
||||||
@ -41,22 +41,24 @@ impl Animation for SwimAnimation {
|
|||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
} * 1.3;
|
} * 1.3;
|
||||||
let abstilt = tilt.abs();
|
|
||||||
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude());
|
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude());
|
||||||
|
let vel = (velocity.magnitude()).min(s_a.amplitude);
|
||||||
|
let slowvel = vel * 0.1;
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / 13.0;
|
next.chest.scale = Vec3::one() / 13.0;
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
||||||
next.chest.orientation = Quaternion::rotation_x(velocity.z.abs() * -0.005 + abstilt * 1.0 + x_tilt) * Quaternion::rotation_z(fast * -0.1);
|
next.chest.orientation = Quaternion::rotation_x(velocity.z.abs() * -0.005 + x_tilt)
|
||||||
|
* Quaternion::rotation_z(fast * -0.1);
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
||||||
next.tail.orientation = Quaternion::rotation_z(fast * -1.0 * velocity.magnitude() * 0.1 + tilt * 2.0);
|
next.tail.orientation = Quaternion::rotation_z(fast * -1.0 * slowvel + tilt * 2.0);
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
||||||
next.fin_l.orientation = Quaternion::rotation_z(fast * 0.6 * velocity.magnitude() * 0.1 - 0.3 + tilt * -0.5);
|
next.fin_l.orientation = Quaternion::rotation_z(fast * 0.6 * slowvel - 0.3 + tilt * -0.5);
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
||||||
next.fin_r.orientation = Quaternion::rotation_z(fast * -0.6 * velocity.magnitude() * 0.1 + 0.3 + tilt * -0.5);
|
next.fin_r.orientation = Quaternion::rotation_z(fast * -0.6 * slowvel + 0.3 + tilt * -0.5);
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
use super::{
|
|
||||||
super::{vek::*, Animation},
|
|
||||||
FishSmallSkeleton, SkeletonAttr,
|
|
||||||
};
|
|
||||||
use std::f32::consts::PI;
|
|
||||||
|
|
||||||
pub struct SwimIdleAnimation;
|
|
||||||
|
|
||||||
type SwimIdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
|
|
||||||
|
|
||||||
impl Animation for SwimIdleAnimation {
|
|
||||||
type Dependency = SwimIdleAnimationDependency;
|
|
||||||
type Skeleton = FishSmallSkeleton;
|
|
||||||
|
|
||||||
#[cfg(feature = "use-dyn-lib")]
|
|
||||||
const UPDATE_FN: &'static [u8] = b"fish_small_swimidle\0";
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_swimidle")]
|
|
||||||
|
|
||||||
fn update_skeleton_inner(
|
|
||||||
skeleton: &Self::Skeleton,
|
|
||||||
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
|
|
||||||
anim_time: f64,
|
|
||||||
_rate: &mut f32,
|
|
||||||
s_a: &SkeletonAttr,
|
|
||||||
) -> Self::Skeleton {
|
|
||||||
let mut next = (*skeleton).clone();
|
|
||||||
|
|
||||||
let slow = (anim_time as f32 * 3.5 + PI).sin();
|
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / 13.0;
|
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
|
|
||||||
next.chest.orientation = Quaternion::rotation_x(0.0);
|
|
||||||
|
|
||||||
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
|
|
||||||
next.tail.orientation = Quaternion::rotation_z(slow * 0.1);
|
|
||||||
|
|
||||||
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_l.orientation = Quaternion::rotation_z(slow * 0.1 - 0.1);
|
|
||||||
|
|
||||||
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
|
|
||||||
next.fin_r.orientation = Quaternion::rotation_z(-slow * 0.1 + 0.1);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
@ -2170,13 +2170,6 @@ impl FigureMgr {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bad, can potentially overflow
|
|
||||||
if vel.0.magnitude_squared() != 0.0 {
|
|
||||||
state.acc_vel += vel.0.magnitude() * dt;
|
|
||||||
} else {
|
|
||||||
state.acc_vel = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !character.same_variant(&last_character.0) {
|
if !character.same_variant(&last_character.0) {
|
||||||
state.state_time = 0.0;
|
state.state_time = 0.0;
|
||||||
}
|
}
|
||||||
@ -2186,32 +2179,8 @@ impl FigureMgr {
|
|||||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||||
physics.in_liquid.is_some(), // In water
|
physics.in_liquid.is_some(), // In water
|
||||||
) {
|
) {
|
||||||
// Standing
|
// Idle
|
||||||
(true, false, false) => anim::fish_medium::IdleAnimation::update_skeleton(
|
(_, false, _) => anim::fish_medium::IdleAnimation::update_skeleton(
|
||||||
&FishMediumSkeleton::default(),
|
|
||||||
time,
|
|
||||||
state.state_time,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
),
|
|
||||||
// Running
|
|
||||||
(true, true, false) => anim::fish_medium::RunAnimation::update_skeleton(
|
|
||||||
&FishMediumSkeleton::default(),
|
|
||||||
(vel.0.magnitude(), time),
|
|
||||||
state.state_time,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
),
|
|
||||||
// In air
|
|
||||||
(false, _, false) => anim::fish_medium::JumpAnimation::update_skeleton(
|
|
||||||
&FishMediumSkeleton::default(),
|
|
||||||
(vel.0.magnitude(), time),
|
|
||||||
state.state_time,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
),
|
|
||||||
// Idle Water
|
|
||||||
(_, false, true) => anim::fish_medium::SwimIdleAnimation::update_skeleton(
|
|
||||||
&FishMediumSkeleton::default(),
|
&FishMediumSkeleton::default(),
|
||||||
(vel.0, ori, state.last_ori, time, state.avg_vel),
|
(vel.0, ori, state.last_ori, time, state.avg_vel),
|
||||||
state.state_time,
|
state.state_time,
|
||||||
@ -2219,7 +2188,7 @@ impl FigureMgr {
|
|||||||
skeleton_attr,
|
skeleton_attr,
|
||||||
),
|
),
|
||||||
// Swim
|
// Swim
|
||||||
(_, true, true) => anim::fish_medium::SwimAnimation::update_skeleton(
|
(_, true, _) => anim::fish_medium::SwimAnimation::update_skeleton(
|
||||||
&FishMediumSkeleton::default(),
|
&FishMediumSkeleton::default(),
|
||||||
(
|
(
|
||||||
vel.0,
|
vel.0,
|
||||||
@ -2586,13 +2555,6 @@ impl FigureMgr {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bad, can potentially overflow
|
|
||||||
if vel.0.magnitude_squared() != 0.0 {
|
|
||||||
state.acc_vel += vel.0.magnitude() * dt;
|
|
||||||
} else {
|
|
||||||
state.acc_vel = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !character.same_variant(&last_character.0) {
|
if !character.same_variant(&last_character.0) {
|
||||||
state.state_time = 0.0;
|
state.state_time = 0.0;
|
||||||
}
|
}
|
||||||
@ -2602,32 +2564,8 @@ impl FigureMgr {
|
|||||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||||
physics.in_liquid.is_some(), // In water
|
physics.in_liquid.is_some(), // In water
|
||||||
) {
|
) {
|
||||||
// Standing
|
// Idle
|
||||||
(true, false, false) => anim::fish_small::IdleAnimation::update_skeleton(
|
(_, false, _) => anim::fish_small::IdleAnimation::update_skeleton(
|
||||||
&FishSmallSkeleton::default(),
|
|
||||||
time,
|
|
||||||
state.state_time,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
),
|
|
||||||
// Running
|
|
||||||
(true, true, false) => anim::fish_small::RunAnimation::update_skeleton(
|
|
||||||
&FishSmallSkeleton::default(),
|
|
||||||
(vel.0.magnitude(), time),
|
|
||||||
state.state_time,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
),
|
|
||||||
// In air
|
|
||||||
(false, _, false) => anim::fish_small::JumpAnimation::update_skeleton(
|
|
||||||
&FishSmallSkeleton::default(),
|
|
||||||
(vel.0.magnitude(), time),
|
|
||||||
state.state_time,
|
|
||||||
&mut state_animation_rate,
|
|
||||||
skeleton_attr,
|
|
||||||
),
|
|
||||||
// Idle Water
|
|
||||||
(_, false, true) => anim::fish_small::SwimIdleAnimation::update_skeleton(
|
|
||||||
&FishSmallSkeleton::default(),
|
&FishSmallSkeleton::default(),
|
||||||
(vel.0, ori, state.last_ori, time, state.avg_vel),
|
(vel.0, ori, state.last_ori, time, state.avg_vel),
|
||||||
state.state_time,
|
state.state_time,
|
||||||
@ -2635,7 +2573,7 @@ impl FigureMgr {
|
|||||||
skeleton_attr,
|
skeleton_attr,
|
||||||
),
|
),
|
||||||
// Swim
|
// Swim
|
||||||
(_, true, true) => anim::fish_small::SwimAnimation::update_skeleton(
|
(_, true, _) => anim::fish_small::SwimAnimation::update_skeleton(
|
||||||
&FishSmallSkeleton::default(),
|
&FishSmallSkeleton::default(),
|
||||||
(
|
(
|
||||||
vel.0,
|
vel.0,
|
||||||
@ -3979,6 +3917,13 @@ impl<S: Skeleton> FigureState<S> {
|
|||||||
self.avg_vel = (1.0 - smoothing) * self.avg_vel + smoothing * (pos - last_pos) / dt;
|
self.avg_vel = (1.0 - smoothing) * self.avg_vel + smoothing * (pos - last_pos) / dt;
|
||||||
}
|
}
|
||||||
self.last_pos = Some(pos);
|
self.last_pos = Some(pos);
|
||||||
|
|
||||||
|
// Can potentially overflow
|
||||||
|
if self.avg_vel.magnitude_squared() != 0.0 {
|
||||||
|
self.acc_vel += self.avg_vel.magnitude() * dt;
|
||||||
|
} else {
|
||||||
|
self.acc_vel = 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }
|
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user