Compare commits
3
Commits
10eb72b368
..
ui_fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e06cbb4b7 | ||
|
|
9a3a1383ff | ||
|
|
1ba29b817b |
+33
-2
@@ -63,7 +63,6 @@ jobs:
|
||||
libxkbcommon-dev \
|
||||
libxkbcommon-x11-0 \
|
||||
mesa-vulkan-drivers \
|
||||
blender \
|
||||
mold \
|
||||
pkg-config
|
||||
|
||||
@@ -130,22 +129,54 @@ jobs:
|
||||
libusb-1.0-0-dev \
|
||||
libwayland-dev \
|
||||
libx11-dev \
|
||||
libxfixes3 \
|
||||
libxi6 \
|
||||
libxkbcommon-dev \
|
||||
libxkbcommon-x11-0 \
|
||||
blender \
|
||||
lld-19 \
|
||||
llvm-19 \
|
||||
mesa-vulkan-drivers \
|
||||
mold \
|
||||
blender \
|
||||
pkg-config
|
||||
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100
|
||||
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100
|
||||
echo "/usr/lib/llvm-19/bin" >> "$GITHUB_PATH"
|
||||
rm -f "$HOME/.cache/cargo-xwin/clang-cl"
|
||||
|
||||
- name: Install pinned Blender
|
||||
run: |
|
||||
scripts/install-blender.sh "$RUNNER_TEMP/blender"
|
||||
echo "BLENDER=$RUNNER_TEMP/blender/blender" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Preprocess assets
|
||||
run: cargo run --locked --bin process-assets --no-default-features --features debug_features -j 4
|
||||
|
||||
- name: Verify processed battlefield asset
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import struct
|
||||
|
||||
path = "imported_assets/Default/stages/battlefield/bf2.blend"
|
||||
with open(path, "rb") as asset:
|
||||
header = asset.read(12)
|
||||
if len(header) != 12:
|
||||
raise SystemExit(f"processed asset is truncated: {path}")
|
||||
magic, version, length = struct.unpack("<4sII", header)
|
||||
if magic != b"glTF" or version != 2 or length != asset.seek(0, 2):
|
||||
raise SystemExit(f"processed asset is not a valid GLB: {path}")
|
||||
asset.seek(12)
|
||||
json_length, chunk_type = struct.unpack("<II", asset.read(8))
|
||||
if chunk_type != 0x4E4F534A:
|
||||
raise SystemExit(f"processed asset has no JSON chunk: {path}")
|
||||
document = json.loads(asset.read(json_length))
|
||||
meshes = document.get("meshes", [])
|
||||
if not meshes:
|
||||
raise SystemExit(f"processed asset contains no meshes: {path}")
|
||||
print(f"{path}: {len(meshes)} meshes, {length} bytes")
|
||||
PY
|
||||
|
||||
- name: Build production binary
|
||||
run: cargo build --locked --profile production --no-default-features --features debug_features -j 4
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
remote_url = "lore://lore.eirexe.moe"
|
||||
identity = "2"
|
||||
|
||||
[store]
|
||||
max_capacity = 2000000
|
||||
eviction_delay = 30
|
||||
max_size = 10737418240
|
||||
compaction_delay = 50
|
||||
|
||||
[file]
|
||||
direct_write = false
|
||||
flush_write = false
|
||||
|
||||
[vfs]
|
||||
vfs_type = "None"
|
||||
@@ -1 +0,0 @@
|
||||
// no catalog entries
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
version="5.2.2"
|
||||
sha256="84098912789dc450e95697c4184fb8a90acbe5111c2ba4aede3fecb57806a168"
|
||||
install_dir="${1:-${BLENDER_INSTALL_DIR:-${HOME}/.local/blender-${version}}}"
|
||||
|
||||
if [[ "$(uname -s)" != Linux || "$(uname -m)" != x86_64 ]]; then
|
||||
echo "error: this installer currently supports Linux x86_64 only" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -x "$install_dir/blender" ]]; then
|
||||
"$install_dir/blender" --version | head -n 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$install_dir")"
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' EXIT
|
||||
|
||||
archive="blender-${version}-linux-x64.tar.xz"
|
||||
url="https://download.blender.org/release/Blender5.2/${archive}"
|
||||
|
||||
curl --fail --location --silent --show-error --output "$tmp_dir/$archive" "$url"
|
||||
printf '%s %s\n' "$sha256" "$tmp_dir/$archive" | sha256sum --check --status
|
||||
tar --extract --xz --file "$tmp_dir/$archive" --directory "$tmp_dir"
|
||||
mv "$tmp_dir/blender-${version}-linux-x64" "$install_dir"
|
||||
|
||||
"$install_dir/blender" --version | head -n 1
|
||||
+22
-4
@@ -84,10 +84,11 @@ impl AssetLoader for BlendSourceLoader {
|
||||
.arg(&blend_path)
|
||||
.arg("--python")
|
||||
.arg(&script)
|
||||
.arg("--")
|
||||
.arg(&output)
|
||||
.arg(&actions_path)
|
||||
.output()
|
||||
.arg("--")
|
||||
.arg(&output)
|
||||
.arg(&actions_path)
|
||||
.arg(&blend_path)
|
||||
.output()
|
||||
.map_err(|error| io::Error::other(format!("failed to start Blender: {error}")))?;
|
||||
if !result.status.success() {
|
||||
return Err(io::Error::other(format!(
|
||||
@@ -106,6 +107,7 @@ impl AssetLoader for BlendSourceLoader {
|
||||
let mut dependencies = manifest.dependencies;
|
||||
let document: serde_json::Value = serde_json::from_slice(&fs::read(&output)?)
|
||||
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
|
||||
validate_export(&document, &output)?;
|
||||
if let Some(images) = document.get("images").and_then(serde_json::Value::as_array) {
|
||||
for image in images {
|
||||
if let Some(uri) = image.get("uri").and_then(serde_json::Value::as_str) {
|
||||
@@ -142,6 +144,22 @@ impl AssetLoader for BlendSourceLoader {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_export(document: &serde_json::Value, output: &Path) -> io::Result<()> {
|
||||
for key in ["scenes", "nodes", "meshes"] {
|
||||
let count = document
|
||||
.get(key)
|
||||
.and_then(serde_json::Value::as_array)
|
||||
.map_or(0, Vec::len);
|
||||
if count == 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("Blender export {} contains no {key}", output.display()),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn referenced_actions(
|
||||
load_context: &mut LoadContext<'_>,
|
||||
root: &Path,
|
||||
|
||||
@@ -7,6 +7,15 @@ import sys
|
||||
def main():
|
||||
output = sys.argv[sys.argv.index("--") + 1]
|
||||
actions_path = sys.argv[sys.argv.index("--") + 2]
|
||||
source_path = sys.argv[sys.argv.index("--") + 3]
|
||||
loaded_path = os.path.realpath(bpy.data.filepath)
|
||||
expected_path = os.path.realpath(source_path)
|
||||
if loaded_path != expected_path:
|
||||
raise RuntimeError(
|
||||
f"Blender loaded {loaded_path!r} instead of {expected_path!r}"
|
||||
)
|
||||
if not bpy.data.objects or not bpy.data.meshes:
|
||||
raise RuntimeError("Blender loaded an empty scene")
|
||||
with open(actions_path) as file:
|
||||
actions_to_keep = set(json.load(file))
|
||||
|
||||
|
||||
+23
-4
@@ -3,11 +3,9 @@
|
||||
use std::{collections::HashMap, time::Duration};
|
||||
|
||||
use bevy::{
|
||||
input::InputSystems,
|
||||
prelude::*,
|
||||
settings::{ReflectSettingsGroup, SaveSettingsDeferred, SettingsGroup},
|
||||
camera::{CameraOutputMode, visibility::RenderLayers}, input::InputSystems, prelude::*, render::render_resource::BlendState, settings::{ReflectSettingsGroup, SaveSettingsDeferred, SettingsGroup},
|
||||
};
|
||||
use bevy_egui::{EguiContexts, EguiPrimaryContextPass, egui};
|
||||
use bevy_egui::{EguiContexts, EguiGlobalSettings, EguiPrimaryContextPass, PrimaryEguiContext, egui};
|
||||
use bevy_ggrs::{RollbackFrameRate, RunGgrsSystems};
|
||||
use enum_cycling::EnumCycle;
|
||||
use enum_cycling_derive::EnumCycle;
|
||||
@@ -397,6 +395,7 @@ impl Plugin for DebugToolsPlugin {
|
||||
.before(RunGgrsSystems)
|
||||
.run_if(in_state(AppState::InMatch)),
|
||||
)
|
||||
.add_systems(Startup, spawn_egui_camera)
|
||||
.add_systems(PreUpdate, restore_frame_step_time.after(RunGgrsSystems))
|
||||
.add_systems(
|
||||
Update,
|
||||
@@ -408,6 +407,26 @@ impl Plugin for DebugToolsPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_egui_camera(mut commands: Commands, mut egui_global_settings: ResMut<EguiGlobalSettings>,) {
|
||||
egui_global_settings.auto_create_primary_context = false;
|
||||
commands.spawn((
|
||||
// The `PrimaryEguiContext` component requires everything needed to render a primary context.
|
||||
PrimaryEguiContext,
|
||||
Camera2d,
|
||||
// Setting RenderLayers to none makes sure we won't render anything apart from the UI.
|
||||
RenderLayers::none(),
|
||||
Camera {
|
||||
order: 2,
|
||||
output_mode: CameraOutputMode::Write {
|
||||
blend_state: Some(BlendState::ALPHA_BLENDING),
|
||||
clear_color: ClearColorConfig::None,
|
||||
},
|
||||
clear_color: ClearColorConfig::Custom(Color::NONE),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn player_handles(players: &Query<&Player>) -> Vec<usize> {
|
||||
let mut handles = players
|
||||
.iter()
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
use bevy::{picking::pointer::PointerId, prelude::*};
|
||||
|
||||
use crate::{
|
||||
AppState,
|
||||
fighter::manifest::{FighterManifest, FighterManifestRegistry},
|
||||
game_settings::CommonAssets,
|
||||
input::{LocalInputAssignments, LocalInputSource},
|
||||
menus::{
|
||||
MenuMarker,
|
||||
button::FGUiButton,
|
||||
character_select::{character_box::CharacterBox, token::CharacterSelectToken},
|
||||
cursor::{FGMenuCursor, MenuCursorInputSource},
|
||||
errors::MenuErrors::FighterManifestNotFound,
|
||||
match_config::{MenuMatchConfig, MenuMatchPlayerSlot},
|
||||
scaling, spawn_menu,
|
||||
style::{FGUiButtonType, FGUiStyle},
|
||||
AppState, fighter::manifest::{FighterManifest, FighterManifestRegistry}, game_settings::CommonAssets, input::{LocalInputAssignments, LocalInputSource}, menus::{
|
||||
MenuCameraMarker, MenuMarker, button::FGUiButton, character_select::{character_box::CharacterBox, token::CharacterSelectToken}, cursor::{FGMenuCursor, MenuCursorInputSource}, errors::MenuErrors::FighterManifestNotFound, match_config::{MenuMatchConfig, MenuMatchPlayerSlot}, scaling, spawn_menu, style::{FGUiButtonType, FGUiStyle},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -241,7 +230,7 @@ pub fn copy_cursor_transform_to_token(
|
||||
character_boxes: Query<(&CharacterBox, &ComputedNode, &UiGlobalTransform)>,
|
||||
match_config: Res<MenuMatchConfig>,
|
||||
cursors: Query<&UiGlobalTransform, With<FGMenuCursor>>,
|
||||
cam: Single<&Camera>,
|
||||
cam: Single<&Camera, With<MenuCameraMarker>>,
|
||||
ui_scale: Res<UiScale>,
|
||||
) -> Result {
|
||||
let camera = cam.into_inner();
|
||||
|
||||
+3
-6
@@ -9,11 +9,8 @@ use bevy::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
input::{LocalInputAssignments, LocalInputSource},
|
||||
menus::{
|
||||
input::{MenuInput, MenuInputState},
|
||||
scaling,
|
||||
style::FGUiStyle,
|
||||
input::{LocalInputAssignments, LocalInputSource}, menus::{
|
||||
MenuCameraMarker, input::{MenuInput, MenuInputState}, scaling, style::FGUiStyle,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -181,7 +178,7 @@ pub fn cursor_input(
|
||||
}
|
||||
|
||||
pub fn update_cursor_transform(
|
||||
camera: Single<&Camera>,
|
||||
camera: Single<&Camera, With<MenuCameraMarker>>,
|
||||
query: Query<(&mut Node, &PointerLocation), With<FGMenuCursor>>,
|
||||
ui_scale: Res<UiScale>,
|
||||
) {
|
||||
|
||||
+1
-4
@@ -53,6 +53,7 @@ pub fn wrap_menu(menu: impl Scene) -> impl Scene {
|
||||
#MenuCamera
|
||||
Camera
|
||||
Camera2d
|
||||
MenuCameraMarker
|
||||
),
|
||||
(
|
||||
#MenuContainer
|
||||
@@ -73,7 +74,6 @@ pub fn wrap_menu(menu: impl Scene) -> impl Scene {
|
||||
|
||||
pub fn despawn_menu(
|
||||
existing_menu: Option<Single<Entity, With<MenuMarker>>>,
|
||||
existing_menu_camera: Option<Single<Entity, With<MenuCameraMarker>>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Some(entity) = existing_menu {
|
||||
@@ -82,9 +82,6 @@ pub fn despawn_menu(
|
||||
.despawn();
|
||||
}
|
||||
|
||||
if let Some(menu_cam) = existing_menu_camera {
|
||||
commands.entity(*menu_cam).despawn();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_menu(
|
||||
|
||||
Reference in New Issue
Block a user