diff --git a/.cargo/config b/.cargo/config index 7ce962b17f..d514696c7e 100644 --- a/.cargo/config +++ b/.cargo/config @@ -9,8 +9,8 @@ csv-import = "run --manifest-path common/Cargo.toml --features=bin_csv --bin csv test-server = "run --bin veloren-server-cli --no-default-features -- -b" tracy-server = "-Zunstable-options run --bin veloren-server-cli --no-default-features --features tracy,simd --profile no_overflow" tracy-world-server = "-Zunstable-options run --bin veloren-server-cli --features tracy,simd --profile no_overflow -- -b" -test-voxygen = "run --bin veloren-voxygen --no-default-features --features simd" -tracy-voxygen = "-Zunstable-options run --bin veloren-voxygen --no-default-features --features tracy,simd --profile no_overflow" +test-voxygen = "run --bin veloren-voxygen --no-default-features --features simd,egui-ui" +tracy-voxygen = "-Zunstable-options run --bin veloren-voxygen --no-default-features --features tracy,simd,egui-ui --profile no_overflow" server = "run --bin veloren-server-cli" dbg-voxygen = "run --bin veloren-voxygen -Zunstable-options --profile debuginfo" diff --git a/Cargo.lock b/Cargo.lock index b496d58d02..f0ffddf320 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,6 +257,12 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9ff149ed9780025acfdb36862d35b28856bb693ceb451259a7164442f22fdc3" +[[package]] +name = "atomic_refcell" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681b971236e0f76b20fcafca0236b8718c9186ee778d67cd78bd5f28fd85427f" + [[package]] name = "atomicwrites" version = "0.3.0" @@ -1437,12 +1443,47 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "egui" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788148861d80b87d28d64440a3d31cae190e50ccc3ea585597466d38428365d7" +dependencies = [ + "epaint", +] + +[[package]] +name = "egui_wgpu_backend" +version = "0.8.0" +source = "git+https://github.com/hasenbanck/egui_wgpu_backend.git?rev=63a002c6a9b6c016e45806dd065864431caab621#63a002c6a9b6c016e45806dd065864431caab621" +dependencies = [ + "bytemuck", + "epi", + "wgpu", +] + +[[package]] +name = "egui_winit_platform" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd4cf17c0cd4dbcf2f8fef55a3592b9b7cfd970576c7302d8ba5c521b8560371" +dependencies = [ + "egui", + "winit", +] + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "emath" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e73d6c8c70eadb71756fbbc3c303ab25e163b46b656886dd250de5636efea12" + [[package]] name = "encoding_rs" version = "0.8.28" @@ -1499,6 +1540,28 @@ dependencies = [ "syn 1.0.72", ] +[[package]] +name = "epaint" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e2db640801230bdda80629bc3a063927a462f5eaf38a98da676954e78ccb99" +dependencies = [ + "ahash 0.7.4", + "atomic_refcell", + "emath", + "ordered-float 2.5.1", + "rusttype 0.9.2", +] + +[[package]] +name = "epi" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c4f6cbede1fc8f836384f85295a59199a4825940abcc3a8a29cfe2e3c37583" +dependencies = [ + "egui", +] + [[package]] name = "error-code" version = "2.3.0" @@ -6095,6 +6158,9 @@ dependencies = [ "directories-next", "dispatch 0.1.4", "dot_vox", + "egui", + "egui_wgpu_backend", + "egui_winit_platform", "enum-iterator", "euc", "futures-executor", @@ -6138,6 +6204,7 @@ dependencies = [ "veloren-i18n", "veloren-server", "veloren-voxygen-anim", + "veloren-voxygen-egui", "veloren-world", "wgpu", "wgpu-profiler", @@ -6151,13 +6218,10 @@ name = "veloren-voxygen-anim" version = "0.10.0" dependencies = [ "bytemuck", - "find_folder", "lazy_static", - "libloading 0.7.0", - "notify 5.0.0-pre.9", - "tracing", "vek", "veloren-common", + "veloren-voxygen-dynlib", ] [[package]] @@ -6167,6 +6231,35 @@ dependencies = [ "veloren-voxygen-anim", ] +[[package]] +name = "veloren-voxygen-dynlib" +version = "0.1.0" +dependencies = [ + "find_folder", + "libloading 0.7.0", + "notify 5.0.0-pre.9", + "tracing", +] + +[[package]] +name = "veloren-voxygen-egui" +version = "0.9.0" +dependencies = [ + "egui", + "egui_winit_platform", + "lazy_static", + "veloren-client", + "veloren-common", + "veloren-voxygen-dynlib", +] + +[[package]] +name = "veloren-voxygen-egui-dyn" +version = "0.9.0" +dependencies = [ + "veloren-voxygen-egui", +] + [[package]] name = "veloren-world" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index 23e860d861..45716c89b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ members = [ "voxygen/anim", "voxygen/anim/dyn", "voxygen/i18n", + "voxygen/dynlib", + "voxygen/egui", + "voxygen/egui/dyn", "world", "network", "network/protocol", diff --git a/client/src/lib.rs b/client/src/lib.rs index 28efbf8e1e..675f2cd70c 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -13,7 +13,7 @@ pub use common_net::msg::ServerInfo; pub use specs::{ join::Join, saveload::{Marker, MarkerAllocator}, - Builder, DispatcherBuilder, Entity as EcsEntity, ReadStorage, WorldExt, + Builder, DispatcherBuilder, Entity as EcsEntity, ReadStorage, World, WorldExt, }; use crate::addr::ConnectionArgs; diff --git a/common/frontend/src/lib.rs b/common/frontend/src/lib.rs index 358797b823..cf3a72766b 100644 --- a/common/frontend/src/lib.rs +++ b/common/frontend/src/lib.rs @@ -61,6 +61,7 @@ where .add_directive("gfx_backend_vulkan=info".parse().unwrap()) .add_directive("wgpu_core=info".parse().unwrap()) .add_directive("wgpu_core::device=warn".parse().unwrap()) + .add_directive("wgpu_core::swap_chain=info".parse().unwrap()) .add_directive("veloren_network_protocol=info".parse().unwrap()) .add_directive("quinn_proto::connection=info".parse().unwrap()) .add_directive( diff --git a/common/src/clock.rs b/common/src/clock.rs index 0eed375d95..4654fa6065 100644 --- a/common/src/clock.rs +++ b/common/src/clock.rs @@ -85,7 +85,7 @@ impl Clock { .map_or(self.last_dt.as_secs_f32(), |t| t.into_inner()), ); if self.last_dts.len() >= NUMBER_OF_DELTAS_COMPARED && self.last_dt > 2 * stable_dt { - tracing::debug!(?self.last_dt, ?self.total_tick_time, "lag spike detected, unusually slow tick"); + tracing::trace!(?self.last_dt, ?self.total_tick_time, "lag spike detected, unusually slow tick"); stable_dt } else { self.last_dt diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 9925e692c9..94f08e2041 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -23,13 +23,14 @@ use crate::{ use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; +use strum_macros::Display; use vek::*; use super::{BuffKind, Density, Mass}; make_case_elim!( body, - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] + #[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)] #[repr(u32)] pub enum Body { Humanoid(body: humanoid::Body) = 0, diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 1b917e7178..4bd835593f 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage, VecStorage}; use specs_idvs::IdvStorage; use std::collections::{BTreeMap, VecDeque}; +use strum_macros::Display; use vek::*; /// Data returned from character behavior fn's to Character Behavior System. @@ -44,7 +45,7 @@ impl From<&JoinData<'_>> for StateUpdate { } } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Display, PartialEq, Serialize, Deserialize)] pub enum CharacterState { Idle, Climb(climb::Data), diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index c9550723a2..095e1e92c0 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -19,6 +19,7 @@ use std::{ ops::{Add, Div}, time::Duration, }; +use strum_macros::Display; use vek::*; pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; @@ -869,7 +870,7 @@ pub fn tick_attack_or_default( /// Determines what portion a state is in. Used in all attacks (eventually). Is /// used to control aspects of animation code, as well as logic within the /// character states. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Display, Eq, Hash, PartialEq, Serialize, Deserialize)] pub enum StageSection { Buildup, Recover, diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 6de4bde135..bd569f7c4d 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -23,17 +23,16 @@ buildInputs = ["xorg.libxcb"] [features] hot-anim = ["anim/use-dyn-lib"] +hot-egui = ["voxygen-egui/use-dyn-lib", "egui"] singleplayer = ["server"] simd = ["vek/platform_intrinsics"] tracy = ["profiling", "profiling/profile-with-tracy", "common-frontend/tracy", "client/tracy"] plugins = ["client/plugins"] +egui-ui = ["voxygen-egui", "egui", "egui_wgpu_backend", "egui_winit_platform"] # We don't ship egui with published release builds so a separate feature is required that excludes it. -# This feature has been added ahead of the egui merge to allow time for Flatpak, AUR and Nix to be updated -# to ensure there isn't any period of time where we're shipping the egui-ui feature enabled by default. -# This comment will be updated after MR 2253 merges. default-publish = ["singleplayer", "native-dialog", "plugins", "simd"] -default = ["default-publish"] +default = ["default-publish", "egui-ui"] [dependencies] client = {package = "veloren-client", path = "../client"} @@ -47,6 +46,7 @@ common-state = {package = "veloren-common-state", path = "../common/state"} anim = {package = "veloren-voxygen-anim", path = "anim"} i18n = {package = "veloren-i18n", path = "i18n"} +voxygen-egui = {package = "veloren-voxygen-egui", path = "egui", optional = true } # Graphics winit = {version = "0.25.0", features = ["serde"]} @@ -65,6 +65,11 @@ window_clipboard = "0.2" glyph_brush = "0.7.0" keyboard-keynames = { git = "https://gitlab.com/Frinksy/keyboard-keynames.git", rev = "9ae8f89014d0b0c5b61d0e821c5aeb6140c5c0dc" } +# EGUI +egui = {version = "0.12", optional = true } +egui_wgpu_backend = {git = "https://github.com/hasenbanck/egui_wgpu_backend.git", rev = "63a002c6a9b6c016e45806dd065864431caab621", optional = true } +egui_winit_platform = {version = "0.8", optional = true } + # ECS specs = {git = "https://github.com/amethyst/specs.git", rev = "f985bec5d456f7b0dd8aae99848f9473c2cd9d46"} specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "8be2abcddf8f524cb5876e8dd20a7e47cfaf7573" } diff --git a/voxygen/anim/Cargo.toml b/voxygen/anim/Cargo.toml index 787defdbd6..5081c532b8 100644 --- a/voxygen/anim/Cargo.toml +++ b/voxygen/anim/Cargo.toml @@ -5,7 +5,7 @@ name = "veloren-voxygen-anim" version = "0.10.0" [features] -use-dyn-lib = ["libloading", "notify", "lazy_static", "tracing", "find_folder"] +use-dyn-lib = ["lazy_static", "voxygen-dynlib"] be-dyn-lib = [] simd = ["vek/platform_intrinsics"] @@ -13,11 +13,10 @@ default = ["simd"] [dependencies] common = {package = "veloren-common", path = "../../common"} -find_folder = {version = "0.3.0", optional = true} # inline_tweak = "1.0.2" -lazy_static = {version = "1.4.0", optional = true} -libloading = {version = "0.7", optional = true} -notify = {version = "5.0.0-pre.2", optional = true} -tracing = {version = "0.1", optional = true} +bytemuck = { version = "1.4", features=["derive"] } vek = {version = "=0.14.1", features = ["serde"]} -bytemuck = { version="1.4", features=["derive"] } +voxygen-dynlib = {package = "veloren-voxygen-dynlib", path = "../dynlib", optional = true} + +# Hot Reloading +lazy_static = {version = "1.4.0", optional = true} diff --git a/voxygen/anim/dyn/src/lib.rs b/voxygen/anim/dyn/src/lib.rs index 9887b30eb7..ea74d42e96 100644 --- a/voxygen/anim/dyn/src/lib.rs +++ b/voxygen/anim/dyn/src/lib.rs @@ -8,7 +8,7 @@ //! start earlier since a cdylib doesn't pipeline with it's dependencies. //! //! NOTE: the `be-dyn-lib` feature must be used for this crate to be useful, it -//! is not on by default becaue this causes cargo to switch the feature on in +//! is not on by default because this causes cargo to switch the feature on in //! the anim crate when compiling the static lib into voxygen. #[cfg(feature = "be-dyn-lib")] pub use veloren_voxygen_anim::*; diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs index b11e1410ad..ab9d933338 100644 --- a/voxygen/anim/src/lib.rs +++ b/voxygen/anim/src/lib.rs @@ -54,7 +54,6 @@ pub mod bird_large; pub mod bird_medium; pub mod character; pub mod dragon; -#[cfg(feature = "use-dyn-lib")] pub mod dyn_lib; pub mod fish_medium; pub mod fish_small; pub mod fixture; @@ -67,14 +66,13 @@ pub mod ship; pub mod theropod; pub mod vek; -#[cfg(feature = "use-dyn-lib")] -pub use dyn_lib::init; - -#[cfg(feature = "use-dyn-lib")] -use std::ffi::CStr; - use self::vek::*; use bytemuck::{Pod, Zeroable}; +#[cfg(feature = "use-dyn-lib")] +use { + lazy_static::lazy_static, std::ffi::CStr, std::sync::Arc, std::sync::Mutex, + voxygen_dynlib::LoadedLib, +}; type MatRaw = [[f32; 4]; 4]; @@ -91,6 +89,15 @@ fn make_bone(mat: Mat4) -> FigureBoneData { pub type Bone = Transform; +#[cfg(feature = "use-dyn-lib")] +lazy_static! { + static ref LIB: Arc>> = + voxygen_dynlib::init("veloren-voxygen-anim", "veloren-voxygen-anim-dyn", "anim"); +} + +#[cfg(feature = "use-dyn-lib")] +pub fn init() { lazy_static::initialize(&LIB); } + pub trait Skeleton: Send + Sync + 'static { type Attr; type Body; @@ -118,10 +125,11 @@ pub fn compute_matrices( } #[cfg(feature = "use-dyn-lib")] { - let lock = dyn_lib::LIB.lock().unwrap(); + let lock = LIB.lock().unwrap(); let lib = &lock.as_ref().unwrap().lib; - let compute_fn: libloading::Symbol< + #[allow(clippy::type_complexity)] + let compute_fn: voxygen_dynlib::Symbol< fn(&S, Mat4, &mut [FigureBoneData; MAX_BONE_COUNT]) -> Vec3, > = unsafe { lib.get(S::COMPUTE_FN) }.unwrap_or_else(|e| { panic!( @@ -169,10 +177,11 @@ pub trait Animation { } #[cfg(feature = "use-dyn-lib")] { - let lock = dyn_lib::LIB.lock().unwrap(); + let lock = LIB.lock().unwrap(); let lib = &lock.as_ref().unwrap().lib; - let update_fn: libloading::Symbol< + #[allow(clippy::type_complexity)] + let update_fn: voxygen_dynlib::Symbol< fn( &Self::Skeleton, Self::Dependency<'a>, @@ -183,9 +192,8 @@ pub trait Animation { > = unsafe { //let start = std::time::Instant::now(); // Overhead of 0.5-5 us (could use hashmap to mitigate if this is an issue) - let f = lib.get(Self::UPDATE_FN); + lib.get(Self::UPDATE_FN) //println!("{}", start.elapsed().as_nanos()); - f } .unwrap_or_else(|e| { panic!( diff --git a/voxygen/dynlib/Cargo.toml b/voxygen/dynlib/Cargo.toml new file mode 100644 index 0000000000..7208c27386 --- /dev/null +++ b/voxygen/dynlib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "veloren-voxygen-dynlib" +version = "0.1.0" +authors = ["Ben Wallis "] +edition = "2018" + +[dependencies] +find_folder = {version = "0.3.0"} +libloading = {version = "0.7"} +notify = {version = "5.0.0-pre.2"} +tracing = "0.1" diff --git a/voxygen/anim/src/dyn_lib.rs b/voxygen/dynlib/src/lib.rs similarity index 67% rename from voxygen/anim/src/dyn_lib.rs rename to voxygen/dynlib/src/lib.rs index 3e8366ed32..336908f5eb 100644 --- a/voxygen/anim/src/dyn_lib.rs +++ b/voxygen/dynlib/src/lib.rs @@ -1,4 +1,3 @@ -use lazy_static::lazy_static; use libloading::Library; use notify::{immediate_watcher, EventKind, RecursiveMode, Watcher}; use std::{ @@ -8,23 +7,16 @@ use std::{ }; use find_folder::Search; -use std::{env, path::PathBuf}; +use std::{ + env, + env::consts::{DLL_PREFIX, DLL_SUFFIX}, + path::{Path, PathBuf}, + sync::Arc, +}; use tracing::{debug, error, info}; -#[cfg(target_os = "windows")] -const COMPILED_FILE: &str = "veloren_voxygen_anim_dyn.dll"; -#[cfg(target_os = "windows")] -const ACTIVE_FILE: &str = "veloren_voxygen_anim_dyn_active.dll"; - -#[cfg(not(target_os = "windows"))] -const COMPILED_FILE: &str = "libveloren_voxygen_anim_dyn.so"; -#[cfg(not(target_os = "windows"))] -const ACTIVE_FILE: &str = "libveloren_voxygen_anim_dyn_active.so"; - -// This option is required as `hotreload()` moves the `LoadedLib`. -lazy_static! { - pub static ref LIB: Mutex> = Mutex::new(Some(LoadedLib::compile_load())); -} +// Re-exports +pub use libloading::Symbol; /// LoadedLib holds a loaded dynamic library and the location of library file /// with the appropriate OS specific name and extension i.e. @@ -45,20 +37,20 @@ impl LoadedLib { /// /// This is necessary because the very first time you use hot reloading you /// wont have the library, so you can't load it until you have compiled it! - fn compile_load() -> Self { + fn compile_load(dyn_package: &str) -> Self { #[cfg(target_os = "macos")] error!("The hot reloading feature does not work on macos."); // Compile - if !compile() { - panic!("Animation compile failed."); + if !compile(dyn_package) { + panic!("{} compile failed.", dyn_package); } else { - info!("Animation compile succeeded."); + info!("{} compile succeeded.", dyn_package); } - copy(&LoadedLib::determine_path()); + copy(&LoadedLib::determine_path(dyn_package), dyn_package); - Self::load() + Self::load(dyn_package) } /// Load a library from disk. @@ -66,8 +58,8 @@ impl LoadedLib { /// Currently this is pretty fragile, it gets the path of where it thinks /// the dynamic library should be and tries to load it. It will panic if it /// is missing. - fn load() -> Self { - let lib_path = LoadedLib::determine_path(); + fn load(dyn_package: &str) -> Self { + let lib_path = LoadedLib::determine_path(dyn_package); // Try to load the library. let lib = match unsafe { Library::new(lib_path.clone()) } { @@ -84,7 +76,7 @@ impl LoadedLib { /// Determine the path to the dynamic library based on the path of the /// current executable. - fn determine_path() -> PathBuf { + fn determine_path(dyn_package: &str) -> PathBuf { let current_exe = env::current_exe(); // If we got the current_exe, we need to go up a level and then down @@ -109,7 +101,7 @@ impl LoadedLib { Err(e) => { panic!( "Could not determine the path of the current executable, this is needed to \ - hotreload the dynamic library. {:?}", + hot-reload the dynamic library. {:?}", e ); }, @@ -117,7 +109,7 @@ impl LoadedLib { // Determine the platform specific path and push it onto our already // established target/debug dir. - lib_path.push(ACTIVE_FILE); + lib_path.push(active_file(dyn_package)); lib_path } @@ -125,13 +117,14 @@ impl LoadedLib { /// Initialise a watcher. /// -/// The assumption is that this is run from the voxygen crate's root directory -/// as it will watch the relative path `anim` for any changes to `.rs` -/// files. Upon noticing changes it will wait a moment and then recompile. -pub fn init() { - // Make sure first compile is done by accessing the lazy_static and then - // immediately dropping (because we don't actually need it). - drop(LIB.lock()); +/// This will search for the directory named `package_source_dir` and watch the +/// files within it for any changes. +pub fn init( + package: &'static str, + dyn_package: &'static str, + package_source_dir: &'static str, +) -> Arc>> { + let lib_storage = Arc::new(Mutex::new(Some(LoadedLib::compile_load(dyn_package)))); // TODO: use crossbeam let (reload_send, reload_recv) = mpsc::channel(); @@ -139,18 +132,24 @@ pub fn init() { // Start watcher let mut watcher = immediate_watcher(move |res| event_fn(res, &reload_send)).unwrap(); - // Search for the anim directory. - let anim_dir = Search::Kids(1) - .for_folder("anim") - .expect("Could not find the anim crate directory relative to the current directory"); + // Search for the source directory of the package being hot-reloaded. + let watch_dir = Search::Kids(1) + .for_folder(package_source_dir) + .unwrap_or_else(|_| { + panic!( + "Could not find the {} crate directory relative to the current directory", + package_source_dir + ) + }); - watcher.watch(anim_dir, RecursiveMode::Recursive).unwrap(); + watcher.watch(watch_dir, RecursiveMode::Recursive).unwrap(); // Start reloader that watcher signals // "Debounces" events since I can't find the option to do this in the latest // `notify` + let lib_storage_clone = Arc::clone(&lib_storage); std::thread::Builder::new() - .name("voxygen_anim_watcher".into()) + .name(format!("{}_hotreload_watcher", package)) .spawn(move || { let mut modified_paths = std::collections::HashSet::new(); while let Ok(path) = reload_recv.recv() { @@ -162,16 +161,32 @@ pub fn init() { info!( ?modified_paths, - "Hot reloading animations because files in `anim` modified." + "Hot reloading {} because files in `{}` modified.", package, package_source_dir ); - hotreload(); + hotreload(dyn_package, &lib_storage_clone); } }) .unwrap(); // Let the watcher live forever std::mem::forget(watcher); + + lib_storage +} + +fn compiled_file(dyn_package: &str) -> String { dyn_lib_file(dyn_package, false) } + +fn active_file(dyn_package: &str) -> String { dyn_lib_file(dyn_package, true) } + +fn dyn_lib_file(dyn_package: &str, active: bool) -> String { + format!( + "{}{}{}{}", + DLL_PREFIX, + dyn_package.replace("-", "_"), + if active { "_active" } else { "" }, + DLL_SUFFIX + ) } /// Event function to hotreload the dynamic library @@ -180,8 +195,8 @@ pub fn init() { /// before sending them back. fn event_fn(res: notify::Result, sender: &mpsc::Sender) { match res { - Ok(event) => match event.kind { - EventKind::Modify(_) => { + Ok(event) => { + if let EventKind::Modify(_) = event.kind { event .paths .iter() @@ -189,10 +204,9 @@ fn event_fn(res: notify::Result, sender: &mpsc::Sender) { .map(|p| p.to_string_lossy().into_owned()) // Signal reloader .for_each(|p| { let _ = sender.send(p); }); - }, - _ => {}, + } }, - Err(e) => error!(?e, "Animation hotreload watcher error."), + Err(e) => error!(?e, "hotreload watcher error."), } } @@ -200,35 +214,35 @@ fn event_fn(res: notify::Result, sender: &mpsc::Sender) { /// /// This will reload the dynamic library by first internally calling compile /// and then reloading the library. -fn hotreload() { +fn hotreload(dyn_package: &str, loaded_lib: &Mutex>) { // Do nothing if recompile failed. - if compile() { - let mut lock = LIB.lock().unwrap(); + if compile(dyn_package) { + let mut lock = loaded_lib.lock().unwrap(); // Close lib. let loaded_lib = lock.take().unwrap(); loaded_lib.lib.close().unwrap(); - copy(&loaded_lib.lib_path); + copy(&loaded_lib.lib_path, dyn_package); // Open new lib. - *lock = Some(LoadedLib::load()); + *lock = Some(LoadedLib::load(dyn_package)); - info!("Updated animations."); + info!("Updated {}.", dyn_package); } } -/// Recompile the anim package +/// Recompile the dyn package /// /// Returns `false` if the compile failed. -fn compile() -> bool { +fn compile(dyn_package: &str) -> bool { let output = Command::new("cargo") .stderr(Stdio::inherit()) .stdout(Stdio::inherit()) .arg("build") .arg("--package") - .arg("veloren-voxygen-anim-dyn") + .arg(dyn_package) .arg("--features") - .arg("veloren-voxygen-anim-dyn/be-dyn-lib") + .arg(format!("{}/be-dyn-lib", dyn_package)) .output() .unwrap(); @@ -239,10 +253,10 @@ fn compile() -> bool { /// /// We do this for all OS's although it is only strictly necessary for windows. /// The reason we do this is to make the code easier to understand and debug. -fn copy(lib_path: &PathBuf) { +fn copy(lib_path: &Path, dyn_package: &str) { // Use the platform specific names. - let lib_compiled_path = lib_path.with_file_name(COMPILED_FILE); - let lib_output_path = lib_path.with_file_name(ACTIVE_FILE); + let lib_compiled_path = lib_path.with_file_name(compiled_file(dyn_package)); + let lib_output_path = lib_path.with_file_name(active_file(dyn_package)); // Get the path to where the lib was compiled to. debug!(?lib_compiled_path, ?lib_output_path, "Moving."); diff --git a/voxygen/egui/Cargo.toml b/voxygen/egui/Cargo.toml new file mode 100644 index 0000000000..6c59194d8c --- /dev/null +++ b/voxygen/egui/Cargo.toml @@ -0,0 +1,20 @@ +[package] +authors = ["Ben Wallis "] +name = "veloren-voxygen-egui" +edition = "2018" +version = "0.9.0" + +[features] +use-dyn-lib = ["lazy_static", "voxygen-dynlib"] +be-dyn-lib = [] + +[dependencies] +client = {package = "veloren-client", path = "../../client"} +common = {package = "veloren-common", path = "../../common"} +egui = "0.12" +egui_winit_platform = "0.8" +voxygen-dynlib = {package = "veloren-voxygen-dynlib", path = "../dynlib", optional = true} + +# Hot Reloading +lazy_static = {version = "1.4.0", optional = true} + diff --git a/voxygen/egui/dyn/Cargo.toml b/voxygen/egui/dyn/Cargo.toml new file mode 100644 index 0000000000..d4865fcacb --- /dev/null +++ b/voxygen/egui/dyn/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["Imbris "] +edition = "2018" +name = "veloren-voxygen-egui-dyn" +version = "0.9.0" + +[lib] +crate-type = ["dylib"] + +[features] +be-dyn-lib = ["veloren-voxygen-egui/be-dyn-lib"] + +[dependencies] +veloren-voxygen-egui = { path = "../" } diff --git a/voxygen/egui/dyn/src/lib.rs b/voxygen/egui/dyn/src/lib.rs new file mode 100644 index 0000000000..68d5e32166 --- /dev/null +++ b/voxygen/egui/dyn/src/lib.rs @@ -0,0 +1,14 @@ +//! This crate hacks around the inability to dynamically specify the +//! `crate-type` for cargo to build. +//! +//! For more details on the issue this is a decent starting point: https://github.com/rust-lang/cargo/pull/8789 +//! +//! This crate avoids use building the dynamic lib when it isn't needed and the +//! same with the non dynamic build. Additionally, this allows compilation to +//! start earlier since a cdylib doesn't pipeline with it's dependencies. +//! +//! NOTE: the `be-dyn-lib` feature must be used for this crate to be useful, it +//! is not on by default because this causes cargo to switch the feature on in +//! the anim crate when compiling the static lib into voxygen. +#[cfg(feature = "be-dyn-lib")] +pub use veloren_voxygen_egui::*; diff --git a/voxygen/egui/src/character_states.rs b/voxygen/egui/src/character_states.rs new file mode 100644 index 0000000000..52b1c9df13 --- /dev/null +++ b/voxygen/egui/src/character_states.rs @@ -0,0 +1,87 @@ +use crate::{two_col_row, SelectedEntityInfo}; +use common::{ + comp::CharacterState, + states::{charged_melee, combo_melee, dash_melee, leap_melee}, +}; +use egui::{Grid, Ui}; + +pub fn draw_char_state_group( + ui: &mut Ui, + _selected_entity_info: &SelectedEntityInfo, + character_state: &CharacterState, +) { + ui.horizontal(|ui| { + ui.label("Current State: "); + ui.label(character_state.to_string()); + }); + match character_state { + CharacterState::ComboMelee(data) => { + combo_melee_grid(ui, data); + }, + CharacterState::DashMelee(data) => dash_melee_grid(ui, data), + CharacterState::ChargedMelee(data) => charged_melee_grid(ui, data), + // Character states with no associated data to display + CharacterState::Dance + | CharacterState::Idle + | CharacterState::Sit + | CharacterState::GlideWield + | CharacterState::Sneak + | CharacterState::Talk + | CharacterState::Wielding => {}, + CharacterState::LeapMelee(data) => leap_melee_grid(ui, data), + _ => { + ui.label(""); + }, + }; +} + +fn charged_melee_grid(ui: &mut Ui, data: &charged_melee::Data) { + Grid::new("selected_entity_charged_melee_grid") + .spacing([40.0, 4.0]) + .max_col_width(100.0) + .striped(true) + .show(ui, |ui| #[rustfmt::skip] { + two_col_row(ui, "Stage Section", data.stage_section.to_string()); + two_col_row(ui, "Timer", format!("{}ms", data.timer.as_millis())); + two_col_row(ui, "Charge Amount", format!("{:.1}", data.charge_amount)); + two_col_row(ui, "Exhausted", if data.exhausted { "True" } else { "False" }); + }); +} + +fn combo_melee_grid(ui: &mut Ui, data: &combo_melee::Data) { + Grid::new("selected_entity_combo_melee_grid") + .spacing([40.0, 4.0]) + .max_col_width(100.0) + .striped(true) + .show(ui, |ui| #[rustfmt::skip] { + two_col_row(ui, "Stage", data.stage.to_string()); + two_col_row(ui, "Timer", format!("{}ms", data.timer.as_millis())); + two_col_row(ui, "num_stages", data.static_data.num_stages.to_string()); + }); +} + +fn dash_melee_grid(ui: &mut Ui, data: &dash_melee::Data) { + Grid::new("selected_entity_dash_melee_grid") + .spacing([40.0, 4.0]) + .max_col_width(100.0) + .striped(true) + .show(ui, |ui| #[rustfmt::skip] { + two_col_row(ui, "Auto Charge", if data.auto_charge { "True" } else { "False " }); + two_col_row(ui, "Timer", format!("{}ms", data.timer.as_millis())); + two_col_row(ui, "Stage Section", data.stage_section.to_string()); + two_col_row(ui, "Exhausted", if data.exhausted { "True" } else { "False " }); + two_col_row(ui, "Charge End Timer", format!("{}ms", data.charge_end_timer.as_millis())); + }); +} + +fn leap_melee_grid(ui: &mut Ui, data: &leap_melee::Data) { + Grid::new("selected_entity_leap_melee_grid") + .spacing([40.0, 4.0]) + .max_col_width(100.0) + .striped(true) + .show(ui, |ui| #[rustfmt::skip] { + two_col_row(ui, "Stage Section", data.stage_section.to_string()); + two_col_row(ui, "Timer", format!("{}ms", data.timer.as_millis())); + two_col_row(ui, "Exhausted", if data.exhausted { "True" } else { "False " }); + }); +} diff --git a/voxygen/egui/src/lib.rs b/voxygen/egui/src/lib.rs new file mode 100644 index 0000000000..03b905695c --- /dev/null +++ b/voxygen/egui/src/lib.rs @@ -0,0 +1,697 @@ +#![feature(stmt_expr_attributes)] + +#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))] +compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once"); + +mod character_states; + +use client::{Client, Join, World, WorldExt}; +use common::{ + comp, + comp::{Poise, PoiseState}, +}; +use core::mem; +use egui::{ + plot::{Plot, Value}, + widgets::plot::Curve, + CollapsingHeader, Color32, Grid, Label, ScrollArea, Slider, Ui, Window, +}; + +fn two_col_row(ui: &mut Ui, label: impl Into