Compare commits

...
2 Commits
Author SHA1 Message Date
EIREXE 84e731fbc8 Fix various runtime shenanigans
CI / build-and-test (pull_request) Successful in 1m32s
CI / production-build (pull_request) Successful in 10m22s
2026-09-25 16:29:11 +02:00
EIREXE 65727ed04f Remove gizmo shenanigans 2026-09-25 16:00:21 +02:00
7 changed files with 44 additions and 16 deletions
-1
View File
@@ -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),
); );
} }
+5 -2
View File
@@ -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],
+12
View File
@@ -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
View File
@@ -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();
-5
View File
@@ -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
View File
@@ -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
View File
@@ -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(),