Some other bullshit
This commit is contained in:
@@ -49,7 +49,6 @@ pub fn apply_animation(
|
||||
>,
|
||||
) {
|
||||
for (mut trf, facing_direction, frame) in children {
|
||||
// Melee model scale is in decimeters
|
||||
trf.rotation = Quat::IDENTITY;
|
||||
if let AnimKind::Turn = frame.kind {
|
||||
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) {
|
||||
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() {
|
||||
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][1].to_num(),
|
||||
matrix.cols[3][2].to_num(),
|
||||
));
|
||||
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 {
|
||||
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]
|
||||
fn capsule_wireframe_caps_extend_in_opposite_directions() {
|
||||
let wireframe = capsule_wireframe();
|
||||
|
||||
+18
-6
@@ -1,9 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use bevy::{
|
||||
asset::UntypedHandle,
|
||||
prelude::*,
|
||||
};
|
||||
use bevy::{asset::UntypedHandle, prelude::*};
|
||||
use bevy_asset_loader::asset_collection::AssetCollection;
|
||||
use ron_asset_manager::prelude::RonAsset;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -11,10 +8,16 @@ use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
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 {
|
||||
#[default]
|
||||
TestFighter,
|
||||
@@ -35,6 +38,8 @@ pub struct FighterHurtbox {
|
||||
pub struct FighterManifest {
|
||||
pub id: FighterId,
|
||||
pub model_path: String,
|
||||
#[reflect(ignore)]
|
||||
pub model_scale: FGi32,
|
||||
pub baked_animation_path: String,
|
||||
#[asset]
|
||||
#[dependency]
|
||||
@@ -108,6 +113,13 @@ pub fn prepare_fighter_manifests(
|
||||
);
|
||||
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() {
|
||||
fail(
|
||||
&mut next_state,
|
||||
|
||||
+8
-4
@@ -22,12 +22,15 @@
|
||||
//! appears in `Add Component`. No registration code is needed.
|
||||
|
||||
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 ron_asset_manager::RonAssetPlugin;
|
||||
use bevy_wind_waker_shader::prelude::*;
|
||||
use clap::Parser;
|
||||
use ron_asset_manager::RonAssetPlugin;
|
||||
|
||||
use crate::{
|
||||
camera::MatchCameraPlugin, fighter::manifest::FighterManifest, game_settings::GameSettings,
|
||||
@@ -42,13 +45,13 @@ pub mod game_settings;
|
||||
pub mod input;
|
||||
pub mod match_loading;
|
||||
mod math;
|
||||
pub mod menus;
|
||||
pub mod netcode;
|
||||
pub mod player;
|
||||
pub mod replay;
|
||||
pub mod schedule;
|
||||
pub mod scripting;
|
||||
pub mod stage;
|
||||
pub mod menus;
|
||||
pub mod texture_reference;
|
||||
|
||||
#[derive(States, Debug, Clone, Copy, Eq, PartialEq, Hash, Default)]
|
||||
@@ -61,6 +64,7 @@ pub enum AppState {
|
||||
LoadStageManifests,
|
||||
PrepareStageManifests,
|
||||
CommonAssetLoadFailed,
|
||||
PreMainMenu,
|
||||
MainMenu,
|
||||
CharacterSelect,
|
||||
StageSelect,
|
||||
@@ -139,7 +143,7 @@ impl Plugin for GamePlugin {
|
||||
stage::manifest::prepare_stage_manifests,
|
||||
)
|
||||
.add_systems(
|
||||
OnEnter(AppState::MainMenu),
|
||||
OnEnter(AppState::PreMainMenu),
|
||||
match_loading::initiate_default_match,
|
||||
)
|
||||
.add_systems(
|
||||
|
||||
@@ -169,9 +169,6 @@ pub fn initiate_default_match(
|
||||
}
|
||||
return;
|
||||
}
|
||||
if !args.synctest {
|
||||
return;
|
||||
}
|
||||
let players = (0..args.players)
|
||||
.map(|handle| MatchPlayer {
|
||||
handle,
|
||||
@@ -270,7 +267,13 @@ pub fn prepare_match(
|
||||
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()) {
|
||||
@@ -300,7 +303,7 @@ pub fn prepare_match(
|
||||
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()
|
||||
{
|
||||
let spawn_x = (index as i32 * 2 + 1 - request.players.len() as i32) * 5;
|
||||
@@ -309,6 +312,7 @@ pub fn prepare_match(
|
||||
player.handle,
|
||||
FGVec2::new(FGi32::from_num(spawn_x), FGi32::lit("12.5")),
|
||||
manifest_handle.clone(),
|
||||
model_scale,
|
||||
animations,
|
||||
attack_scripts,
|
||||
WorldAssetRoot(scene),
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate, ui::widget::ImageNodeSize};
|
||||
|
||||
use crate::{
|
||||
fighter::{FighterId, manifest::FighterManifest}, menus::{button::FGUiButton, style::FGUiButtonType},
|
||||
fighter::{FighterId, manifest::FighterManifest},
|
||||
menus::{button::FGUiButton, style::FGUiButtonType},
|
||||
};
|
||||
|
||||
#[derive(Component, Clone, FromTemplate)]
|
||||
pub struct CharacterBox {
|
||||
pub fighter_manifest: Handle<FighterManifest>,
|
||||
pub fighter_id: FighterId
|
||||
pub fighter_id: FighterId,
|
||||
}
|
||||
|
||||
impl CharacterBox {
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
pub enum CharacterSelectErrors {
|
||||
|
||||
}
|
||||
pub enum CharacterSelectErrors {}
|
||||
|
||||
@@ -5,8 +5,20 @@ use bevy::{
|
||||
use bevy_egui::egui::accesskit::TextAlign;
|
||||
|
||||
use crate::{
|
||||
AppState, 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,
|
||||
AppState,
|
||||
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>,
|
||||
styles: Res<Assets<FGUiStyle>>,
|
||||
) {
|
||||
|
||||
for addition in addition.read() {
|
||||
let slot = addition.slot;
|
||||
create_portrait(
|
||||
@@ -155,7 +166,6 @@ pub fn handle_fighter_slot_addition(
|
||||
&addition.input_source,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn css_auto_assign_slots(
|
||||
@@ -220,7 +230,11 @@ pub fn update_start_banner_visibility(
|
||||
config: Res<MenuMatchConfig>,
|
||||
) {
|
||||
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(
|
||||
@@ -269,4 +283,4 @@ pub fn despawn_tokens(tokens: Query<Entity, With<CharacterSelectToken>>, mut com
|
||||
for token in tokens {
|
||||
commands.entity(token).despawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,13 @@ use crate::menus::style::FGUiStyle;
|
||||
#[derive(Component, Clone)]
|
||||
pub struct CharacterSelectToken {
|
||||
pub slot: usize,
|
||||
pub cursor: Entity
|
||||
pub cursor: Entity,
|
||||
}
|
||||
|
||||
impl CharacterSelectToken {
|
||||
pub fn create(cursor: Entity, slot: usize, style: &FGUiStyle) -> impl Bundle {
|
||||
(
|
||||
CharacterSelectToken {
|
||||
slot,
|
||||
cursor
|
||||
},
|
||||
CharacterSelectToken { slot, cursor },
|
||||
Pickable::IGNORE,
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
@@ -26,9 +23,13 @@ impl CharacterSelectToken {
|
||||
},
|
||||
ImageNode {
|
||||
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()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-17
@@ -9,7 +9,12 @@ use bevy::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
input::{LocalInputAssignments, LocalInputSource}, menus::{input::{MenuInput, MenuInputState}, scaling, style::FGUiStyle},
|
||||
input::{LocalInputAssignments, LocalInputSource},
|
||||
menus::{
|
||||
input::{MenuInput, MenuInputState},
|
||||
scaling,
|
||||
style::FGUiStyle,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -30,7 +35,7 @@ impl FGMenuCursor {
|
||||
pub fn create_cursor(
|
||||
input_source: MenuCursorInputSource,
|
||||
style: &FGUiStyle,
|
||||
pointer_id: PointerId
|
||||
pointer_id: PointerId,
|
||||
) -> impl Bundle {
|
||||
let circle_icon = style.cursor.handle().clone();
|
||||
(
|
||||
@@ -57,22 +62,22 @@ impl FGMenuCursor {
|
||||
)
|
||||
}
|
||||
pub fn create_shared_cursor(style: &FGUiStyle) -> impl Bundle {
|
||||
Self::create_cursor(
|
||||
MenuCursorInputSource::Any,
|
||||
style,
|
||||
PointerId::Mouse
|
||||
)
|
||||
Self::create_cursor(MenuCursorInputSource::Any, style, PointerId::Mouse)
|
||||
}
|
||||
pub fn create_player_cursor(
|
||||
player_slot: usize,
|
||||
style: &FGUiStyle,
|
||||
input_source: &LocalInputSource,
|
||||
) -> 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(
|
||||
MenuCursorInputSource::Player(player_slot),
|
||||
style,
|
||||
pointer_id
|
||||
pointer_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -81,19 +86,17 @@ impl FGMenuCursor {
|
||||
pub fn copy_mouse_input(
|
||||
mut query: Query<(&FGMenuCursor, &mut PointerLocation, &PointerId)>,
|
||||
assignments: Res<LocalInputAssignments>,
|
||||
mut input_events: MessageReader<Pointer<Move>>
|
||||
mut input_events: MessageReader<Pointer<Move>>,
|
||||
) {
|
||||
|
||||
for event in input_events.read() {
|
||||
if let PointerId::Mouse = event.pointer_id {
|
||||
for (cursor, mut location, _) in query.iter_mut() {
|
||||
let is_mouse = match cursor.input_source {
|
||||
MenuCursorInputSource::Any => true,
|
||||
MenuCursorInputSource::Player(slot) => {
|
||||
assignments.get(slot).map(|(_, source)| {
|
||||
matches!(source, LocalInputSource::Keyboard)
|
||||
}).unwrap_or_default()
|
||||
},
|
||||
MenuCursorInputSource::Player(slot) => assignments
|
||||
.get(slot)
|
||||
.map(|(_, source)| matches!(source, LocalInputSource::Keyboard))
|
||||
.unwrap_or_default(),
|
||||
};
|
||||
|
||||
if is_mouse {
|
||||
@@ -185,7 +188,15 @@ pub fn update_cursor_transform(
|
||||
let camera = camera.into_inner();
|
||||
|
||||
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.top = px(ui_pos.y);
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,4 +8,4 @@ pub enum MenuErrors {
|
||||
FighterManifestNotFound,
|
||||
#[error("Match config error: {0:?}")]
|
||||
MatchConfigError(#[from] MenuMatchConfigErrors),
|
||||
}
|
||||
}
|
||||
|
||||
+13
-6
@@ -91,10 +91,14 @@ impl MenuInput {
|
||||
self.accept.accumulate(&other.accept);
|
||||
self.back.accumulate(&other.back);
|
||||
self.start.accumulate(&other.start);
|
||||
self.movement_digital_up.accumulate(&other.movement_digital_up);
|
||||
self.movement_digital_down.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_digital_up
|
||||
.accumulate(&other.movement_digital_up);
|
||||
self.movement_digital_down
|
||||
.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);
|
||||
}
|
||||
}
|
||||
@@ -247,9 +251,12 @@ pub fn sample_menu_inputs(
|
||||
state
|
||||
.inputs
|
||||
.push((LocalInputSource::Keyboard, keyboard_input(&key, &map)));
|
||||
|
||||
|
||||
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() {
|
||||
let local_source = LocalInputSource::Gamepad(entity);
|
||||
|
||||
+5
-5
@@ -190,7 +190,10 @@ impl Plugin for MenuPlugin {
|
||||
)
|
||||
.add_systems(
|
||||
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()
|
||||
.run_if(in_state(AppState::CharacterSelect))
|
||||
.run_if(any_with_component::<CharacterSelectScreen>),
|
||||
@@ -214,14 +217,11 @@ impl Plugin for MenuPlugin {
|
||||
OnEnter(AppState::StageSelect),
|
||||
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(
|
||||
OnExit(AppState::StageSelect),
|
||||
(cursor::despawn_cursors, despawn_menu),
|
||||
)
|
||||
|
||||
//---------
|
||||
// STAGE SELECT END
|
||||
//---------
|
||||
|
||||
+26
-6
@@ -48,7 +48,7 @@ pub fn process_inputs(
|
||||
action_state.pressed_actions.clear();
|
||||
let input = menu_inputs.aggregate();
|
||||
let has_direction = input.movement.length() != 0.0;
|
||||
|
||||
|
||||
let mut dir_distances = [
|
||||
(input.movement_digital_up, input.movement.dot(Vec2::Y)),
|
||||
(input.movement_digital_down, input.movement.dot(Vec2::NEG_Y)),
|
||||
@@ -82,12 +82,32 @@ pub fn process_inputs(
|
||||
false
|
||||
};
|
||||
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 { 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.movement.y > 0.0 {
|
||||
action_state
|
||||
.pressed_actions
|
||||
.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;
|
||||
|
||||
+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 {
|
||||
let viewport_position = camera.world_to_viewport(camera_transform, Vec3::new(pos.x, pos.y, 0.0)).unwrap();
|
||||
pub fn world_to_ui_position(
|
||||
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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
ui_position
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{
|
||||
AppState, game_settings::CommonAssets, 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},
|
||||
AppState,
|
||||
game_settings::CommonAssets,
|
||||
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;
|
||||
@@ -64,12 +74,16 @@ pub fn stage_selected(
|
||||
query: Query<&StageBox>,
|
||||
mut commands: Commands,
|
||||
mut next_state: ResMut<NextState<AppState>>,
|
||||
mut match_config: ResMut<MenuMatchConfig>
|
||||
mut match_config: ResMut<MenuMatchConfig>,
|
||||
) -> Result {
|
||||
let stage_box = query.get(ev.event_target());
|
||||
if let Ok(stage_box) = stage_box {
|
||||
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(())
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate, ui::widget::ImageNodeSize};
|
||||
|
||||
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)]
|
||||
pub struct StageBox {
|
||||
pub stage_manifest: Handle<StageManifest>,
|
||||
pub stage_id: StageId
|
||||
pub stage_id: StageId,
|
||||
}
|
||||
|
||||
impl StageBox {
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ron_asset_manager::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::texture_reference::TextureReference;
|
||||
|
||||
|
||||
+1
-1
@@ -346,7 +346,7 @@ fn finish_playback(
|
||||
commands.remove_resource::<ReplayRuntime>();
|
||||
commands.remove_resource::<LoadedReplay>();
|
||||
commands.insert_resource(ReplayComplete);
|
||||
next_state.set(AppState::MainMenu);
|
||||
next_state.set(AppState::PreMainMenu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -19,9 +19,10 @@ pub enum GameplaySet {
|
||||
StateUpdate,
|
||||
/// Integrate velocities into positions.
|
||||
Physics,
|
||||
/// Solve collision boxes
|
||||
Animation,
|
||||
/// Resolve the integrated positions against the stage.
|
||||
Collision,
|
||||
Animation,
|
||||
}
|
||||
|
||||
/// Declares the order of [`GameplaySet`] inside [`GgrsSchedule`]. Added by
|
||||
|
||||
+10
-4
@@ -7,10 +7,14 @@ use strum::IntoEnumIterator;
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
use crate::{
|
||||
AppState, game_settings::GameSettings, math::vec::FGVec2, stage::{
|
||||
AppState,
|
||||
game_settings::GameSettings,
|
||||
math::vec::FGVec2,
|
||||
stage::{
|
||||
StagePoly,
|
||||
line::{StageCollision, StagePolyLineSegmentType, StagePolyType},
|
||||
}, texture_reference::TextureReference,
|
||||
},
|
||||
texture_reference::TextureReference,
|
||||
};
|
||||
use bevy::prelude::*;
|
||||
|
||||
@@ -58,7 +62,9 @@ pub struct StageCameraProfile {
|
||||
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 {
|
||||
#[default]
|
||||
TestStage,
|
||||
@@ -176,7 +182,7 @@ pub fn prepare_stage_manifests(
|
||||
}
|
||||
|
||||
commands.insert_resource(StageManifestRegistry(registry));
|
||||
next_state.set(AppState::MainMenu);
|
||||
next_state.set(AppState::PreMainMenu);
|
||||
}
|
||||
|
||||
impl StageManifest {
|
||||
|
||||
Reference in New Issue
Block a user