Compare commits
2
Commits
0cb81ec2e9
...
ecb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84e731fbc8 | ||
|
|
65727ed04f |
@@ -605,7 +605,6 @@ impl Plugin for FighterAttackPlugin {
|
|||||||
intersect_attacks_with_hurtboxes,
|
intersect_attacks_with_hurtboxes,
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.after(crate::fighter::baked_animation::update_fighter_bone_matrices)
|
|
||||||
.in_set(GameplaySet::Attacks),
|
.in_set(GameplaySet::Attacks),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ mod tests {
|
|||||||
second.translate(FGVec3::lit("0", "3", "0"));
|
second.translate(FGVec3::lit("0", "3", "0"));
|
||||||
let mut matrices = FighterBoneMatrices::default();
|
let mut matrices = FighterBoneMatrices::default();
|
||||||
matrices.set_pose(
|
matrices.set_pose(
|
||||||
|
AnimKind::Wait,
|
||||||
&["root".into(), "hand".into()],
|
&["root".into(), "hand".into()],
|
||||||
&[None, Some(0)],
|
&[None, Some(0)],
|
||||||
&[first, second],
|
&[first, second],
|
||||||
@@ -239,6 +240,7 @@ mod tests {
|
|||||||
hand.translate(FGVec3::lit("0", "3", "0"));
|
hand.translate(FGVec3::lit("0", "3", "0"));
|
||||||
let mut matrices = FighterBoneMatrices::default();
|
let mut matrices = FighterBoneMatrices::default();
|
||||||
matrices.set_pose(
|
matrices.set_pose(
|
||||||
|
AnimKind::Wait,
|
||||||
&["root".into(), "hand".into()],
|
&["root".into(), "hand".into()],
|
||||||
&[None, Some(0)],
|
&[None, Some(0)],
|
||||||
&[root, hand],
|
&[root, hand],
|
||||||
@@ -266,9 +268,9 @@ mod tests {
|
|||||||
let parents = [None, Some(0)];
|
let parents = [None, Some(0)];
|
||||||
let pose = [FixedMat4::IDENTITY, FixedMat4::IDENTITY];
|
let pose = [FixedMat4::IDENTITY, FixedMat4::IDENTITY];
|
||||||
|
|
||||||
matrices.set_pose(&names, &parents, &pose, FGi32::ONE);
|
matrices.set_pose(AnimKind::Wait, &names, &parents, &pose, FGi32::ONE);
|
||||||
let capacities = matrices.buffer_capacities();
|
let capacities = matrices.buffer_capacities();
|
||||||
matrices.set_pose(&names, &parents, &pose, FGi32::ONE);
|
matrices.set_pose(AnimKind::Wait, &names, &parents, &pose, FGi32::ONE);
|
||||||
|
|
||||||
assert_eq!(capacities, matrices.buffer_capacities());
|
assert_eq!(capacities, matrices.buffer_capacities());
|
||||||
}
|
}
|
||||||
@@ -281,6 +283,7 @@ mod tests {
|
|||||||
hand.translate(FGVec3::lit("0", "2", "0"));
|
hand.translate(FGVec3::lit("0", "2", "0"));
|
||||||
let mut matrices = FighterBoneMatrices::default();
|
let mut matrices = FighterBoneMatrices::default();
|
||||||
matrices.set_pose(
|
matrices.set_pose(
|
||||||
|
AnimKind::Wait,
|
||||||
&["root".into(), "hand".into()],
|
&["root".into(), "hand".into()],
|
||||||
&[None, Some(0)],
|
&[None, Some(0)],
|
||||||
&[root, hand],
|
&[root, hand],
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ pub struct FighterBoneMatrices {
|
|||||||
local_matrices: Vec<FixedMat4>,
|
local_matrices: Vec<FixedMat4>,
|
||||||
previous_local_matrices: Vec<FixedMat4>,
|
previous_local_matrices: Vec<FixedMat4>,
|
||||||
model_matrices: Vec<Option<FixedMat4>>,
|
model_matrices: Vec<Option<FixedMat4>>,
|
||||||
|
presentation_kind: Option<AnimKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Debug, Default)]
|
#[derive(Component, Clone, Debug, Default)]
|
||||||
@@ -138,6 +139,7 @@ impl FighterBoneMatrices {
|
|||||||
}
|
}
|
||||||
pub(super) fn set_pose(
|
pub(super) fn set_pose(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
kind: AnimKind,
|
||||||
bone_names: &[String],
|
bone_names: &[String],
|
||||||
parents: &[Option<usize>],
|
parents: &[Option<usize>],
|
||||||
local: &[FixedMat4],
|
local: &[FixedMat4],
|
||||||
@@ -166,6 +168,7 @@ impl FighterBoneMatrices {
|
|||||||
self.previous_local_matrices.reserve(local.len());
|
self.previous_local_matrices.reserve(local.len());
|
||||||
self.model_matrices.reserve(local.len());
|
self.model_matrices.reserve(local.len());
|
||||||
std::mem::swap(&mut self.matrices, &mut self.previous_frame_matrices);
|
std::mem::swap(&mut self.matrices, &mut self.previous_frame_matrices);
|
||||||
|
let animation_changed = self.presentation_kind != Some(kind);
|
||||||
std::mem::swap(&mut self.local_matrices, &mut self.previous_local_matrices);
|
std::mem::swap(&mut self.local_matrices, &mut self.previous_local_matrices);
|
||||||
self.local_matrices.clear();
|
self.local_matrices.clear();
|
||||||
self.local_matrices.extend_from_slice(local);
|
self.local_matrices.extend_from_slice(local);
|
||||||
@@ -189,6 +192,14 @@ impl FighterBoneMatrices {
|
|||||||
model_scale.mul(matrix.expect("baked bone hierarchy should be valid"))
|
model_scale.mul(matrix.expect("baked bone hierarchy should be valid"))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
// A state transition is a discontinuity, not an animation frame to
|
||||||
|
// interpolate from the previous clip. Keep the presentation pose at
|
||||||
|
// the new clip's first/current frame immediately.
|
||||||
|
if animation_changed {
|
||||||
|
self.previous_local_matrices
|
||||||
|
.clone_from(&self.local_matrices);
|
||||||
|
}
|
||||||
|
self.presentation_kind = Some(kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +229,7 @@ pub fn update_fighter_bone_matrices(
|
|||||||
.get(&fighter.manifest)
|
.get(&fighter.manifest)
|
||||||
.expect("fighter manifest should be loaded before the match starts");
|
.expect("fighter manifest should be loaded before the match starts");
|
||||||
matrices.set_pose(
|
matrices.set_pose(
|
||||||
|
frame.kind,
|
||||||
&baked.bone_names,
|
&baked.bone_names,
|
||||||
&baked.parents,
|
&baked.parents,
|
||||||
pose,
|
pose,
|
||||||
|
|||||||
+15
-1
@@ -27,6 +27,7 @@ use crate::game_settings::GameSettings;
|
|||||||
use crate::input::FighterInput;
|
use crate::input::FighterInput;
|
||||||
use crate::math::int::FGi32;
|
use crate::math::int::FGi32;
|
||||||
use crate::math::vec::FGVec2;
|
use crate::math::vec::FGVec2;
|
||||||
|
use crate::math::vec3::FGVec3;
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
|
|
||||||
pub fn debug_draw_ecb(
|
pub fn debug_draw_ecb(
|
||||||
@@ -39,6 +40,12 @@ pub fn debug_draw_ecb(
|
|||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
) {
|
) {
|
||||||
for (ecb, trf, ecb_prev, trf_prev) in ecbs {
|
for (ecb, trf, ecb_prev, trf_prev) in ecbs {
|
||||||
|
gizmos.cross(
|
||||||
|
FGVec3::new(trf.0.x, trf.0.y, FGi32::ZERO).to_vec3(),
|
||||||
|
2.0,
|
||||||
|
bevy::color::palettes::css::BLUE,
|
||||||
|
);
|
||||||
|
|
||||||
let transformed =
|
let transformed =
|
||||||
ecb.to_3d_lineloop(Transform::from_xyz(trf.x.to_num(), trf.y.to_num(), 0.0));
|
ecb.to_3d_lineloop(Transform::from_xyz(trf.x.to_num(), trf.y.to_num(), 0.0));
|
||||||
gizmos.lineloop(transformed, YELLOW);
|
gizmos.lineloop(transformed, YELLOW);
|
||||||
@@ -153,7 +160,14 @@ pub fn fighter_debug(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn animation_debug(query: Query<(&FighterTranslation, &FighterFacingDirection, &FighterBoneMatrices)>, mut gizmos: Gizmos) {
|
pub fn animation_debug(
|
||||||
|
query: Query<(
|
||||||
|
&FighterTranslation,
|
||||||
|
&FighterFacingDirection,
|
||||||
|
&FighterBoneMatrices,
|
||||||
|
)>,
|
||||||
|
mut gizmos: Gizmos,
|
||||||
|
) {
|
||||||
for (global_transform, facing_dir, matrices) in query {
|
for (global_transform, facing_dir, matrices) in query {
|
||||||
let global_transform = global_transform.get_3d_transform(facing_dir);
|
let global_transform = global_transform.get_3d_transform(facing_dir);
|
||||||
let marker_transform = global_transform.to_mat4();
|
let marker_transform = global_transform.to_mat4();
|
||||||
|
|||||||
@@ -80,13 +80,10 @@ pub fn update_ecb(
|
|||||||
&FighterTranslation,
|
&FighterTranslation,
|
||||||
&FighterFacingDirection,
|
&FighterFacingDirection,
|
||||||
)>,
|
)>,
|
||||||
mut gizmos: Gizmos
|
|
||||||
) {
|
) {
|
||||||
for (mut ecb, surface_state, bone_indices, bone_matrices, translation, facing_dir) in query {
|
for (mut ecb, surface_state, bone_indices, bone_matrices, translation, facing_dir) in query {
|
||||||
let trf = translation.get_3d_transform(facing_dir);
|
let trf = translation.get_3d_transform(facing_dir);
|
||||||
|
|
||||||
gizmos.cross(trf.get_translation().to_vec3(), 2.0, bevy::color::palettes::css::BLUE);
|
|
||||||
|
|
||||||
let transformed_ecb_bones = bone_indices.indices.iter().filter_map(|idx| {
|
let transformed_ecb_bones = bone_indices.indices.iter().filter_map(|idx| {
|
||||||
let Some((_, bone_matrix)) = bone_matrices.get_by_idx(*idx) else {
|
let Some((_, bone_matrix)) = bone_matrices.get_by_idx(*idx) else {
|
||||||
return None;
|
return None;
|
||||||
@@ -114,8 +111,6 @@ pub fn update_ecb(
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
dbg!(ecb_lock_frames_remaining);
|
|
||||||
|
|
||||||
ecb.top = top;
|
ecb.top = top;
|
||||||
|
|
||||||
if ecb_lock_frames_remaining == 0 {
|
if ecb_lock_frames_remaining == 0 {
|
||||||
|
|||||||
+7
-2
@@ -171,10 +171,15 @@ impl Plugin for FighterPlugin {
|
|||||||
)*/
|
)*/
|
||||||
.add_systems(
|
.add_systems(
|
||||||
GgrsSchedule,
|
GgrsSchedule,
|
||||||
(ecb::update_ecb, state::state_collision_interrupt_system, ecb::decrement_ecb_lockout).chain().in_set(GameplaySet::Collision),
|
(
|
||||||
|
(ecb::update_ecb, ecb::decrement_ecb_lockout, state::state_collision_interrupt_system).chain(),
|
||||||
|
baked_animation::update_fighter_bone_matrices,
|
||||||
|
)
|
||||||
|
.chain()
|
||||||
|
.in_set(GameplaySet::Collision),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
PostUpdate,
|
||||||
(
|
(
|
||||||
motion::apply_fighter_translation_to_visuals,
|
motion::apply_fighter_translation_to_visuals,
|
||||||
animation::apply_animation,
|
animation::apply_animation,
|
||||||
|
|||||||
+3
-3
@@ -19,10 +19,10 @@ pub enum GameplaySet {
|
|||||||
StateUpdate,
|
StateUpdate,
|
||||||
/// Integrate velocities into positions.
|
/// Integrate velocities into positions.
|
||||||
Physics,
|
Physics,
|
||||||
/// Solve collision boxes
|
|
||||||
Animation,
|
|
||||||
/// Resolve the integrated positions against the stage.
|
/// Resolve the integrated positions against the stage.
|
||||||
Collision,
|
Collision,
|
||||||
|
/// Solve collision boxes
|
||||||
|
Animation,
|
||||||
/// Resolve attacks
|
/// Resolve attacks
|
||||||
Attacks,
|
Attacks,
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,8 @@ impl Plugin for GameplaySchedulePlugin {
|
|||||||
GameplaySet::Interrupt,
|
GameplaySet::Interrupt,
|
||||||
GameplaySet::StateUpdate,
|
GameplaySet::StateUpdate,
|
||||||
GameplaySet::Physics,
|
GameplaySet::Physics,
|
||||||
GameplaySet::Collision,
|
|
||||||
GameplaySet::Animation,
|
GameplaySet::Animation,
|
||||||
|
GameplaySet::Collision,
|
||||||
GameplaySet::Attacks,
|
GameplaySet::Attacks,
|
||||||
)
|
)
|
||||||
.chain(),
|
.chain(),
|
||||||
|
|||||||
Reference in New Issue
Block a user