Merge branch 'master' into tilemapdata

This commit is contained in:
b-guild
2025-02-27 15:34:10 -08:00
committed by GitHub
42 changed files with 552 additions and 345 deletions
+5
View File
@@ -15,6 +15,11 @@
history.bin
settings.ron
# Nix/NixOS
.direnv/
.envrc
!flake.lock
# from https://github.com/github/gitignore/blob/master/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
+16
View File
@@ -1,3 +1,19 @@
# 0.36.1
Minor release with fixes for some annoying bugs.
## Fixed
- Fixed frustum culling issues for meshes.
- Correctly mark inheritable properties as modified when animating them.
- Show selected item in the asset browser when clearing selection text.
- Fixed incorrect width of the node removal dialog.
- Fixed physics desynchronization issue.
- Fixed docking manager layout saving and loading.
- Improved project name validation (in both `fyrox-template` and the project manager).
- Fixed example shader in the documentation.
- Added names for floating panels in the editor—fixes incorrect layout after loading.
# 0.36
This version unifies versions of sub-crates - now all sub-crates have the same version. This makes it easier to migrate
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyroxed"
version = "0.36.0"
version = "0.36.2"
license = "MIT"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
@@ -13,6 +13,6 @@ readme = "README.md"
include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md"]
[dependencies]
fyrox = { version = "0.36.0", path = "../fyrox" }
fyroxed_base = { version = "0.36.0", path = "../editor" }
fyrox = { version = "0.36.2", path = "../fyrox" }
fyroxed_base = { version = "0.36.2", path = "../editor" }
clap = { version = "4", features = ["derive"] }
+3 -3
View File
@@ -1,7 +1,7 @@
[package]
name = "fyroxed_base"
license = "MIT"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
rust-version = "1.80"
@@ -13,8 +13,8 @@ readme = "README.md"
include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md", "/resources/**/*"]
[dependencies]
fyrox = { version = "0.36.0", path = "../fyrox", default-features = false }
fyrox-build-tools = { version = "0.36.0", path = "../fyrox-build-tools" }
fyrox = { version = "0.36.2", path = "../fyrox", default-features = false }
fyrox-build-tools = { version = "0.36.2", path = "../fyrox-build-tools" }
lazy_static = "1.4.0"
ron = "0.8.0"
serde = "^1.0.0"
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+22 -17
View File
@@ -53,9 +53,12 @@ use crate::{
scroll_viewer::{ScrollViewerBuilder, ScrollViewerMessage},
searchbar::{SearchBarBuilder, SearchBarMessage},
stack_panel::StackPanelBuilder,
style::{resource::StyleResourceExt, Style},
text::TextMessage,
text_box::TextBoxBuilder,
utils::make_simple_tooltip,
utils::{
make_dropdown_list_option, make_image_button_with_tooltip, make_simple_tooltip,
},
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
wrap_panel::WrapPanelBuilder,
@@ -72,18 +75,15 @@ use crate::{
utils::window_content,
Message, Mode,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::{make_dropdown_list_option, make_image_button_with_tooltip};
use notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::fs::File;
use std::io::Write;
use std::sync::atomic::{AtomicBool, Ordering};
use std::{
ffi::OsStr,
fs::File,
io::Write,
path::{Path, PathBuf},
process::Command,
sync::{
atomic::{AtomicBool, Ordering},
mpsc::{self, Sender},
Arc,
},
@@ -547,7 +547,8 @@ pub struct AssetBrowser {
item_to_select: Option<PathBuf>,
inspector: AssetInspector,
context_menu: ContextMenu,
selected_path: PathBuf,
current_path: PathBuf,
selected_item_path: PathBuf,
watcher: Option<RecommendedWatcher>,
dependency_viewer: DependencyViewer,
resource_creator: Option<ResourceCreator>,
@@ -757,7 +758,7 @@ impl AssetBrowser {
item_to_select: None,
inspector,
context_menu,
selected_path: Default::default(),
current_path: Default::default(),
add_resource,
resource_creator: None,
preview_cache: AssetPreviewCache::new(preview_receiver, 4),
@@ -766,6 +767,7 @@ impl AssetBrowser {
preview_generators: AssetPreviewGeneratorsCollection::new(),
refresh,
watcher,
selected_item_path: Default::default(),
}
}
@@ -887,8 +889,8 @@ impl AssetBrowser {
) {
if let Some(watcher) = self.watcher.as_mut() {
// notify 6.1.1 crashes otherwise
if self.selected_path.exists() {
Log::verify(watcher.unwatch(&self.selected_path));
if self.current_path.exists() {
Log::verify(watcher.unwatch(&self.current_path));
}
if path.exists() {
Log::verify(watcher.watch(path, RecursiveMode::NonRecursive));
@@ -897,7 +899,7 @@ impl AssetBrowser {
}
}
self.selected_path = path.to_path_buf();
self.current_path = path.to_path_buf();
self.refresh(ui, resource_manager, message_sender);
}
@@ -914,7 +916,7 @@ impl AssetBrowser {
self.clear_assets(ui);
// Add "return" item.
if let Some(mut parent_path) = make_relative_path(&self.selected_path)
if let Some(mut parent_path) = make_relative_path(&self.current_path)
.ok()
.and_then(|path| path.parent().map(|path| path.to_owned()))
{
@@ -946,7 +948,7 @@ impl AssetBrowser {
let mut resources = Vec::new();
// Get all supported assets from folder and generate previews for them.
if let Ok(dir_iter) = std::fs::read_dir(&self.selected_path) {
if let Ok(dir_iter) = std::fs::read_dir(&self.current_path) {
for entry in dir_iter.flatten() {
if let Ok(entry_path) = make_relative_path(entry.path()) {
if entry_path.is_dir() {
@@ -962,7 +964,7 @@ impl AssetBrowser {
}
// Collect built-in resource (only if the root folder is selected).
if let Ok(path) = self.selected_path.canonicalize() {
if let Ok(path) = self.current_path.canonicalize() {
if let Ok(working_dir) = std::env::current_dir().and_then(|dir| dir.canonicalize()) {
if path == working_dir {
let built_in_resources = resource_manager
@@ -1028,7 +1030,7 @@ impl AssetBrowser {
message,
engine,
sender.clone(),
&self.selected_path,
&self.current_path,
);
if asset_added {
self.refresh(
@@ -1058,6 +1060,8 @@ impl AssetBrowser {
.path
.clone();
self.selected_item_path = asset_path.clone();
self.inspector.inspect_resource_import_options(
&asset_path,
ui,
@@ -1114,7 +1118,8 @@ impl AssetBrowser {
&& message.direction() == MessageDirection::FromWidget
{
if search_text.is_empty() {
let path = self.selected_path.clone();
let path = self.selected_item_path.parent().unwrap().to_path_buf();
self.item_to_select = Some(self.selected_item_path.clone());
self.set_path(&path, ui, &engine.resource_manager, &sender);
} else {
self.clear_assets(ui);
+54 -15
View File
@@ -316,6 +316,7 @@ pub enum Mode {
Build {
queue: VecDeque<CommandDescriptor>,
process: Option<std::process::Child>,
play_after_build: bool,
},
Play {
process: std::process::Child,
@@ -573,6 +574,7 @@ pub struct Editor {
pub surface_data_viewer: Option<SurfaceDataViewer>,
pub processed_ui_messages: usize,
pub styles: FxHashMap<EditorStyle, StyleResource>,
pub running_game_process: Option<(std::process::Child, Arc<AtomicBool>)>,
}
impl Editor {
@@ -983,6 +985,7 @@ impl Editor {
surface_data_viewer: None,
processed_ui_messages: 0,
styles,
running_game_process: None,
};
if let Some(data) = startup_data {
@@ -1139,7 +1142,9 @@ impl Editor {
} else if hot_key == key_bindings.load_scene {
sender.send(Message::OpenLoadSceneDialog);
} else if hot_key == key_bindings.run_game {
sender.send(Message::SwitchToBuildMode);
sender.send(Message::SwitchToBuildMode {
play_after_build: true,
});
} else if hot_key == key_bindings.save_scene {
if let Some(entry) = self.scenes.current_scene_entry_ref() {
if let Some(path) = entry.path.as_ref() {
@@ -1315,6 +1320,11 @@ impl Editor {
self.build_window = build_window.handle_ui_message(message, ui, || {
self.message_sender.send(Message::SwitchToEditMode)
});
if self.build_window.is_none() {
if let Some((process, active)) = self.running_game_process.take() {
self.mode = Mode::Play { process, active };
}
}
}
if let Some(export_window) = self.export_window.as_mut() {
export_window.handle_ui_message(message, ui, &self.message_sender);
@@ -1549,9 +1559,9 @@ impl Editor {
}
}
fn set_build_mode(&mut self) {
if !matches!(self.mode, Mode::Edit) {
Log::err("Cannot enter build mode when from non-Edit mode!");
fn set_build_mode(&mut self, play_after_build: bool) {
if matches!(self.mode, Mode::Build { .. }) {
Log::err("Cannot enter build mode when another build mode is active!");
return;
}
@@ -1581,10 +1591,24 @@ impl Editor {
.cloned()
.collect::<VecDeque<_>>();
self.mode = Mode::Build {
queue,
process: None,
};
let old_mode = std::mem::replace(
&mut self.mode,
Mode::Build {
queue,
process: None,
play_after_build,
},
);
match old_mode {
Mode::Edit => {}
Mode::Build { .. } => {
unreachable!();
}
Mode::Play { process, active } => {
self.running_game_process = Some((process, active));
}
}
let ui = self.engine.user_interfaces.first_mut();
self.build_window = Some(BuildWindow::new("your game", &mut ui.build_ctx()));
@@ -2156,6 +2180,7 @@ impl Editor {
Mode::Build {
ref mut process,
ref mut queue,
play_after_build,
} => {
if process.is_none() {
if let Some(build_command) = queue.pop_front() {
@@ -2197,14 +2222,26 @@ impl Editor {
Log::err("Failed to build the game!");
self.mode = Mode::Edit;
self.on_mode_changed();
} else if queue.is_empty() {
} else if queue.is_empty() && play_after_build {
self.set_play_mode();
} else {
if let Some(build_window) = self.build_window.as_mut() {
build_window.reset(self.engine.user_interfaces.first());
let ui = self.engine.user_interfaces.first();
if queue.is_empty() {
if let Some(build_window) = self.build_window.take() {
build_window.destroy(ui);
}
if let Some((process, active)) =
self.running_game_process.take()
{
self.mode = Mode::Play { process, active };
}
} else {
if let Some(build_window) = self.build_window.as_mut() {
build_window.reset(ui);
}
// Continue on next command.
*process = None;
}
// Continue on next command.
*process = None;
}
}
}
@@ -2384,10 +2421,12 @@ impl Editor {
.world_viewer
.try_locate_object(handle, self.engine.user_interfaces.first()),
Message::SwitchMode => match self.mode {
Mode::Edit => self.set_build_mode(),
Mode::Edit => self.set_build_mode(true),
_ => self.set_editor_mode(),
},
Message::SwitchToBuildMode => self.set_build_mode(),
Message::SwitchToBuildMode { play_after_build } => {
self.set_build_mode(play_after_build)
}
Message::SwitchToEditMode => self.set_editor_mode(),
Message::OpenLoadSceneDialog => {
self.menu
+3 -1
View File
@@ -78,7 +78,9 @@ pub enum Message {
SetCurrentScene(Uuid),
FocusObject(Handle<Node>),
SetEditorCameraProjection(Projection),
SwitchToBuildMode,
SwitchToBuildMode {
play_after_build: bool,
},
SwitchToEditMode,
SwitchMode,
OpenLoadSceneDialog,
+45 -9
View File
@@ -39,11 +39,16 @@ use crate::{
message::{MessageDirection, MouseButton, UiMessage},
numeric::{NumericUpDownBuilder, NumericUpDownMessage},
stack_panel::StackPanelBuilder,
style::{resource::StyleResourceExt, Style},
tab_control::{
Tab, TabControl, TabControlBuilder, TabControlMessage, TabDefinition, TabUserData,
},
text::{TextBuilder, TextMessage},
utils::make_simple_tooltip,
utils::{
make_dropdown_list_option, make_dropdown_list_option_universal,
make_dropdown_list_option_with_height, make_image_button_with_tooltip,
make_simple_tooltip,
},
vec::{Vec3EditorBuilder, Vec3EditorMessage},
widget::{WidgetBuilder, WidgetMessage},
window::{WindowBuilder, WindowMessage, WindowTitle},
@@ -64,12 +69,6 @@ use crate::{
DropdownListBuilder, GameScene, Message, Mode, SaveSceneConfirmationDialogAction,
SceneContainer, Settings,
};
use fyrox::gui::style::resource::StyleResourceExt;
use fyrox::gui::style::Style;
use fyrox::gui::utils::{
make_dropdown_list_option, make_dropdown_list_option_universal,
make_dropdown_list_option_with_height, make_image_button_with_tooltip,
};
use std::{
ops::Deref,
sync::mpsc::{self, Receiver},
@@ -281,6 +280,7 @@ pub struct SceneViewer {
interaction_modes: FxHashMap<Uuid, Handle<UiNode>>,
camera_projection: Handle<UiNode>,
play: Handle<UiNode>,
build: Handle<UiNode>,
stop: Handle<UiNode>,
build_profile: Handle<UiNode>,
sender: MessageSender,
@@ -305,6 +305,7 @@ impl SceneViewer {
let selection_frame;
let camera_projection;
let play;
let build;
let stop;
let build_profile;
@@ -376,6 +377,10 @@ impl SceneViewer {
.with_orientation(Orientation::Horizontal)
.build(ctx);
let build_tooltip = "Build Project.\nBuilds the game, but does not run it. Could be \
useful for hot reloading - change the source code and then press this button. The new version \
of the game DLL will be built and automagically loaded by the editor and the running game.";
let top_ribbon = GridBuilder::new(
WidgetBuilder::new()
.with_child(interaction_mode_panel)
@@ -411,7 +416,8 @@ impl SceneViewer {
play = ButtonBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.with_width(26.0),
.with_width(26.0)
.with_tooltip(make_simple_tooltip(ctx, "Play")),
)
.with_content(
ImageBuilder::new(
@@ -429,6 +435,29 @@ impl SceneViewer {
.build(ctx);
play
})
.with_child({
build = ButtonBuilder::new(
WidgetBuilder::new()
.with_margin(Thickness::uniform(1.0))
.with_width(26.0)
.with_tooltip(make_simple_tooltip(ctx, build_tooltip)),
)
.with_content(
ImageBuilder::new(
WidgetBuilder::new()
.with_width(16.0)
.with_height(16.0)
.with_margin(Thickness::uniform(4.0))
.with_background(
Brush::Solid(Color::opaque(0, 200, 0)).into(),
),
)
.with_opt_texture(load_image!("../../resources/hammer.png"))
.build(ctx),
)
.build(ctx);
build
})
.with_child({
stop = ButtonBuilder::new(
WidgetBuilder::new()
@@ -571,6 +600,7 @@ impl SceneViewer {
scene_gizmo_image,
debug_switches,
grid_snap_menu,
build,
}
}
}
@@ -717,7 +747,13 @@ impl SceneViewer {
}
if message.destination() == self.play {
self.sender.send(Message::SwitchToBuildMode);
self.sender.send(Message::SwitchToBuildMode {
play_after_build: true,
});
} else if message.destination() == self.build {
self.sender.send(Message::SwitchToBuildMode {
play_after_build: false,
});
} else if message.destination() == self.stop {
self.sender.send(Message::SwitchToEditMode);
}
Generated
+48
View File
@@ -0,0 +1,48 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1739866667,
"narHash": "sha256-EO1ygNKZlsAC9avfcwHkKGMsmipUk1Uc0TbrEZpkn64=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "73cf49b8ad837ade2de76f87eb53fc85ed5d4680",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1740074384,
"narHash": "sha256-T2eO9ognlph94/TyAu1uILo38fZG1G4S5FQxG+YBDv0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "d291a120b6524911249b198baf3ec3e07ff57e04",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+46
View File
@@ -0,0 +1,46 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
nixpkgs,
rust-overlay,
...
}:
let
overlays = [
(import rust-overlay)
];
systems = [
"x86_64-linux"
"aarch64-linux"
];
forAllSystems = f:
nixpkgs.lib.genAttrs systems
(system: f { pkgs = import nixpkgs { inherit system overlays; }; });
in
{
devShells = forAllSystems ({ pkgs }: with pkgs; {
default = mkShell rec {
buildInputs = [
rust-bin.stable.latest.default
pkg-config
xorg.libxcb
alsa-lib
wayland
libxkbcommon
libGL
];
LD_LIBRARY_PATH = "${lib.makeLibraryPath buildInputs}";
};
});
};
}
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-animation"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -15,8 +15,8 @@ readme = "README.md"
rust-version = "1.80"
[dependencies]
fyrox-core = { version = "0.36.0", path = "../fyrox-core" }
fyrox-resource = { version = "0.36.0", path = "../fyrox-resource" }
fyrox-core = { version = "0.36.2", path = "../fyrox-core" }
fyrox-resource = { version = "0.36.2", path = "../fyrox-resource" }
strum = "0.26.1"
strum_macros = "0.26.1"
fxhash = "0.2.1"
+54 -15
View File
@@ -235,7 +235,7 @@ impl TrackValue {
/// Tries to perform a numeric type casting of the current value to some other and returns a boxed value, that can
/// be used to set the value using reflection.
pub fn apply_to_any(&self, any: &mut dyn Any, value_type: ValueType) {
pub fn apply_to_any(&self, any: &mut dyn Any, value_type: ValueType) -> bool {
fn convert_vec2<T>(vec2: &Vector2<f32>) -> Vector2<T>
where
f32: AsPrimitive<T>,
@@ -260,17 +260,19 @@ impl TrackValue {
Vector4::new(vec4.x.as_(), vec4.y.as_(), vec4.z.as_(), vec4.w.as_())
}
fn set<T>(any: &mut dyn Any, value: T)
fn set<T>(any: &mut dyn Any, value: T) -> bool
where
T: Any + Copy,
{
if let Some(boolean) = any.downcast_mut::<T>() {
*boolean = value;
if let Some(any_val) = any.downcast_mut::<T>() {
*any_val = value;
true
} else {
Log::err(format!(
"Animation: unable to set value of type {}! Types mismatch!",
any::type_name::<T>()
))
));
false
}
}
@@ -287,7 +289,7 @@ impl TrackValue {
ValueType::I16 => set(any, *real as i16),
ValueType::U8 => set(any, *real as u8),
ValueType::I8 => set(any, *real as i8),
_ => (),
_ => false,
},
TrackValue::Vector2(vec2) => match value_type {
ValueType::Vector2Bool => set(any, Vector2::new(vec2.x.ne(&0.0), vec2.y.ne(&0.0))),
@@ -301,7 +303,7 @@ impl TrackValue {
ValueType::Vector2I16 => set(any, convert_vec2::<i16>(vec2)),
ValueType::Vector2U8 => set(any, convert_vec2::<u8>(vec2)),
ValueType::Vector2I8 => set(any, convert_vec2::<i8>(vec2)),
_ => (),
_ => false,
},
TrackValue::Vector3(vec3) => match value_type {
ValueType::Vector3Bool => set(
@@ -318,7 +320,7 @@ impl TrackValue {
ValueType::Vector3I16 => set(any, convert_vec3::<i16>(vec3)),
ValueType::Vector3U8 => set(any, convert_vec3::<u8>(vec3)),
ValueType::Vector3I8 => set(any, convert_vec3::<i8>(vec3)),
_ => (),
_ => false,
},
TrackValue::Vector4(vec4) => match value_type {
ValueType::Vector4Bool => set(
@@ -340,12 +342,12 @@ impl TrackValue {
ValueType::Vector4I16 => set(any, convert_vec4::<i16>(vec4)),
ValueType::Vector4U8 => set(any, convert_vec4::<u8>(vec4)),
ValueType::Vector4I8 => set(any, convert_vec4::<i8>(vec4)),
_ => (),
_ => false,
},
TrackValue::UnitQuaternion(quat) => match value_type {
ValueType::UnitQuaternionF32 => set(any, *quat),
ValueType::UnitQuaternionF64 => set(any, quat.cast::<f64>()),
_ => (),
_ => false,
},
}
}
@@ -410,9 +412,19 @@ impl BoundValue {
) {
object.as_reflect_mut(&mut |object_ref| {
object_ref.resolve_path_mut(property_path, &mut |result| match result {
Ok(property) => property.as_any_mut(&mut |any| {
self.value.apply_to_any(any, value_type);
}),
Ok(property) => {
let mut applied = false;
property.as_any_mut(&mut |any| {
applied = self.value.apply_to_any(any, value_type);
});
if applied {
property.as_inheritable_variable_mut(&mut |var| {
if let Some(var) = var {
var.mark_modified();
}
});
}
}
Err(err) => {
Log::err(format!(
"Failed to set property {property_path}! Reason: {err:?}"
@@ -459,11 +471,21 @@ pub fn negate_unit_quaternion(a: &UnitQuaternion<f32>) -> UnitQuaternion<f32> {
#[cfg(test)]
mod test {
use crate::value::{BoundValue, TrackValue, ValueBinding, ValueType};
use fyrox_core::reflect::prelude::*;
use fyrox_core::{reflect::prelude::*, variable::InheritableVariable};
#[derive(Default, Reflect, Debug, PartialEq)]
#[derive(Reflect, Debug, PartialEq)]
struct OtherStruct {
field: u32,
inheritable_variable: InheritableVariable<u32>,
}
impl Default for OtherStruct {
fn default() -> Self {
Self {
field: 0,
inheritable_variable: InheritableVariable::new_non_modified(0),
}
}
}
#[derive(Default, Reflect, Debug, PartialEq)]
@@ -499,6 +521,14 @@ mod test {
value: TrackValue::Real(123.0),
};
let inheritable_variable_value = BoundValue {
binding: ValueBinding::Property {
name: "inheritable_variable".into(),
value_type: ValueType::U32,
},
value: TrackValue::Real(123.0),
};
let mut object = MyStruct::default();
some_bool_value.apply_to_object(&mut object, "some_bool", ValueType::Bool);
@@ -509,5 +539,14 @@ mod test {
field_value.apply_to_object(&mut object, "other_struct.field", ValueType::U32);
assert_eq!(object.other_struct.field, 123);
assert!(!object.other_struct.inheritable_variable.is_modified());
inheritable_variable_value.apply_to_object(
&mut object,
"other_struct.inheritable_variable",
ValueType::U32,
);
assert_eq!(object.other_struct.field, 123);
assert!(object.other_struct.inheritable_variable.is_modified());
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-build-tools"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
license = "MIT"
description = "Build tools for Fyrox Engine"
@@ -13,7 +13,7 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0" }
fyrox-ui = { path = "../fyrox-ui", version = "0.36.0" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2" }
fyrox-ui = { path = "../fyrox-ui", version = "0.36.2" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.2" }
serde = { version = "1.0.215", features = ["derive"] }
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-core-derive"
version = "0.36.0"
version = "0.36.2"
authors = ["toyboot4e <[email protected]>, Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-core"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -15,8 +15,8 @@ readme = "README.md"
rust-version = "1.80"
[dependencies]
fyrox-core-derive = { path = "../fyrox-core-derive", version = "0.36.0" }
fyrox-math = { path = "../fyrox-math", version = "0.36.0" }
fyrox-core-derive = { path = "../fyrox-core-derive", version = "0.36.2" }
fyrox-math = { path = "../fyrox-math", version = "0.36.2" }
base64 = "0.22.1"
byteorder = "1.4.3"
rand = "0.8.4"
+13 -6
View File
@@ -41,13 +41,13 @@
//! friendliness.
use crate::{reflect::prelude::*, visitor::prelude::*, ComponentProvider};
use std::cell::UnsafeCell;
use std::{
any::{Any, TypeId},
fmt::Debug,
future::Future,
marker::PhantomData,
ops::{Index, IndexMut},
sync::atomic::{self, AtomicIsize},
};
pub mod handle;
@@ -184,15 +184,22 @@ where
// Zero - non-borrowed.
// Negative values - amount of mutable borrows, positive - amount of immutable borrows.
#[derive(Default, Debug)]
struct RefCounter(pub AtomicIsize);
struct RefCounter(pub UnsafeCell<isize>);
unsafe impl Sync for RefCounter {}
unsafe impl Send for RefCounter {}
impl RefCounter {
fn increment(&self) {
self.0.fetch_add(1, atomic::Ordering::Relaxed);
unsafe fn get(&self) -> isize {
*self.0.get()
}
fn decrement(&self) {
self.0.fetch_sub(1, atomic::Ordering::Relaxed);
unsafe fn increment(&self) {
*self.0.get() += 1;
}
unsafe fn decrement(&self) {
*self.0.get() -= 1;
}
}
+36 -74
View File
@@ -20,14 +20,13 @@
use super::{Handle, PayloadContainer, Pool, RefCounter};
use crate::ComponentProvider;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::{
any::TypeId,
cell::RefCell,
cmp::Ordering,
fmt::{Debug, Display, Formatter},
marker::PhantomData,
ops::{Deref, DerefMut},
sync::atomic,
};
pub struct Ref<'a, 'b, T>
@@ -64,7 +63,11 @@ where
T: ?Sized,
{
fn drop(&mut self) {
self.ref_counter.decrement();
// SAFETY: This is safe, because this ref lifetime is managed by the borrow checker,
// so it cannot outlive the pool record.
unsafe {
self.ref_counter.decrement();
}
}
}
@@ -111,7 +114,11 @@ where
T: ?Sized,
{
fn drop(&mut self) {
self.ref_counter.increment();
// SAFETY: This is safe, because this ref lifetime is managed by the borrow checker,
// so it cannot outlive the pool record.
unsafe {
self.ref_counter.increment();
}
}
}
@@ -229,7 +236,7 @@ where
return Err(MultiBorrowError::InvalidHandleGeneration(handle));
}
let current_ref_count = record.ref_counter.0.load(atomic::Ordering::Relaxed);
let current_ref_count = unsafe { record.ref_counter.get() };
if current_ref_count < 0 {
return Err(MultiBorrowError::MutablyBorrowed(handle));
}
@@ -241,16 +248,8 @@ where
return Err(MultiBorrowError::Empty(handle));
};
if let Err(ref_count) = record.ref_counter.0.compare_exchange(
current_ref_count,
current_ref_count + 1,
atomic::Ordering::Acquire,
atomic::Ordering::Relaxed,
) {
// This might happen if other thread have already acquired the mutable reference.
if ref_count < 0 {
return Err(MultiBorrowError::MutablyBorrowed(handle));
}
unsafe {
record.ref_counter.increment();
}
Ok(Ref {
@@ -299,7 +298,9 @@ where
return Err(MultiBorrowError::InvalidHandleGeneration(handle));
}
let current_ref_count = record.ref_counter.0.load(atomic::Ordering::Relaxed);
// SAFETY: It is safe to access the counter because of borrow checker guarantees that
// the record is alive.
let current_ref_count = unsafe { record.ref_counter.get() };
match current_ref_count.cmp(&0) {
Ordering::Less => {
return Err(MultiBorrowError::MutablyBorrowed(handle));
@@ -317,21 +318,10 @@ where
return Err(MultiBorrowError::Empty(handle));
};
if let Err(ref_count) = record.ref_counter.0.compare_exchange(
0,
-1,
atomic::Ordering::Acquire,
atomic::Ordering::Relaxed,
) {
match ref_count.cmp(&0) {
Ordering::Less => {
return Err(MultiBorrowError::MutablyBorrowed(handle));
}
Ordering::Greater => {
return Err(MultiBorrowError::ImmutablyBorrowed(handle));
}
_ => (),
}
// SAFETY: It is safe to access the counter because of borrow checker guarantees that
// the record is alive.
unsafe {
record.ref_counter.decrement();
}
Ok(RefMut {
@@ -364,22 +354,18 @@ where
return Err(MultiBorrowError::InvalidHandleGeneration(handle));
}
// Acquire temporary lock.
if let Err(ref_count) = record.ref_counter.0.compare_exchange(
0,
-1,
atomic::Ordering::Acquire,
atomic::Ordering::Relaxed,
) {
match ref_count.cmp(&0) {
Ordering::Less => {
return Err(MultiBorrowError::MutablyBorrowed(handle));
}
Ordering::Greater => {
return Err(MultiBorrowError::ImmutablyBorrowed(handle));
}
_ => (),
// The record must be non-borrowed to be freed.
// SAFETY: It is safe to access the counter because of borrow checker guarantees that
// the record is alive.
let current_ref_count = unsafe { record.ref_counter.get() };
match current_ref_count.cmp(&0) {
Ordering::Less => {
return Err(MultiBorrowError::MutablyBorrowed(handle));
}
Ordering::Greater => {
return Err(MultiBorrowError::ImmutablyBorrowed(handle));
}
_ => (),
}
// SAFETY: We've enforced borrowing rules by the previous check.
@@ -391,8 +377,6 @@ where
self.free_indices.borrow_mut().push(handle.index);
record.ref_counter.increment();
Ok(payload)
}
}
@@ -439,7 +423,6 @@ where
mod test {
use super::MultiBorrowError;
use crate::pool::Pool;
use std::sync::atomic;
#[derive(PartialEq, Clone, Copy, Debug)]
struct MyPayload(u32);
@@ -485,25 +468,9 @@ mod test {
// Test immutable borrowing of the same element with the following mutable borrowing.
{
let ref_a_1 = ctx.try_get(a);
assert_eq!(
ref_a_1
.as_ref()
.unwrap()
.ref_counter
.0
.load(atomic::Ordering::Relaxed),
1
);
assert_eq!(unsafe { ref_a_1.as_ref().unwrap().ref_counter.get() }, 1);
let ref_a_2 = ctx.try_get(a);
assert_eq!(
ref_a_2
.as_ref()
.unwrap()
.ref_counter
.0
.load(atomic::Ordering::Relaxed),
2
);
assert_eq!(unsafe { ref_a_2.as_ref().unwrap().ref_counter.get() }, 2);
assert_eq!(ref_a_1.as_deref(), Ok(&val_a));
assert_eq!(ref_a_2.as_deref(), Ok(&val_a));
@@ -519,12 +486,7 @@ mod test {
assert_eq!(mut_ref_a_1.as_deref_mut(), Ok(&mut val_a));
assert_eq!(
mut_ref_a_1
.as_ref()
.unwrap()
.ref_counter
.0
.load(atomic::Ordering::Relaxed),
unsafe { mut_ref_a_1.as_ref().unwrap().ref_counter.get() },
-1
);
}
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-dylib"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
authors = ["Dmitry Stepanov <[email protected]>", "Fyrox Engine Contributors"]
license = "MIT"
@@ -21,4 +21,4 @@ crate-type = ["dylib"]
mesh_analysis = ["fyrox-impl/mesh_analysis"]
[dependencies]
fyrox-impl = { path = "../fyrox-impl", version = "0.36.0" }
fyrox-impl = { path = "../fyrox-impl", version = "0.36.2" }
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-graph"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -14,6 +14,6 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.2" }
fxhash = "0.2.1"
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-graphics"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
license = "MIT"
description = "Graphics API abstraction for Fyrox Game Engine"
@@ -13,7 +13,7 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0", features = ["serde"] }
fyrox-core = { path = "../fyrox-core", version = "0.36.2", features = ["serde"] }
glow = "0.16"
serde = { version = "1", features = ["derive"] }
strum = "0.26.1"
+10 -10
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-impl"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>", "Fyrox Engine Contributors"]
edition = "2021"
license = "MIT"
@@ -15,15 +15,15 @@ readme = "README.md"
rust-version = "1.80"
[dependencies]
fyrox-core-derive = { path = "../fyrox-core-derive", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.0", features = ["serde"] }
fyrox-sound = { path = "../fyrox-sound", version = "0.36.0" }
fyrox-ui = { path = "../fyrox-ui", version = "0.36.0" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.0" }
fyrox-animation = { path = "../fyrox-animation", version = "0.36.0" }
fyrox-graph = { path = "../fyrox-graph", version = "0.36.0" }
fyrox-graphics = { path = "../fyrox-graphics", version = "0.36.0" }
fyrox-texture = { path = "../fyrox-texture", version = "0.36.0" }
fyrox-core-derive = { path = "../fyrox-core-derive", version = "0.36.2" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2", features = ["serde"] }
fyrox-sound = { path = "../fyrox-sound", version = "0.36.2" }
fyrox-ui = { path = "../fyrox-ui", version = "0.36.2" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.2" }
fyrox-animation = { path = "../fyrox-animation", version = "0.36.2" }
fyrox-graph = { path = "../fyrox-graph", version = "0.36.2" }
fyrox-graphics = { path = "../fyrox-graphics", version = "0.36.2" }
fyrox-texture = { path = "../fyrox-texture", version = "0.36.2" }
fyrox-autotile = { path = "../fyrox-autotile", version = "0.36.0" }
rapier2d = { version = "0.23", features = ["debug-render"] }
rapier3d = { version = "0.23", features = ["debug-render"] }
+4 -11
View File
@@ -625,6 +625,8 @@ impl PhysicsWorld {
max_ccd_substeps: self.integration_parameters.max_ccd_substeps as usize,
};
let mut query = self.query.borrow_mut();
self.pipeline.step(
&self.gravity,
&integration_parameters,
@@ -636,9 +638,7 @@ impl PhysicsWorld {
&mut self.joints.set,
&mut self.multibody_joints.set,
&mut self.ccd_solver,
// In Rapier 0.17 passing query pipeline here sometimes causing panic in numeric overflow,
// so we keep updating it manually.
None,
Some(&mut query),
&(),
&*self.event_handler,
);
@@ -715,14 +715,7 @@ impl PhysicsWorld {
pub fn cast_ray<S: QueryResultsStorage>(&self, opts: RayCastOptions, query_buffer: &mut S) {
let time = instant::Instant::now();
let mut query = self.query.borrow_mut();
// TODO: Ideally this must be called once per frame, but it seems to be impossible because
// a body can be deleted during the consecutive calls of this method which will most
// likely end up in panic because of invalid handle stored in internal acceleration
// structure. This could be fixed by delaying deleting of bodies/collider to the end
// of the frame.
query.update(&self.colliders);
let query = self.query.borrow_mut();
query_buffer.clear();
let ray = Ray::new(
+4 -11
View File
@@ -1162,6 +1162,8 @@ impl PhysicsWorld {
max_ccd_substeps: self.integration_parameters.max_ccd_substeps as usize,
};
let mut query = self.query.borrow_mut();
self.pipeline.step(
&self.gravity,
&integration_parameters,
@@ -1173,9 +1175,7 @@ impl PhysicsWorld {
&mut self.joints.set,
&mut self.multibody_joints.set,
&mut self.ccd_solver,
// In Rapier 0.17 passing query pipeline here sometimes causing panic in numeric overflow,
// so we keep updating it manually.
None,
Some(&mut query),
&(),
&*self.event_handler,
);
@@ -1252,14 +1252,7 @@ impl PhysicsWorld {
pub fn cast_ray<S: QueryResultsStorage>(&self, opts: RayCastOptions, query_buffer: &mut S) {
let time = instant::Instant::now();
let mut query = self.query.borrow_mut();
// TODO: Ideally this must be called once per frame, but it seems to be impossible because
// a body can be deleted during the consecutive calls of this method which will most
// likely end up in panic because of invalid handle stored in internal acceleration
// structure. This could be fixed by delaying deleting of bodies/collider to the end
// of the frame.
query.update(&self.colliders);
let query = self.query.borrow_mut();
query_buffer.clear();
let ray = Ray::new(
+4 -8
View File
@@ -643,13 +643,11 @@ impl NodeTrait for Mesh {
fn on_global_transform_changed(
&self,
_new_global_transform: &Matrix4<f32>,
new_global_transform: &Matrix4<f32>,
context: &mut SyncContext,
) {
if self.surfaces.iter().any(|s| !s.bones.is_empty()) {
let mut world_aabb = self
.local_bounding_box()
.transform(&self.global_transform());
let mut world_aabb = self.local_bounding_box().transform(new_global_transform);
// Special case for skinned meshes.
for surface in self.surfaces.iter() {
@@ -662,10 +660,8 @@ impl NodeTrait for Mesh {
self.world_bounding_box.set(world_aabb)
} else {
self.world_bounding_box.set(
self.local_bounding_box()
.transform(&self.global_transform()),
);
self.world_bounding_box
.set(self.local_bounding_box().transform(new_global_transform));
}
}
+13 -84
View File
@@ -29,20 +29,7 @@ use crate::{
visitor::{Visit, VisitError, VisitResult, Visitor},
},
engine::SerializationContext,
scene::{
self,
camera::Camera,
decal::Decal,
dim2::{self, rectangle::Rectangle},
light::{directional::DirectionalLight, point::PointLight, spot::SpotLight},
mesh::Mesh,
node::Node,
particle_system::ParticleSystem,
pivot::Pivot,
sound::{listener::Listener, Sound},
sprite::Sprite,
terrain::Terrain,
},
scene::node::Node,
};
/// A wrapper for node pool record that allows to define custom visit method to have full
@@ -51,80 +38,22 @@ use crate::{
pub struct NodeContainer(Option<Node>);
fn read_node(name: &str, visitor: &mut Visitor) -> Result<Node, VisitError> {
let node = {
// Handle legacy nodes.
let mut kind_id = 0u8;
if kind_id.visit("KindId", visitor).is_ok() {
let mut node = match kind_id {
0 => Node::new(Pivot::default()),
1 => {
let mut region = visitor.enter_region(name)?;
let mut region = visitor.enter_region(name)?;
let mut light_id = 0u32;
light_id.visit("KindId", &mut region)?;
let mut id = Uuid::default();
id.visit("TypeUuid", &mut region)?;
let mut light_node = match light_id {
0 => Node::new(SpotLight::default()),
1 => Node::new(PointLight::default()),
2 => Node::new(DirectionalLight::default()),
_ => {
return Err(VisitError::User(format!(
"Invalid legacy light kind {light_id}"
)))
}
};
let serialization_context = region
.blackboard
.get::<SerializationContext>()
.expect("Visitor environment must contain serialization context!");
light_node.visit("Data", &mut region)?;
let mut node = serialization_context
.node_constructors
.try_create(&id)
.ok_or_else(|| VisitError::User(format!("Unknown node type uuid {id}!")))?;
return Ok(light_node);
}
2 => Node::new(Camera::default()),
3 => Node::new(Mesh::default()),
4 => Node::new(Sprite::default()),
5 => Node::new(ParticleSystem::default()),
6 => Node::new(Terrain::default()),
7 => Node::new(Decal::default()),
8 => Node::new(scene::rigidbody::RigidBody::default()),
9 => Node::new(scene::collider::Collider::default()),
10 => Node::new(scene::joint::Joint::default()),
11 => Node::new(Rectangle::default()),
12 => Node::new(dim2::rigidbody::RigidBody::default()),
13 => Node::new(dim2::collider::Collider::default()),
14 => Node::new(dim2::joint::Joint::default()),
15 => Node::new(Sound::default()),
16 => Node::new(Listener::default()),
_ => {
return Err(VisitError::User(format!(
"Invalid legacy node kind {kind_id}"
)))
}
};
node.visit(name, visitor)?;
node
} else {
// Latest version
let mut region = visitor.enter_region(name)?;
let mut id = Uuid::default();
id.visit("TypeUuid", &mut region)?;
let serialization_context = region
.blackboard
.get::<SerializationContext>()
.expect("Visitor environment must contain serialization context!");
let mut node = serialization_context
.node_constructors
.try_create(&id)
.ok_or_else(|| VisitError::User(format!("Unknown node type uuid {id}!")))?;
node.visit("NodeData", &mut region)?;
node
}
};
node.visit("NodeData", &mut region)?;
Ok(node)
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-math"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
+9
View File
@@ -620,6 +620,15 @@ pub struct SmoothAngle {
}
impl SmoothAngle {
#[inline]
pub fn new(angle: f32, speed: f32) -> Self {
Self {
angle,
target: angle,
speed,
}
}
#[inline]
pub fn set_target(&mut self, angle: f32) -> &mut Self {
self.target = angle;
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-resource"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -14,7 +14,7 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2" }
fxhash = "0.2.1"
ron = "0.8.0"
serde = { version = "1", features = ["derive"] }
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-scripts"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -14,4 +14,4 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox = { version = "0.36.0", path = "../fyrox" }
fyrox = { version = "0.36.2", path = "../fyrox" }
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-sound"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -15,8 +15,8 @@ readme = "README.md"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.2" }
hrtf = "0.8.0"
hound = "3.4.0"
strum = "0.26.1"
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-texture"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
license = "MIT"
description = "Texture utilities for Fyrox Engine"
@@ -13,8 +13,8 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2" }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.2" }
ddsfile = "0.5.0"
fast_image_resize = "5.0.0"
serde = { version = "1", features = ["derive"] }
+6 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-ui"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>"]
edition = "2021"
license = "MIT"
@@ -15,11 +15,11 @@ readme = "README.md"
rust-version = "1.80"
[dependencies]
fyrox-core = { path = "../fyrox-core", version = "0.36.0", features = ["serde"] }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.0" }
fyrox-texture = { path = "../fyrox-texture", version = "0.36.0" }
fyrox-graph = { path = "../fyrox-graph", version = "0.36.0" }
fyrox-animation = { path = "../fyrox-animation", version = "0.36.0" }
fyrox-core = { path = "../fyrox-core", version = "0.36.2", features = ["serde"] }
fyrox-resource = { path = "../fyrox-resource", version = "0.36.2" }
fyrox-texture = { path = "../fyrox-texture", version = "0.36.2" }
fyrox-graph = { path = "../fyrox-graph", version = "0.36.2" }
fyrox-animation = { path = "../fyrox-animation", version = "0.36.2" }
lazy_static = "1.4.0"
copypasta = "0.10.1"
fontdue = "0.9.2"
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox"
version = "0.36.0"
version = "0.36.2"
authors = ["Dmitry Stepanov <[email protected]>", "Fyrox Engine Contributors"]
edition = "2021"
license = "MIT"
@@ -20,5 +20,5 @@ dylib = ["fyrox-dylib"]
mesh_analysis = ["fyrox-impl/mesh_analysis", "fyrox-dylib/mesh_analysis"]
[dependencies]
fyrox-impl = { version = "0.36.0", path = "../fyrox-impl", optional = true }
fyrox-dylib = { version = "0.36.0", path = "../fyrox-dylib", optional = true }
fyrox-impl = { version = "0.36.2", path = "../fyrox-impl", optional = true }
fyrox-dylib = { version = "0.36.2", path = "../fyrox-dylib", optional = true }
+4 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-project-manager"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
authors = ["Dmitry Stepanov <[email protected]>"]
license = "MIT"
@@ -13,9 +13,9 @@ repository = "https://github.com/FyroxEngine/Fyrox"
rust-version = "1.80"
[dependencies]
fyrox = { version = "0.36.0", path = "../fyrox" }
fyrox-template-core = { version = "0.36.0", path = "../template-core" }
fyrox-build-tools = { version = "0.36.0", path = "../fyrox-build-tools" }
fyrox = { version = "0.36.2", path = "../fyrox" }
fyrox-template-core = { version = "0.36.2", path = "../template-core" }
fyrox-build-tools = { version = "0.36.2", path = "../fyrox-build-tools" }
serde = { version = "1", features = ["derive"] }
ron = "0.8.1"
open = "5.0.1"
+22
View File
@@ -191,10 +191,32 @@ fn make_project_item(
.with_text(engine_version)
.build(ctx);
let project_size = if let Some(project_dir) = Path::new(path).parent() {
let size = utils::calculate_directory_size(project_dir);
utils::format_size(size)
} else {
String::from("N/A")
};
let size_text = TextBuilder::new(
WidgetBuilder::new()
.with_foreground(ctx.style.property(Style::BRUSH_BRIGHTEST))
.with_margin(Thickness {
left: 0.0,
top: 6.0,
right: 8.0,
bottom: 0.0,
}),
)
.with_font_size(13.0.into())
.with_text(format!("Size: {}", project_size))
.build(ctx);
let info = StackPanelBuilder::new(
WidgetBuilder::new()
.with_horizontal_alignment(HorizontalAlignment::Right)
.with_vertical_alignment(VerticalAlignment::Center)
.with_child(size_text)
.with_child(engine_version)
.with_child(hot_reload),
)
+3 -2
View File
@@ -226,8 +226,9 @@ impl UpgradeTool {
if message.destination() == self.version_type_selector {
match *index {
0 => {
self.selected_version =
Version::Specific(fyrox_template_core::CURRENT_VERSION.to_string());
self.selected_version = Version::Specific(
fyrox_template_core::CURRENT_ENGINE_VERSION.to_string(),
);
}
1 => {
self.selected_version = Version::Local;
+36
View File
@@ -28,6 +28,7 @@ use fyrox::{
},
};
use std::{
fs,
path::{Path, PathBuf},
process::{Command, Stdio},
};
@@ -157,3 +158,38 @@ pub fn fyrox_dependency_from_path(manifest_path: &Path) -> Option<Dependency> {
pub fn has_fyrox_in_deps(metadata: &Metadata) -> bool {
fyrox_dependency(metadata).is_some()
}
pub fn calculate_directory_size(path: &Path) -> u64 {
let mut total_size = 0;
if let Ok(entries) = fs::read_dir(path) {
for entry in entries.flatten() {
let entry_path = entry.path();
if entry_path.is_file() {
if let Ok(metadata) = entry.metadata() {
total_size += metadata.len();
}
} else if entry_path.is_dir() {
total_size += calculate_directory_size(&entry_path);
}
}
}
total_size
}
pub fn format_size(size: u64) -> String {
const KB: u64 = 1024;
const MB: u64 = KB * 1024;
const GB: u64 = MB * 1024;
if size >= GB {
format!("{:.2} GB", size as f64 / GB as f64)
} else if size >= MB {
format!("{:.2} MB", size as f64 / MB as f64)
} else if size >= KB {
format!("{:.2} KB", size as f64 / KB as f64)
} else {
format!("{} B", size)
}
}
+6 -3
View File
@@ -1,13 +1,13 @@
[package]
name = "fyrox-template-core"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
authors = ["Dmitry Stepanov <[email protected]>"]
license = "MIT"
description = "Project template generator for Fyrox engine"
keywords = ["fyrox", "game", "project"]
categories = ["game-development"]
include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md"]
include = ["/src/**/*", "/Cargo.toml", "/LICENSE", "/README.md", "engine.version", "editor.version", "scripts.version"]
homepage = "https://fyrox.rs"
repository = "https://github.com/FyroxEngine/Fyrox"
readme = "README.md"
@@ -19,4 +19,7 @@ convert_case = "0.6.0"
toml = "0.8.10"
toml_edit = "0.22.6"
regex = "1.7.3"
unicode-xid = "0.2.6"
unicode-xid = "0.2.6"
[build-dependencies]
toml_edit = "0.22.6"
+36
View File
@@ -0,0 +1,36 @@
use std::{
fs::File,
io::{Read, Write},
};
use toml_edit::DocumentMut;
fn write_version_file(src: &str, dest: &str) {
let mut fyrox_toml = File::open(src).expect("Cargo.toml must exist!");
let mut toml = String::new();
fyrox_toml
.read_to_string(&mut toml)
.expect("File must be readable");
let document = toml.parse::<DocumentMut>().unwrap();
let package = document
.get("package")
.and_then(|i| i.as_table())
.expect("package section must exist!");
let version = package.get("version").expect("version must be set!");
let mut file = File::create(dest).expect("version file must be accessible for writing!");
let version = version.to_string().replace('\"', "");
file.write_all(version.as_bytes())
.expect("fyrox.version must be writable!");
drop(file);
}
fn main() {
write_version_file("../fyrox/Cargo.toml", "./engine.version");
write_version_file("../editor/Cargo.toml", "./editor.version");
write_version_file("../fyrox-scripts/Cargo.toml", "./scripts.version");
}
+13 -29
View File
@@ -26,32 +26,16 @@ use std::{
collections::HashMap,
fmt::Display,
fs::{create_dir_all, read_dir, remove_dir_all, File},
io::{Cursor, Read, Write},
io::{Read, Write},
path::Path,
process::Command,
sync::LazyLock,
};
use toml_edit::{table, value, DocumentMut};
use uuid::Uuid;
// Template generator version must match the engine version. This is checked by the CI.
pub static CURRENT_VERSION: LazyLock<String> = LazyLock::new(|| {
let manifest = include_bytes!("../Cargo.toml");
let mut file = Cursor::new(&manifest);
let mut toml = String::new();
if file.read_to_string(&mut toml).is_ok() {
if let Ok(document) = toml.parse::<DocumentMut>() {
if let Some(package) = document.get("package").and_then(|i| i.as_table()) {
if let Some(version) = package.get("version") {
return version.to_string().replace('\"', "");
}
}
}
}
panic!("Project manager's Cargo.toml is malformed!");
});
pub static CURRENT_ENGINE_VERSION: &str = include_str!("../engine.version");
pub static CURRENT_EDITOR_VERSION: &str = include_str!("../editor.version");
pub static CURRENT_SCRIPTS_VERSION: &str = include_str!("../scripts.version");
fn write_file<P: AsRef<Path>, S: AsRef<str>>(path: P, content: S) -> Result<(), String> {
let mut file = File::create(path.as_ref()).map_err(|e| e.to_string())?;
@@ -621,7 +605,6 @@ fn init_workspace(base_path: &Path, vcs: &str) -> Result<(), String> {
}
// Write Cargo.toml
let version = &*CURRENT_VERSION;
write_file(
base_path.join("Cargo.toml"),
format!(
@@ -631,10 +614,10 @@ members = ["editor", "executor", "executor-wasm", "executor-android", "game", "g
resolver = "2"
[workspace.dependencies.fyrox]
version = "{version}"
version = "{CURRENT_ENGINE_VERSION}"
default-features = false
[workspace.dependencies.fyroxed_base]
version = "{version}"
version = "{CURRENT_EDITOR_VERSION}"
default-features = false
# Separate build profiles for hot reloading. These profiles ensures that build artifacts for
@@ -800,10 +783,10 @@ pub fn upgrade_project(root_path: &Path, version: &str, local: bool) -> Result<(
// TODO: This will be obsolete in 1.0 and should be removed.
let editor_versions = [
(
CURRENT_VERSION.to_string(),
CURRENT_ENGINE_VERSION.to_string(),
(
CURRENT_VERSION.to_string(),
Some(CURRENT_VERSION.to_string()),
CURRENT_EDITOR_VERSION.to_string(),
Some(CURRENT_SCRIPTS_VERSION.to_string()),
),
),
(
@@ -861,10 +844,11 @@ pub fn upgrade_project(root_path: &Path, version: &str, local: bool) -> Result<(
dependencies["fyrox_scripts"] = scripts_table;
}
} else {
dependencies["fyrox"] = value(&*CURRENT_VERSION);
dependencies["fyroxed_base"] = value(&*CURRENT_VERSION);
dependencies["fyrox"] = value(CURRENT_ENGINE_VERSION);
dependencies["fyroxed_base"] = value(CURRENT_EDITOR_VERSION);
if dependencies.contains_key("fyrox_scripts") {
dependencies["fyrox_scripts"] = value(&*CURRENT_VERSION);
dependencies["fyrox_scripts"] =
value(CURRENT_SCRIPTS_VERSION);
}
}
} else if version == "nightly" {
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "fyrox-template"
version = "0.36.0"
version = "0.36.2"
edition = "2021"
authors = ["Dmitry Stepanov <[email protected]>"]
license = "MIT"
@@ -14,5 +14,5 @@ readme = "README.md"
rust-version = "1.80"
[dependencies]
fyrox-template-core = { version = "0.36.0", path = "../template-core" }
fyrox-template-core = { version = "0.36.2", path = "../template-core" }
clap = { version = "4", features = ["derive"] }