Windows is weird, cargo is weird..... (also tidy up a few things)

This commit is contained in:
Imbris 2020-06-18 02:45:49 -04:00
parent 18e6b59966
commit 124ed52554
6 changed files with 120 additions and 65 deletions

1
Cargo.lock generated
View File

@ -4606,6 +4606,7 @@ version = "0.6.0"
dependencies = [
"lazy_static",
"libloading 0.6.2",
"log",
"notify",
"vek",
"veloren-common",

View File

@ -9,7 +9,7 @@ name = "voxygen_anim"
crate-type = ["lib", "cdylib"]
[features]
use-dyn-lib = ["libloading", "notify", "lazy_static"]
use-dyn-lib = ["libloading", "notify", "lazy_static", "log"]
be-dyn-lib = []
default = ["be-dyn-lib"]
@ -20,4 +20,4 @@ common = { package = "veloren-common", path = "../../../common" }
libloading = { version = "0.6.2", optional = true }
notify = { version = "5.0.0-pre.2", optional = true }
lazy_static = { version = "1.4.0", optional = true }
log = { version = "0.4.8", optional = true }

View File

@ -3,7 +3,9 @@ use libloading::Library;
use notify::{immediate_watcher, EventKind, RecursiveMode, Watcher};
use std::{
process::{Command, Stdio},
sync::Mutex,
sync::{mpsc, Mutex},
thread,
time::Duration,
};
lazy_static! {
@ -17,21 +19,17 @@ pub struct LoadedLib {
impl LoadedLib {
fn compile_load() -> Self {
// Compile
let _output = Command::new("cargo")
.stderr(Stdio::inherit())
.stdout(Stdio::inherit())
.arg("build")
.arg("--package")
.arg("veloren-voxygen-anim")
.output()
.unwrap();
compile();
#[cfg(target_os = "windows")]
copy();
Self::load()
}
fn load() -> Self {
#[cfg(target_os = "windows")]
let lib = Library::new("../target/debug/voxygen_anim.dll").unwrap();
let lib = Library::new("../target/debug/voxygen_anim_active.dll").unwrap();
#[cfg(not(target_os = "windows"))]
let lib = Library::new("../target/debug/libvoxygen_anim.so").unwrap();
@ -41,8 +39,11 @@ impl LoadedLib {
// Starts up watcher
pub fn init() {
// Make sure first compile is done
drop(LIB.lock());
// TODO: use crossbeam
let (reload_send, reload_recv) = std::sync::mpsc::channel();
let (reload_send, reload_recv) = mpsc::channel();
// Start watcher
let mut watcher = immediate_watcher(move |res| event_fn(res, &reload_send)).unwrap();
@ -51,10 +52,24 @@ pub fn init() {
// Start reloader that watcher signals
// "Debounces" events since I can't find the option to do this in the latest
// `notify`
std::thread::spawn(move || {
while let Ok(()) = reload_recv.recv() {
// Wait for another modify event before reloading
while let Ok(()) = reload_recv.recv_timeout(std::time::Duration::from_millis(300)) {}
thread::spawn(move || {
let mut modified_paths = std::collections::HashSet::new();
while let Ok(path) = reload_recv.recv() {
modified_paths.insert(path);
// Wait for to see if there are more modify events before reloading
while let Ok(path) = reload_recv.recv_timeout(Duration::from_millis(300)) {
modified_paths.insert(path);
}
let mut info = "Hot reloading animations because these files were modified:".to_owned();
for path in std::mem::take(&mut modified_paths) {
info.push('\n');
info.push('\"');
info.push_str(&path);
info.push('\"');
}
log::warn!("{}", info);
// Reload
reload();
@ -67,32 +82,48 @@ pub fn init() {
// Recompiles and hotreloads the lib if the source is changed
// Note: designed with voxygen dir as working dir, could be made more flexible
fn event_fn(res: notify::Result<notify::Event>, sender: &std::sync::mpsc::Sender<()>) {
fn event_fn(res: notify::Result<notify::Event>, sender: &mpsc::Sender<String>) {
match res {
Ok(event) => match event.kind {
EventKind::Modify(_) => {
if event
event
.paths
.iter()
.any(|p| p.extension().map(|e| e == "rs").unwrap_or(false))
{
println!(
"Hot reloading animations because these files were modified:\n{:?}",
event.paths
);
.filter(|p| p.extension().map(|e| e == "rs").unwrap_or(false))
.map(|p| p.to_string_lossy().into_owned())
// Signal reloader
let _ = sender.send(());
}
.for_each(|p| { let _ = sender.send(p); });
},
_ => {},
},
Err(e) => println!("watch error: {:?}", e),
Err(e) => log::error!("Animation hotreload watch error: {:?}", e),
}
}
fn reload() {
// Compile
// Stop if recompile failed
if !compile() {
return;
}
let mut lock = LIB.lock().unwrap();
// Close lib
lock.take().unwrap().lib.close().unwrap();
// Rename lib file on windows
// Called after closing lib so file will be unlocked
#[cfg(target_os = "windows")]
copy();
// Open new lib
*lock = Some(LoadedLib::load());
log::warn!("Updated animations");
}
// Returns false if compile failed
fn compile() -> bool {
let output = Command::new("cargo")
.stderr(Stdio::inherit())
.stdout(Stdio::inherit())
@ -102,21 +133,23 @@ fn reload() {
.output()
.unwrap();
// Stop if recompile failed
// If compile failed
if !output.status.success() {
println!("Failed to compile anim crate");
return;
log::error!("Failed to compile anim crate");
false
} else {
log::warn!("Animation recompile success!!");
true
}
println!("Compile Success!!");
let mut lock = LIB.lock().unwrap();
// Close lib
lock.take().unwrap().lib.close().unwrap();
// Open new lib
*lock = Some(LoadedLib::load());
println!("Updated");
}
// Copy lib file if on windows since loading the lib locks the file blocking
// future compilation
#[cfg(target_os = "windows")]
fn copy() {
std::fs::copy(
"../target/debug/voxygen_anim.dll",
"../target/debug/voxygen_anim_active.dll",
)
.expect("Failed to rename animations dll");
}

View File

@ -20,6 +20,8 @@ pub mod quadruped_small;
#[cfg(feature = "use-dyn-lib")]
pub use dyn_lib::init;
#[cfg(feature = "use-dyn-lib")]
use std::ffi::CStr;
use vek::*;
// TODO: replace with inner type everywhere
@ -83,7 +85,16 @@ pub trait Skeleton: Send + Sync + 'static {
let lib = &lock.as_ref().unwrap().lib;
let compute_fn: libloading::Symbol<fn(&Self) -> ([FigureBoneData; 16], Vec3<f32>)> =
unsafe { lib.get(Self::COMPUTE_FN).unwrap() };
unsafe { lib.get(Self::COMPUTE_FN) }.unwrap_or_else(|err| {
panic!(
"Trying to use: {} but had error: {:?}",
CStr::from_bytes_with_nul(Self::COMPUTE_FN)
.map(CStr::to_str)
.unwrap()
.unwrap(),
err
)
});
compute_fn(self)
}
@ -135,10 +146,20 @@ 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).unwrap();
let f = lib.get(Self::UPDATE_FN);
//println!("{}", start.elapsed().as_nanos());
f
};
}
.unwrap_or_else(|err| {
panic!(
"Trying to use: {} but had error: {:?}",
CStr::from_bytes_with_nul(Self::UPDATE_FN)
.map(CStr::to_str)
.unwrap()
.unwrap(),
err
)
});
update_fn(skeleton, dependency, anim_time, rate, skeleton_attr)
}

View File

@ -4,7 +4,7 @@ use crate::{
render::{FigurePipeline, Mesh, Model, Renderer},
scene::camera::CameraMode,
};
use anim::{Skeleton};
use anim::Skeleton;
use common::{
assets::watch::ReloadIndicator,
comp::{

View File

@ -2103,21 +2103,21 @@ impl<S: Skeleton> FigureState<S> {
fn figure_bone_data_from_anim(mats: [anim::FigureBoneData; 16]) -> [FigureBoneData; 16] {
[
FigureBoneData::new(mats[0].0),
FigureBoneData::new(mats[1].0),
FigureBoneData::new(mats[2].0),
FigureBoneData::new(mats[3].0),
FigureBoneData::new(mats[4].0),
FigureBoneData::new(mats[5].0),
FigureBoneData::new(mats[6].0),
FigureBoneData::new(mats[7].0),
FigureBoneData::new(mats[8].0),
FigureBoneData::new(mats[9].0),
FigureBoneData::new(mats[10].0),
FigureBoneData::new(mats[11].0),
FigureBoneData::new(mats[12].0),
FigureBoneData::new(mats[13].0),
FigureBoneData::new(mats[14].0),
FigureBoneData::new(mats[15].0),
FigureBoneData::new(mats[0].0),
FigureBoneData::new(mats[1].0),
FigureBoneData::new(mats[2].0),
FigureBoneData::new(mats[3].0),
FigureBoneData::new(mats[4].0),
FigureBoneData::new(mats[5].0),
FigureBoneData::new(mats[6].0),
FigureBoneData::new(mats[7].0),
FigureBoneData::new(mats[8].0),
FigureBoneData::new(mats[9].0),
FigureBoneData::new(mats[10].0),
FigureBoneData::new(mats[11].0),
FigureBoneData::new(mats[12].0),
FigureBoneData::new(mats[13].0),
FigureBoneData::new(mats[14].0),
FigureBoneData::new(mats[15].0),
]
}