Some other bullshit
This commit is contained in:
@@ -49,7 +49,6 @@ pub fn apply_animation(
|
|||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
for (mut trf, facing_direction, frame) in children {
|
for (mut trf, facing_direction, frame) in children {
|
||||||
// Melee model scale is in decimeters
|
|
||||||
trf.rotation = Quat::IDENTITY;
|
trf.rotation = Quat::IDENTITY;
|
||||||
if let AnimKind::Turn = frame.kind {
|
if let AnimKind::Turn = frame.kind {
|
||||||
trf.rotate_local_y(
|
trf.rotate_local_y(
|
||||||
|
|||||||
+18
-2
@@ -149,14 +149,16 @@ pub fn fighter_debug(
|
|||||||
|
|
||||||
pub fn animation_debug(query: Query<(&GlobalTransform, &FighterBoneMatrices)>, mut gizmos: Gizmos) {
|
pub fn animation_debug(query: Query<(&GlobalTransform, &FighterBoneMatrices)>, mut gizmos: Gizmos) {
|
||||||
for (global_transform, matrices) in query {
|
for (global_transform, matrices) in query {
|
||||||
|
let (_, rotation, translation) = global_transform.to_scale_rotation_translation();
|
||||||
|
let marker_transform = Transform::from_translation(translation).with_rotation(rotation);
|
||||||
for (_, matrix) in matrices.iter() {
|
for (_, matrix) in matrices.iter() {
|
||||||
let pos = global_transform.transform_point(Vec3::new(
|
let pos = marker_transform.transform_point(Vec3::new(
|
||||||
matrix.cols[3][0].to_num(),
|
matrix.cols[3][0].to_num(),
|
||||||
matrix.cols[3][1].to_num(),
|
matrix.cols[3][1].to_num(),
|
||||||
matrix.cols[3][2].to_num(),
|
matrix.cols[3][2].to_num(),
|
||||||
));
|
));
|
||||||
gizmos.cross(pos, 0.5, bevy::color::palettes::css::RED);
|
gizmos.cross(pos, 0.5, bevy::color::palettes::css::RED);
|
||||||
gizmos.axes(*global_transform, 1.0);
|
gizmos.axes(marker_transform, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,6 +292,20 @@ fn capsule_wireframe() -> &'static CapsuleWireframe {
|
|||||||
mod capsule_debug_tests {
|
mod capsule_debug_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn animation_markers_ignore_visual_scale() {
|
||||||
|
let global = GlobalTransform::from(Transform {
|
||||||
|
translation: Vec3::new(3.0, 4.0, 5.0),
|
||||||
|
rotation: Quat::from_rotation_y(std::f32::consts::FRAC_PI_2),
|
||||||
|
scale: Vec3::splat(10.0),
|
||||||
|
});
|
||||||
|
let (_, rotation, translation) = global.to_scale_rotation_translation();
|
||||||
|
let marker_transform = Transform::from_translation(translation).with_rotation(rotation);
|
||||||
|
|
||||||
|
let marker = marker_transform.transform_point(Vec3::new(2.0, 0.0, 0.0));
|
||||||
|
assert!(marker.abs_diff_eq(Vec3::new(3.0, 4.0, 3.0), 1e-5));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn capsule_wireframe_caps_extend_in_opposite_directions() {
|
fn capsule_wireframe_caps_extend_in_opposite_directions() {
|
||||||
let wireframe = capsule_wireframe();
|
let wireframe = capsule_wireframe();
|
||||||
|
|||||||
+18
-6
@@ -1,9 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{asset::UntypedHandle, prelude::*};
|
||||||
asset::UntypedHandle,
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use bevy_asset_loader::asset_collection::AssetCollection;
|
use bevy_asset_loader::asset_collection::AssetCollection;
|
||||||
use ron_asset_manager::prelude::RonAsset;
|
use ron_asset_manager::prelude::RonAsset;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -11,10 +8,16 @@ use strum::IntoEnumIterator;
|
|||||||
use strum_macros::EnumIter;
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AppState, fighter::{FighterAttributes, FighterCameraProfile, animation::AnimKind, attack::AttackKind}, game_settings::GameSettings, math::{int::FGi32, vec3::FGVec3}, texture_reference::TextureReference,
|
AppState,
|
||||||
|
fighter::{FighterAttributes, FighterCameraProfile, animation::AnimKind, attack::AttackKind},
|
||||||
|
game_settings::GameSettings,
|
||||||
|
math::{int::FGi32, vec3::FGVec3},
|
||||||
|
texture_reference::TextureReference,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Reflect, EnumIter, Default)]
|
#[derive(
|
||||||
|
Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Reflect, EnumIter, Default,
|
||||||
|
)]
|
||||||
pub enum FighterId {
|
pub enum FighterId {
|
||||||
#[default]
|
#[default]
|
||||||
TestFighter,
|
TestFighter,
|
||||||
@@ -35,6 +38,8 @@ pub struct FighterHurtbox {
|
|||||||
pub struct FighterManifest {
|
pub struct FighterManifest {
|
||||||
pub id: FighterId,
|
pub id: FighterId,
|
||||||
pub model_path: String,
|
pub model_path: String,
|
||||||
|
#[reflect(ignore)]
|
||||||
|
pub model_scale: FGi32,
|
||||||
pub baked_animation_path: String,
|
pub baked_animation_path: String,
|
||||||
#[asset]
|
#[asset]
|
||||||
#[dependency]
|
#[dependency]
|
||||||
@@ -108,6 +113,13 @@ pub fn prepare_fighter_manifests(
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if manifest.model_scale <= FGi32::ZERO {
|
||||||
|
fail(
|
||||||
|
&mut next_state,
|
||||||
|
&format!("{:?} has a non-positive model scale", manifest.id),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if manifest.baked_animation_path.is_empty() {
|
if manifest.baked_animation_path.is_empty() {
|
||||||
fail(
|
fail(
|
||||||
&mut next_state,
|
&mut next_state,
|
||||||
|
|||||||
+8
-4
@@ -22,12 +22,15 @@
|
|||||||
//! appears in `Add Component`. No registration code is needed.
|
//! appears in `Add Component`. No registration code is needed.
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::processor::{AssetProcessor, ProcessorState}, prelude::*, settings::SettingsPlugin, tasks::block_on,
|
asset::processor::{AssetProcessor, ProcessorState},
|
||||||
|
prelude::*,
|
||||||
|
settings::SettingsPlugin,
|
||||||
|
tasks::block_on,
|
||||||
};
|
};
|
||||||
use bevy_asset_loader::prelude::*;
|
use bevy_asset_loader::prelude::*;
|
||||||
use ron_asset_manager::RonAssetPlugin;
|
|
||||||
use bevy_wind_waker_shader::prelude::*;
|
use bevy_wind_waker_shader::prelude::*;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use ron_asset_manager::RonAssetPlugin;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
camera::MatchCameraPlugin, fighter::manifest::FighterManifest, game_settings::GameSettings,
|
camera::MatchCameraPlugin, fighter::manifest::FighterManifest, game_settings::GameSettings,
|
||||||
@@ -42,13 +45,13 @@ pub mod game_settings;
|
|||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod match_loading;
|
pub mod match_loading;
|
||||||
mod math;
|
mod math;
|
||||||
|
pub mod menus;
|
||||||
pub mod netcode;
|
pub mod netcode;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod replay;
|
pub mod replay;
|
||||||
pub mod schedule;
|
pub mod schedule;
|
||||||
pub mod scripting;
|
pub mod scripting;
|
||||||
pub mod stage;
|
pub mod stage;
|
||||||
pub mod menus;
|
|
||||||
pub mod texture_reference;
|
pub mod texture_reference;
|
||||||
|
|
||||||
#[derive(States, Debug, Clone, Copy, Eq, PartialEq, Hash, Default)]
|
#[derive(States, Debug, Clone, Copy, Eq, PartialEq, Hash, Default)]
|
||||||
@@ -61,6 +64,7 @@ pub enum AppState {
|
|||||||
LoadStageManifests,
|
LoadStageManifests,
|
||||||
PrepareStageManifests,
|
PrepareStageManifests,
|
||||||
CommonAssetLoadFailed,
|
CommonAssetLoadFailed,
|
||||||
|
PreMainMenu,
|
||||||
MainMenu,
|
MainMenu,
|
||||||
CharacterSelect,
|
CharacterSelect,
|
||||||
StageSelect,
|
StageSelect,
|
||||||
@@ -139,7 +143,7 @@ impl Plugin for GamePlugin {
|
|||||||
stage::manifest::prepare_stage_manifests,
|
stage::manifest::prepare_stage_manifests,
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
OnEnter(AppState::MainMenu),
|
OnEnter(AppState::PreMainMenu),
|
||||||
match_loading::initiate_default_match,
|
match_loading::initiate_default_match,
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
|||||||
@@ -169,9 +169,6 @@ pub fn initiate_default_match(
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !args.synctest {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let players = (0..args.players)
|
let players = (0..args.players)
|
||||||
.map(|handle| MatchPlayer {
|
.map(|handle| MatchPlayer {
|
||||||
handle,
|
handle,
|
||||||
@@ -270,7 +267,13 @@ pub fn prepare_match(
|
|||||||
scripts: character.attack_scripts.clone(),
|
scripts: character.attack_scripts.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
prepared.push((scene, animations, attack_scripts, manifest_handle));
|
prepared.push((
|
||||||
|
scene,
|
||||||
|
animations,
|
||||||
|
attack_scripts,
|
||||||
|
manifest_handle,
|
||||||
|
manifest.model_scale,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let session = match create_session(&args, request.players.len()) {
|
let session = match create_session(&args, request.players.len()) {
|
||||||
@@ -300,7 +303,7 @@ pub fn prepare_match(
|
|||||||
stage_manifest.camera.clone(),
|
stage_manifest.camera.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (index, (player, (scene, animations, attack_scripts, manifest_handle))) in
|
for (index, (player, (scene, animations, attack_scripts, manifest_handle, model_scale))) in
|
||||||
request.players.iter().zip(prepared).enumerate()
|
request.players.iter().zip(prepared).enumerate()
|
||||||
{
|
{
|
||||||
let spawn_x = (index as i32 * 2 + 1 - request.players.len() as i32) * 5;
|
let spawn_x = (index as i32 * 2 + 1 - request.players.len() as i32) * 5;
|
||||||
@@ -309,6 +312,7 @@ pub fn prepare_match(
|
|||||||
player.handle,
|
player.handle,
|
||||||
FGVec2::new(FGi32::from_num(spawn_x), FGi32::lit("12.5")),
|
FGVec2::new(FGi32::from_num(spawn_x), FGi32::lit("12.5")),
|
||||||
manifest_handle.clone(),
|
manifest_handle.clone(),
|
||||||
|
model_scale,
|
||||||
animations,
|
animations,
|
||||||
attack_scripts,
|
attack_scripts,
|
||||||
WorldAssetRoot(scene),
|
WorldAssetRoot(scene),
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate, ui::widget::ImageNodeSize};
|
use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate, ui::widget::ImageNodeSize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fighter::{FighterId, manifest::FighterManifest}, menus::{button::FGUiButton, style::FGUiButtonType},
|
fighter::{FighterId, manifest::FighterManifest},
|
||||||
|
menus::{button::FGUiButton, style::FGUiButtonType},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Component, Clone, FromTemplate)]
|
#[derive(Component, Clone, FromTemplate)]
|
||||||
pub struct CharacterBox {
|
pub struct CharacterBox {
|
||||||
pub fighter_manifest: Handle<FighterManifest>,
|
pub fighter_manifest: Handle<FighterManifest>,
|
||||||
pub fighter_id: FighterId
|
pub fighter_id: FighterId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterBox {
|
impl CharacterBox {
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
pub enum CharacterSelectErrors {
|
pub enum CharacterSelectErrors {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,8 +5,20 @@ use bevy::{
|
|||||||
use bevy_egui::egui::accesskit::TextAlign;
|
use bevy_egui::egui::accesskit::TextAlign;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AppState, fighter::manifest::{FighterManifest, FighterManifestRegistry}, game_settings::CommonAssets, input::{LocalInputAssignments, LocalInputSource}, menus::{
|
AppState,
|
||||||
MenuMarker, build_menu_with_props, button::FGUiButton, character_select::{character_box::CharacterBox, token::CharacterSelectToken}, cursor::{FGMenuCursor, MenuCursorInputSource}, errors::MenuErrors::{self, FighterManifestNotFound}, match_config::{MenuMatchConfig, MenuMatchPlayerSlot}, scaling, spawn_menu, style::{FGUiButtonType, FGUiStyle}, wrap_menu,
|
fighter::manifest::{FighterManifest, FighterManifestRegistry},
|
||||||
|
game_settings::CommonAssets,
|
||||||
|
input::{LocalInputAssignments, LocalInputSource},
|
||||||
|
menus::{
|
||||||
|
MenuMarker, build_menu_with_props,
|
||||||
|
button::FGUiButton,
|
||||||
|
character_select::{character_box::CharacterBox, token::CharacterSelectToken},
|
||||||
|
cursor::{FGMenuCursor, MenuCursorInputSource},
|
||||||
|
errors::MenuErrors::{self, FighterManifestNotFound},
|
||||||
|
match_config::{MenuMatchConfig, MenuMatchPlayerSlot},
|
||||||
|
scaling, spawn_menu,
|
||||||
|
style::{FGUiButtonType, FGUiStyle},
|
||||||
|
wrap_menu,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -142,7 +154,6 @@ pub fn handle_fighter_slot_addition(
|
|||||||
common_assets: Res<CommonAssets>,
|
common_assets: Res<CommonAssets>,
|
||||||
styles: Res<Assets<FGUiStyle>>,
|
styles: Res<Assets<FGUiStyle>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
for addition in addition.read() {
|
for addition in addition.read() {
|
||||||
let slot = addition.slot;
|
let slot = addition.slot;
|
||||||
create_portrait(
|
create_portrait(
|
||||||
@@ -155,7 +166,6 @@ pub fn handle_fighter_slot_addition(
|
|||||||
&addition.input_source,
|
&addition.input_source,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn css_auto_assign_slots(
|
pub fn css_auto_assign_slots(
|
||||||
@@ -220,7 +230,11 @@ pub fn update_start_banner_visibility(
|
|||||||
config: Res<MenuMatchConfig>,
|
config: Res<MenuMatchConfig>,
|
||||||
) {
|
) {
|
||||||
let match_ready = config.all_players_ready();
|
let match_ready = config.all_players_ready();
|
||||||
commands.entity(banner.into_inner()).insert(if match_ready {Visibility::Visible} else {Visibility::Hidden});
|
commands.entity(banner.into_inner()).insert(if match_ready {
|
||||||
|
Visibility::Visible
|
||||||
|
} else {
|
||||||
|
Visibility::Hidden
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_cursor_transform_to_token(
|
pub fn copy_cursor_transform_to_token(
|
||||||
@@ -269,4 +283,4 @@ pub fn despawn_tokens(tokens: Query<Entity, With<CharacterSelectToken>>, mut com
|
|||||||
for token in tokens {
|
for token in tokens {
|
||||||
commands.entity(token).despawn();
|
commands.entity(token).despawn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,13 @@ use crate::menus::style::FGUiStyle;
|
|||||||
#[derive(Component, Clone)]
|
#[derive(Component, Clone)]
|
||||||
pub struct CharacterSelectToken {
|
pub struct CharacterSelectToken {
|
||||||
pub slot: usize,
|
pub slot: usize,
|
||||||
pub cursor: Entity
|
pub cursor: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterSelectToken {
|
impl CharacterSelectToken {
|
||||||
pub fn create(cursor: Entity, slot: usize, style: &FGUiStyle) -> impl Bundle {
|
pub fn create(cursor: Entity, slot: usize, style: &FGUiStyle) -> impl Bundle {
|
||||||
(
|
(
|
||||||
CharacterSelectToken {
|
CharacterSelectToken { slot, cursor },
|
||||||
slot,
|
|
||||||
cursor
|
|
||||||
},
|
|
||||||
Pickable::IGNORE,
|
Pickable::IGNORE,
|
||||||
Node {
|
Node {
|
||||||
position_type: PositionType::Absolute,
|
position_type: PositionType::Absolute,
|
||||||
@@ -26,9 +23,13 @@ impl CharacterSelectToken {
|
|||||||
},
|
},
|
||||||
ImageNode {
|
ImageNode {
|
||||||
image: style.css_token.handle.handle.clone(),
|
image: style.css_token.handle.handle.clone(),
|
||||||
color: style.player_colors.get(slot).copied().unwrap_or(Color::WHITE),
|
color: style
|
||||||
|
.player_colors
|
||||||
|
.get(slot)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(Color::WHITE),
|
||||||
..default()
|
..default()
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-17
@@ -9,7 +9,12 @@ use bevy::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
input::{LocalInputAssignments, LocalInputSource}, menus::{input::{MenuInput, MenuInputState}, scaling, style::FGUiStyle},
|
input::{LocalInputAssignments, LocalInputSource},
|
||||||
|
menus::{
|
||||||
|
input::{MenuInput, MenuInputState},
|
||||||
|
scaling,
|
||||||
|
style::FGUiStyle,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -30,7 +35,7 @@ impl FGMenuCursor {
|
|||||||
pub fn create_cursor(
|
pub fn create_cursor(
|
||||||
input_source: MenuCursorInputSource,
|
input_source: MenuCursorInputSource,
|
||||||
style: &FGUiStyle,
|
style: &FGUiStyle,
|
||||||
pointer_id: PointerId
|
pointer_id: PointerId,
|
||||||
) -> impl Bundle {
|
) -> impl Bundle {
|
||||||
let circle_icon = style.cursor.handle().clone();
|
let circle_icon = style.cursor.handle().clone();
|
||||||
(
|
(
|
||||||
@@ -57,22 +62,22 @@ impl FGMenuCursor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub fn create_shared_cursor(style: &FGUiStyle) -> impl Bundle {
|
pub fn create_shared_cursor(style: &FGUiStyle) -> impl Bundle {
|
||||||
Self::create_cursor(
|
Self::create_cursor(MenuCursorInputSource::Any, style, PointerId::Mouse)
|
||||||
MenuCursorInputSource::Any,
|
|
||||||
style,
|
|
||||||
PointerId::Mouse
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
pub fn create_player_cursor(
|
pub fn create_player_cursor(
|
||||||
player_slot: usize,
|
player_slot: usize,
|
||||||
style: &FGUiStyle,
|
style: &FGUiStyle,
|
||||||
input_source: &LocalInputSource,
|
input_source: &LocalInputSource,
|
||||||
) -> impl Bundle {
|
) -> impl Bundle {
|
||||||
let pointer_id = if matches!(input_source, LocalInputSource::Keyboard) {PointerId::Mouse} else {PointerId::Custom(Uuid::new_v4())};
|
let pointer_id = if matches!(input_source, LocalInputSource::Keyboard) {
|
||||||
|
PointerId::Mouse
|
||||||
|
} else {
|
||||||
|
PointerId::Custom(Uuid::new_v4())
|
||||||
|
};
|
||||||
Self::create_cursor(
|
Self::create_cursor(
|
||||||
MenuCursorInputSource::Player(player_slot),
|
MenuCursorInputSource::Player(player_slot),
|
||||||
style,
|
style,
|
||||||
pointer_id
|
pointer_id,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,19 +86,17 @@ impl FGMenuCursor {
|
|||||||
pub fn copy_mouse_input(
|
pub fn copy_mouse_input(
|
||||||
mut query: Query<(&FGMenuCursor, &mut PointerLocation, &PointerId)>,
|
mut query: Query<(&FGMenuCursor, &mut PointerLocation, &PointerId)>,
|
||||||
assignments: Res<LocalInputAssignments>,
|
assignments: Res<LocalInputAssignments>,
|
||||||
mut input_events: MessageReader<Pointer<Move>>
|
mut input_events: MessageReader<Pointer<Move>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
for event in input_events.read() {
|
for event in input_events.read() {
|
||||||
if let PointerId::Mouse = event.pointer_id {
|
if let PointerId::Mouse = event.pointer_id {
|
||||||
for (cursor, mut location, _) in query.iter_mut() {
|
for (cursor, mut location, _) in query.iter_mut() {
|
||||||
let is_mouse = match cursor.input_source {
|
let is_mouse = match cursor.input_source {
|
||||||
MenuCursorInputSource::Any => true,
|
MenuCursorInputSource::Any => true,
|
||||||
MenuCursorInputSource::Player(slot) => {
|
MenuCursorInputSource::Player(slot) => assignments
|
||||||
assignments.get(slot).map(|(_, source)| {
|
.get(slot)
|
||||||
matches!(source, LocalInputSource::Keyboard)
|
.map(|(_, source)| matches!(source, LocalInputSource::Keyboard))
|
||||||
}).unwrap_or_default()
|
.unwrap_or_default(),
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_mouse {
|
if is_mouse {
|
||||||
@@ -185,7 +188,15 @@ pub fn update_cursor_transform(
|
|||||||
let camera = camera.into_inner();
|
let camera = camera.into_inner();
|
||||||
|
|
||||||
for (mut node, location) in query {
|
for (mut node, location) in query {
|
||||||
let ui_pos = scaling::logical_to_ui_position(location.location.as_ref().map(|d| d.position).unwrap_or_default(), camera, &ui_scale);
|
let ui_pos = scaling::logical_to_ui_position(
|
||||||
|
location
|
||||||
|
.location
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| d.position)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
camera,
|
||||||
|
&ui_scale,
|
||||||
|
);
|
||||||
node.left = px(ui_pos.x);
|
node.left = px(ui_pos.x);
|
||||||
node.top = px(ui_pos.y);
|
node.top = px(ui_pos.y);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,4 +8,4 @@ pub enum MenuErrors {
|
|||||||
FighterManifestNotFound,
|
FighterManifestNotFound,
|
||||||
#[error("Match config error: {0:?}")]
|
#[error("Match config error: {0:?}")]
|
||||||
MatchConfigError(#[from] MenuMatchConfigErrors),
|
MatchConfigError(#[from] MenuMatchConfigErrors),
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-6
@@ -91,10 +91,14 @@ impl MenuInput {
|
|||||||
self.accept.accumulate(&other.accept);
|
self.accept.accumulate(&other.accept);
|
||||||
self.back.accumulate(&other.back);
|
self.back.accumulate(&other.back);
|
||||||
self.start.accumulate(&other.start);
|
self.start.accumulate(&other.start);
|
||||||
self.movement_digital_up.accumulate(&other.movement_digital_up);
|
self.movement_digital_up
|
||||||
self.movement_digital_down.accumulate(&other.movement_digital_down);
|
.accumulate(&other.movement_digital_up);
|
||||||
self.movement_digital_left.accumulate(&other.movement_digital_left);
|
self.movement_digital_down
|
||||||
self.movement_digital_right.accumulate(&other.movement_digital_right);
|
.accumulate(&other.movement_digital_down);
|
||||||
|
self.movement_digital_left
|
||||||
|
.accumulate(&other.movement_digital_left);
|
||||||
|
self.movement_digital_right
|
||||||
|
.accumulate(&other.movement_digital_right);
|
||||||
self.movement = self.movement.clamp_length_max(1.0);
|
self.movement = self.movement.clamp_length_max(1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,9 +251,12 @@ pub fn sample_menu_inputs(
|
|||||||
state
|
state
|
||||||
.inputs
|
.inputs
|
||||||
.push((LocalInputSource::Keyboard, keyboard_input(&key, &map)));
|
.push((LocalInputSource::Keyboard, keyboard_input(&key, &map)));
|
||||||
|
|
||||||
let mut prev_joystick_states: Vec<(LocalInputSource, MenuJoystickState)> = vec![];
|
let mut prev_joystick_states: Vec<(LocalInputSource, MenuJoystickState)> = vec![];
|
||||||
std::mem::swap(&mut prev_joystick_states, &mut state.prev_frame_joystick_state);
|
std::mem::swap(
|
||||||
|
&mut prev_joystick_states,
|
||||||
|
&mut state.prev_frame_joystick_state,
|
||||||
|
);
|
||||||
|
|
||||||
for (entity, pad) in pads.iter() {
|
for (entity, pad) in pads.iter() {
|
||||||
let local_source = LocalInputSource::Gamepad(entity);
|
let local_source = LocalInputSource::Gamepad(entity);
|
||||||
|
|||||||
+5
-5
@@ -190,7 +190,10 @@ impl Plugin for MenuPlugin {
|
|||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
(character_select::css_auto_assign_slots, character_select::handle_fighter_slot_addition)
|
(
|
||||||
|
character_select::css_auto_assign_slots,
|
||||||
|
character_select::handle_fighter_slot_addition,
|
||||||
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.run_if(in_state(AppState::CharacterSelect))
|
.run_if(in_state(AppState::CharacterSelect))
|
||||||
.run_if(any_with_component::<CharacterSelectScreen>),
|
.run_if(any_with_component::<CharacterSelectScreen>),
|
||||||
@@ -214,14 +217,11 @@ impl Plugin for MenuPlugin {
|
|||||||
OnEnter(AppState::StageSelect),
|
OnEnter(AppState::StageSelect),
|
||||||
stage_select::setup_stage_select,
|
stage_select::setup_stage_select,
|
||||||
)
|
)
|
||||||
.add_observer(stage_select::stage_selected.run_if(in_state(AppState::StageSelect)),
|
.add_observer(stage_select::stage_selected.run_if(in_state(AppState::StageSelect)))
|
||||||
)
|
|
||||||
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
OnExit(AppState::StageSelect),
|
OnExit(AppState::StageSelect),
|
||||||
(cursor::despawn_cursors, despawn_menu),
|
(cursor::despawn_cursors, despawn_menu),
|
||||||
)
|
)
|
||||||
|
|
||||||
//---------
|
//---------
|
||||||
// STAGE SELECT END
|
// STAGE SELECT END
|
||||||
//---------
|
//---------
|
||||||
|
|||||||
+26
-6
@@ -48,7 +48,7 @@ pub fn process_inputs(
|
|||||||
action_state.pressed_actions.clear();
|
action_state.pressed_actions.clear();
|
||||||
let input = menu_inputs.aggregate();
|
let input = menu_inputs.aggregate();
|
||||||
let has_direction = input.movement.length() != 0.0;
|
let has_direction = input.movement.length() != 0.0;
|
||||||
|
|
||||||
let mut dir_distances = [
|
let mut dir_distances = [
|
||||||
(input.movement_digital_up, input.movement.dot(Vec2::Y)),
|
(input.movement_digital_up, input.movement.dot(Vec2::Y)),
|
||||||
(input.movement_digital_down, input.movement.dot(Vec2::NEG_Y)),
|
(input.movement_digital_down, input.movement.dot(Vec2::NEG_Y)),
|
||||||
@@ -82,12 +82,32 @@ pub fn process_inputs(
|
|||||||
false
|
false
|
||||||
};
|
};
|
||||||
if curr_dir.is_just_pressed() || repeat_press {
|
if curr_dir.is_just_pressed() || repeat_press {
|
||||||
if input.movement.y > 0.0 { action_state.pressed_actions.insert(DirectionalNavigationAction::Up); }
|
if input.movement.y > 0.0 {
|
||||||
if input.movement.y < 0.0 { action_state.pressed_actions.insert(DirectionalNavigationAction::Down); }
|
action_state
|
||||||
if input.movement.x < 0.0 { action_state.pressed_actions.insert(DirectionalNavigationAction::Left); }
|
.pressed_actions
|
||||||
if input.movement.x > 0.0 { action_state.pressed_actions.insert(DirectionalNavigationAction::Right); }
|
.insert(DirectionalNavigationAction::Up);
|
||||||
|
}
|
||||||
|
if input.movement.y < 0.0 {
|
||||||
|
action_state
|
||||||
|
.pressed_actions
|
||||||
|
.insert(DirectionalNavigationAction::Down);
|
||||||
|
}
|
||||||
|
if input.movement.x < 0.0 {
|
||||||
|
action_state
|
||||||
|
.pressed_actions
|
||||||
|
.insert(DirectionalNavigationAction::Left);
|
||||||
|
}
|
||||||
|
if input.movement.x > 0.0 {
|
||||||
|
action_state
|
||||||
|
.pressed_actions
|
||||||
|
.insert(DirectionalNavigationAction::Right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if input.accept.is_pressed() {
|
||||||
|
action_state
|
||||||
|
.pressed_actions
|
||||||
|
.insert(DirectionalNavigationAction::Select);
|
||||||
}
|
}
|
||||||
if input.accept.is_pressed() { action_state.pressed_actions.insert(DirectionalNavigationAction::Select); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FOCUSED_BORDER: Srgba = bevy::color::palettes::tailwind::BLUE_50;
|
const FOCUSED_BORDER: Srgba = bevy::color::palettes::tailwind::BLUE_50;
|
||||||
|
|||||||
+10
-3
@@ -30,8 +30,15 @@ pub fn ui_scaling_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn world_to_ui_position(pos: Vec2, camera: &Camera, camera_transform: &GlobalTransform, ui_scale: &UiScale) -> Vec2 {
|
pub fn world_to_ui_position(
|
||||||
let viewport_position = camera.world_to_viewport(camera_transform, Vec3::new(pos.x, pos.y, 0.0)).unwrap();
|
pos: Vec2,
|
||||||
|
camera: &Camera,
|
||||||
|
camera_transform: &GlobalTransform,
|
||||||
|
ui_scale: &UiScale,
|
||||||
|
) -> Vec2 {
|
||||||
|
let viewport_position = camera
|
||||||
|
.world_to_viewport(camera_transform, Vec3::new(pos.x, pos.y, 0.0))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let viewport_rect = camera.logical_viewport_rect().unwrap();
|
let viewport_rect = camera.logical_viewport_rect().unwrap();
|
||||||
|
|
||||||
@@ -46,4 +53,4 @@ pub fn logical_to_ui_position(pos: Vec2, camera: &Camera, ui_scale: &UiScale) ->
|
|||||||
let ui_position = (pos - viewport_rect.min) / ui_scale.0;
|
let ui_position = (pos - viewport_rect.min) / ui_scale.0;
|
||||||
|
|
||||||
ui_position
|
ui_position
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AppState, game_settings::CommonAssets, match_loading::initiate_match, menus::{
|
AppState,
|
||||||
MenuMarker, button::FGUiButton, cursor, match_config::MenuMatchConfig, spawn_menu, stage_select::stage_box::StageBox, style::{FGUiButtonType, FGUiStyle},
|
game_settings::CommonAssets,
|
||||||
}, stage::manifest::{StageManifest, StageManifestRegistry},
|
match_loading::initiate_match,
|
||||||
|
menus::{
|
||||||
|
MenuMarker,
|
||||||
|
button::FGUiButton,
|
||||||
|
cursor,
|
||||||
|
match_config::MenuMatchConfig,
|
||||||
|
spawn_menu,
|
||||||
|
stage_select::stage_box::StageBox,
|
||||||
|
style::{FGUiButtonType, FGUiStyle},
|
||||||
|
},
|
||||||
|
stage::manifest::{StageManifest, StageManifestRegistry},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod stage_box;
|
pub mod stage_box;
|
||||||
@@ -64,12 +74,16 @@ pub fn stage_selected(
|
|||||||
query: Query<&StageBox>,
|
query: Query<&StageBox>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut next_state: ResMut<NextState<AppState>>,
|
mut next_state: ResMut<NextState<AppState>>,
|
||||||
mut match_config: ResMut<MenuMatchConfig>
|
mut match_config: ResMut<MenuMatchConfig>,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
let stage_box = query.get(ev.event_target());
|
let stage_box = query.get(ev.event_target());
|
||||||
if let Ok(stage_box) = stage_box {
|
if let Ok(stage_box) = stage_box {
|
||||||
match_config.stage = Some(stage_box.stage_id);
|
match_config.stage = Some(stage_box.stage_id);
|
||||||
initiate_match(&mut commands, &mut next_state, match_config.to_pending_match()?);
|
initiate_match(
|
||||||
|
&mut commands,
|
||||||
|
&mut next_state,
|
||||||
|
match_config.to_pending_match()?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate, ui::widget::ImageNodeSize};
|
use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate, ui::widget::ImageNodeSize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fighter::{FighterId, manifest::FighterManifest}, menus::{button::FGUiButton, style::FGUiButtonType}, stage::manifest::{StageId, StageManifest},
|
fighter::{FighterId, manifest::FighterManifest},
|
||||||
|
menus::{button::FGUiButton, style::FGUiButtonType},
|
||||||
|
stage::manifest::{StageId, StageManifest},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Component, Clone, FromTemplate)]
|
#[derive(Component, Clone, FromTemplate)]
|
||||||
pub struct StageBox {
|
pub struct StageBox {
|
||||||
pub stage_manifest: Handle<StageManifest>,
|
pub stage_manifest: Handle<StageManifest>,
|
||||||
pub stage_id: StageId
|
pub stage_id: StageId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StageBox {
|
impl StageBox {
|
||||||
|
|||||||
+1
-1
@@ -1,8 +1,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use ron_asset_manager::prelude::*;
|
use ron_asset_manager::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::texture_reference::TextureReference;
|
use crate::texture_reference::TextureReference;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -346,7 +346,7 @@ fn finish_playback(
|
|||||||
commands.remove_resource::<ReplayRuntime>();
|
commands.remove_resource::<ReplayRuntime>();
|
||||||
commands.remove_resource::<LoadedReplay>();
|
commands.remove_resource::<LoadedReplay>();
|
||||||
commands.insert_resource(ReplayComplete);
|
commands.insert_resource(ReplayComplete);
|
||||||
next_state.set(AppState::MainMenu);
|
next_state.set(AppState::PreMainMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -19,9 +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,
|
||||||
Animation,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Declares the order of [`GameplaySet`] inside [`GgrsSchedule`]. Added by
|
/// Declares the order of [`GameplaySet`] inside [`GgrsSchedule`]. Added by
|
||||||
|
|||||||
+10
-4
@@ -7,10 +7,14 @@ use strum::IntoEnumIterator;
|
|||||||
use strum_macros::EnumIter;
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AppState, game_settings::GameSettings, math::vec::FGVec2, stage::{
|
AppState,
|
||||||
|
game_settings::GameSettings,
|
||||||
|
math::vec::FGVec2,
|
||||||
|
stage::{
|
||||||
StagePoly,
|
StagePoly,
|
||||||
line::{StageCollision, StagePolyLineSegmentType, StagePolyType},
|
line::{StageCollision, StagePolyLineSegmentType, StagePolyType},
|
||||||
}, texture_reference::TextureReference,
|
},
|
||||||
|
texture_reference::TextureReference,
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
@@ -58,7 +62,9 @@ pub struct StageCameraProfile {
|
|||||||
pub max_downward_pan_degrees: f32,
|
pub max_downward_pan_degrees: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Reflect, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash, Debug, EnumIter, Default)]
|
#[derive(
|
||||||
|
Reflect, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash, Debug, EnumIter, Default,
|
||||||
|
)]
|
||||||
pub enum StageId {
|
pub enum StageId {
|
||||||
#[default]
|
#[default]
|
||||||
TestStage,
|
TestStage,
|
||||||
@@ -176,7 +182,7 @@ pub fn prepare_stage_manifests(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commands.insert_resource(StageManifestRegistry(registry));
|
commands.insert_resource(StageManifestRegistry(registry));
|
||||||
next_state.set(AppState::MainMenu);
|
next_state.set(AppState::PreMainMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StageManifest {
|
impl StageManifest {
|
||||||
|
|||||||
Reference in New Issue
Block a user