log: logging to file, console and stdout

This commit is contained in:
2023-10-25 03:05:53 +02:00
parent 23e127e908
commit 5eaefd9aab
13 changed files with 276 additions and 115 deletions
Generated
+92
View File
@@ -255,6 +255,15 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "deranged"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
dependencies = [
"powerfmt",
]
[[package]] [[package]]
name = "directories" name = "directories"
version = "4.0.1" version = "4.0.1"
@@ -677,6 +686,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.3.0" version = "0.3.0"
@@ -892,6 +907,15 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "objc" name = "objc"
version = "0.2.7" version = "0.2.7"
@@ -1015,6 +1039,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.69" version = "1.0.69"
@@ -1285,6 +1315,17 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simplelog"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acee08041c5de3d5048c8b3f6f13fafb3026b24ba43c6a695a0c76179b844369"
dependencies = [
"log 0.4.20",
"termcolor",
"time",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@@ -1349,6 +1390,15 @@ version = "0.12.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a"
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.50" version = "1.0.50"
@@ -1401,9 +1451,11 @@ dependencies = [
"glm", "glm",
"image", "image",
"imgui", "imgui",
"log 0.4.20",
"mint", "mint",
"rfd", "rfd",
"serde", "serde",
"simplelog",
] ]
[[package]] [[package]]
@@ -1417,6 +1469,37 @@ dependencies = [
"weezl", "weezl",
] ]
[[package]]
name = "time"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
dependencies = [
"deranged",
"itoa",
"libc",
"num_threads",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
dependencies = [
"time-core",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.2" version = "0.8.2"
@@ -1591,6 +1674,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi 0.3.9",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
+2
View File
@@ -18,6 +18,8 @@ anyhow = "1.0.71"
rfd = "0.11.3" rfd = "0.11.3"
bincode = "1.3.3" bincode = "1.3.3"
fs4 = "0.7.0" fs4 = "0.7.0"
simplelog = "0.12.1"
log = "0.4.20"
[dependencies.imgui] [dependencies.imgui]
version = "0.11.0" version = "0.11.0"
+2 -2
View File
@@ -1,8 +1,8 @@
3dobs TODOs: 3dobs TODOs:
- [x] Help menu - [x] Help menu
- [x] About window - [x] About window
- [ ] File logger - [x] File logger
- [ ] Logger should log to file, console and stdout - [x] Logger should log to file, console and stdout
- [x] Move console to be under objects - [x] Move console to be under objects
- [x] Don't have the viewport window be scrollable - [x] Don't have the viewport window be scrollable
- [x] Object rotation with left click + mouse movement (very rudimentary implementation, but works) - [x] Object rotation with left click + mouse movement (very rudimentary implementation, but works)
+6 -4
View File
@@ -1,5 +1,7 @@
use std::{io::{BufReader, BufRead}, collections::HashMap, path::PathBuf}; use std::{io::{BufReader, BufRead}, collections::HashMap, path::PathBuf};
use log::{error, warn, trace};
use crate::{mesh::Vertex, aabb::AABB, importer::ObjMesh, importer::Object, importer::Material}; use crate::{mesh::Vertex, aabb::AABB, importer::ObjMesh, importer::Object, importer::Material};
const BUF_CAP: usize = 1024 * 128; // 128 Kilobytes const BUF_CAP: usize = 1024 * 128; // 128 Kilobytes
@@ -140,7 +142,7 @@ fn parse_mtl(path: &PathBuf) -> Result<HashMap<String, Material>, Box<dyn std::e
Some(MtlToken::DiffuseTexture) => { Some(MtlToken::DiffuseTexture) => {
// TODO: textures // TODO: textures
} }
_ => { println!("Unhandled material token: {}", token) }, _ => { warn!("Unhandled material token: {}", token) },
} }
} }
} }
@@ -327,7 +329,7 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
materials.extend(m); materials.extend(m);
}, },
Err(e) => { Err(e) => {
eprintln!("Failed to parse mtl file {:?}: {}", material_path, e); error!("Failed to parse mtl file {:?}: {}", material_path, e);
} }
} }
} }
@@ -360,12 +362,12 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
Some(ObjToken::Line) | Some(ObjToken::Point) => { Some(ObjToken::Line) | Some(ObjToken::Point) => {
// we don't handle lines or points // we don't handle lines or points
} }
_ => { println!("Unhandled obj token: {}", token) }, _ => { warn!("Unhandled obj token: {}", token) },
} }
} }
} }
let elapsed = now.elapsed(); let elapsed = now.elapsed();
println!("Loaded in {}ms", elapsed.as_millis()); trace!("Loaded in {}ms", elapsed.as_millis());
let mesh_name = { let mesh_name = {
if current_mesh_name.is_empty() && !object_name.is_empty() { if current_mesh_name.is_empty() && !object_name.is_empty() {
+3 -1
View File
@@ -1,5 +1,7 @@
use std::io::{Read, Seek, BufReader, BufRead}; use std::io::{Read, Seek, BufReader, BufRead};
use log::trace;
use crate::{importer::ObjMesh, importer::Object, importer::Material, aabb::AABB, mesh::Vertex}; use crate::{importer::ObjMesh, importer::Object, importer::Material, aabb::AABB, mesh::Vertex};
const STL_HEADER_SIZE: u64 = 80; const STL_HEADER_SIZE: u64 = 80;
@@ -229,7 +231,7 @@ pub fn load_stl(mut file: std::fs::File) -> Result<Object, Box<dyn std::error::E
parse_binary_stl(file)? parse_binary_stl(file)?
}; };
let elapsed = now.elapsed(); let elapsed = now.elapsed();
println!("Loaded in {} ms", elapsed.as_millis()); trace!("Loaded in {} ms", elapsed.as_millis());
Ok(obj) Ok(obj)
} }
+2 -1
View File
@@ -1,6 +1,7 @@
use std::{os::unix::net::{UnixListener, UnixStream}, path::PathBuf, io::{Write, Read}, fs::File, process::exit, thread, sync::mpsc::Receiver}; use std::{os::unix::net::{UnixListener, UnixStream}, path::PathBuf, io::{Write, Read}, fs::File, process::exit, thread, sync::mpsc::Receiver};
use fs4::FileExt; use fs4::FileExt;
use log::error;
fn create_named_pipe(pipe_path: PathBuf) -> UnixListener { fn create_named_pipe(pipe_path: PathBuf) -> UnixListener {
if pipe_path.exists() { if pipe_path.exists() {
@@ -58,7 +59,7 @@ pub fn init(lock_file: &File, args_paths: Vec<PathBuf>, one_instance: bool) -> O
ipc_tx.send(paths).unwrap(); ipc_tx.send(paths).unwrap();
} }
Err(err) => { Err(err) => {
println!("Error: {:?}", err); error!("Error: {:?}", err);
break; break;
} }
} }
+1 -1
View File
@@ -8,7 +8,7 @@ pub mod utils;
pub mod mesh; pub mod mesh;
pub mod model; pub mod model;
pub mod ui; pub mod ui;
pub mod log; pub mod logger;
pub mod aabb; pub mod aabb;
pub mod importer; pub mod importer;
pub mod ipc; pub mod ipc;
-64
View File
@@ -1,64 +0,0 @@
#[derive(Clone)]
pub enum LogLevel {
Debug,
Info,
Warning,
Error,
}
impl From<LogLevel> for mint::Vector4<f32> {
fn from(level: LogLevel) -> Self {
match level {
LogLevel::Debug => [0.5, 0.5, 1.0, 1.0].into(),
LogLevel::Info => [0.5, 0.5, 0.5, 1.0].into(),
LogLevel::Warning => [1.0, 0.64, 0.0, 1.0].into(),
LogLevel::Error => [1.0, 0.0, 0.0, 1.0].into(),
}
}
}
#[derive(Clone)]
pub struct LogMessage {
pub level: LogLevel,
pub message: String,
}
impl LogMessage {
pub fn new(level: LogLevel, message: &str) -> Self {
let severity = match level {
LogLevel::Debug => "DEBUG",
LogLevel::Info => "INFO",
LogLevel::Warning => "WARNING",
LogLevel::Error => "ERROR",
};
Self {
level,
message: format!("[{}]: {}", severity, message),
}
}
}
pub struct Log {
pub history: Vec<LogMessage>,
}
impl Log {
pub fn clear(&mut self) {
self.history.clear();
}
pub fn log(&mut self, message: &str, level: LogLevel) {
// TODO: also write to a log file
self.history.push(LogMessage::new(level, message));
}
}
impl Default for Log {
fn default() -> Self {
Self {
history: Vec::new(),
}
}
}
+100
View File
@@ -0,0 +1,100 @@
use std::{io::Write, sync::{Arc, RwLock}};
#[derive(Copy, Clone)]
pub enum LogLevel {
Error,
Warn,
Info,
Debug,
}
impl From<LogLevel> for mint::Vector4<f32> {
fn from(level: LogLevel) -> Self {
match level {
LogLevel::Debug => [0.5, 0.5, 1.0, 1.0].into(),
LogLevel::Info => [0.5, 0.5, 0.5, 1.0].into(),
LogLevel::Warn => [1.0, 0.64, 0.0, 1.0].into(),
LogLevel::Error => [1.0, 0.0, 0.0, 1.0].into(),
}
}
}
impl From<log::LevelFilter> for LogLevel {
fn from(level: log::LevelFilter) -> Self {
match level {
log::LevelFilter::Debug => LogLevel::Debug,
log::LevelFilter::Info => LogLevel::Info,
log::LevelFilter::Warn => LogLevel::Warn,
log::LevelFilter::Error => LogLevel::Error,
_ => LogLevel::Debug,
}
}
}
pub struct LogMessage {
pub level: LogLevel,
pub message: String,
}
impl LogMessage {
pub fn new(level: LogLevel, message: &str) -> Self {
Self {
level,
message: format!("{}", message),
}
}
}
#[derive(Default)]
pub struct Log {
pub history: Vec<LogMessage>,
}
impl Log {
pub fn clear(&mut self) {
self.history.clear();
}
pub fn log(&mut self, message: &str, level: LogLevel) {
self.history.push(LogMessage::new(level, message));
}
}
#[derive(Clone)]
pub struct WritableLog {
pub arc: Arc<RwLock<Log>>,
buf: String
}
impl Default for WritableLog {
fn default() -> Self {
Self{arc: Arc::new(RwLock::new(Log::default())), buf: String::with_capacity(1024)}
}
}
impl Write for WritableLog {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buf.push_str(std::str::from_utf8(buf).unwrap());
if buf.contains(&b'\n') {
self.flush()?;
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
// match the log level found at index 0 till space to LogLevel
let level = match &self.buf[0..self.buf.find(' ').unwrap()] {
"[ERROR]" => LogLevel::Error,
"[WARN]" => LogLevel::Warn,
"[INFO]" => LogLevel::Info,
"[DEBUG]" => LogLevel::Debug,
_ => LogLevel::Info,
};
let mut logger = self.arc.write().unwrap();
logger.log(&self.buf, level);
self.buf.clear();
Ok(())
}
}
+40 -3
View File
@@ -1,13 +1,49 @@
use glfw::{Action, Context, Key, Modifiers};
use glad_gl::gl;
use anyhow;
use std::fs::File; use std::fs::File;
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use glfw::{Action, Context, Key, Modifiers};
use glad_gl::gl;
use anyhow;
use simplelog::*;
use threedobs::{shader, ui::ui, utils, ipc}; use threedobs::{shader, ui::ui, utils, ipc};
fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> { fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
let logger = threedobs::logger::WritableLog::default();
let log_conf = ConfigBuilder::default()
.set_target_level(LevelFilter::Error)
.set_thread_level(LevelFilter::Off)
.set_level_color(Level::Error, Some(Color::Red))
.set_level_color(Level::Debug, Some(Color::Rgb(128, 128, 255)))
.set_level_color(Level::Warn, Some(Color::Rgb(255, 163, 0)))
.set_level_color(Level::Info, Some(Color::Rgb(128, 128, 128)))
.build();
let in_program_log_conf = ConfigBuilder::default()
.set_target_level(LevelFilter::Off)
.set_time_level(LevelFilter::Off)
.set_thread_level(LevelFilter::Off)
.set_level_color(Level::Error, Some(Color::Red))
.set_level_color(Level::Debug, Some(Color::Rgb(128, 128, 255)))
.set_level_color(Level::Warn, Some(Color::Rgb(255, 255, 0)))
.set_level_color(Level::Info, Some(Color::Rgb(128, 128, 128)))
.build();
let log_level = if cfg!(debug_assertions) {
LevelFilter::Debug
} else {
LevelFilter::Info
};
CombinedLogger::init(
vec![
TermLogger::new(log_level, log_conf.clone(), TerminalMode::Mixed, ColorChoice::Auto),
WriteLogger::new(log_level, log_conf, File::create("3dobs.log")?),
WriteLogger::new(log_level, in_program_log_conf, logger.clone())
]
).unwrap();
let settings: ui::Settings = confy::load("3dobs", "settings")?; let settings: ui::Settings = confy::load("3dobs", "settings")?;
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
@@ -36,6 +72,7 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
let mut state = ui::State{ let mut state = ui::State{
settings, settings,
logger,
..Default::default() ..Default::default()
}; };
+5 -4
View File
@@ -1,5 +1,6 @@
use glad_gl::gl; use glad_gl::gl;
use anyhow::Result; use anyhow::Result;
use log::{debug, error};
pub struct ShaderSource { pub struct ShaderSource {
pub name: String, pub name: String,
@@ -26,7 +27,7 @@ impl Shader {
let mut success1 = 0; let mut success1 = 0;
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success1); gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success1);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("vertex shader {:?} compiled with status: {}", debug!("vertex shader {:?} compiled with status: {}",
vertex_obj.name, vertex_obj.name,
success1 success1
); );
@@ -34,7 +35,7 @@ impl Shader {
let info_buf = [0u8; 512]; let info_buf = [0u8; 512];
gl::GetShaderInfoLog(vertex_shader as u32, 512, std::ptr::null_mut(), info_buf.as_ptr() as *mut i8); gl::GetShaderInfoLog(vertex_shader as u32, 512, std::ptr::null_mut(), info_buf.as_ptr() as *mut i8);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("vertex shader info: {}", std::str::from_utf8(&info_buf).unwrap()); error!("vertex shader info: {}", std::str::from_utf8(&info_buf).unwrap());
} }
let frag_shader = gl::CreateShader(gl::FRAGMENT_SHADER); let frag_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
@@ -45,7 +46,7 @@ impl Shader {
let mut success2 = 0; let mut success2 = 0;
gl::GetShaderiv(frag_shader, gl::COMPILE_STATUS, &mut success2); gl::GetShaderiv(frag_shader, gl::COMPILE_STATUS, &mut success2);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("frag shader {:?} compiled with status: {}", debug!("frag shader {:?} compiled with status: {}",
frag_obj.name, frag_obj.name,
success2 success2
); );
@@ -53,7 +54,7 @@ impl Shader {
let info_buf2 = [0u8; 512]; let info_buf2 = [0u8; 512];
gl::GetShaderInfoLog(frag_shader as u32, 512, std::ptr::null_mut(), info_buf2.as_ptr() as *mut i8); gl::GetShaderInfoLog(frag_shader as u32, 512, std::ptr::null_mut(), info_buf2.as_ptr() as *mut i8);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("frag shader info: {}", std::str::from_utf8(&info_buf2).unwrap()); error!("frag shader info: {}", std::str::from_utf8(&info_buf2).unwrap());
} }
let shader_program = gl::CreateProgram(); let shader_program = gl::CreateProgram();
+16 -24
View File
@@ -1,9 +1,10 @@
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use glad_gl::gl; use glad_gl::gl;
use log::{info, debug};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use crate::{camera::Camera, model, imgui_glfw_support, imgui_opengl_renderer, mesh, ui, log, utils}; use crate::{camera::Camera, model, imgui_glfw_support, imgui_opengl_renderer, mesh, ui, logger, utils};
#[derive(Default, Debug, Serialize, Deserialize, Clone)] #[derive(Default, Debug, Serialize, Deserialize, Clone)]
pub struct Settings { pub struct Settings {
@@ -26,7 +27,7 @@ pub struct State {
pub camera: Camera, pub camera: Camera,
pub objects: Vec<model::Model>, pub objects: Vec<model::Model>,
pub viewport_size: [f32; 2], pub viewport_size: [f32; 2],
pub logger: log::Log, pub logger: logger::WritableLog,
pub settings: Settings, pub settings: Settings,
} }
@@ -48,7 +49,7 @@ impl Default for State {
camera: Camera::new(), camera: Camera::new(),
objects: vec![], objects: vec![],
viewport_size: [0.0, 0.0], viewport_size: [0.0, 0.0],
logger: log::Log::default(), logger: logger::WritableLog::default(),
settings: Settings::default(), settings: Settings::default(),
} }
} }
@@ -210,10 +211,7 @@ fn draw_object_hierarchy(ui: &imgui::Ui, state: &mut State, idx: usize) -> bool
ui.table_next_column(); ui.table_next_column();
if ui.small_button(format!("X###{}-{}", object.name.as_str(), idx)) { if ui.small_button(format!("X###{}-{}", object.name.as_str(), idx)) {
let output = format!("Removing object {}", object.name); info!("Removing object {}", object.name);
println!("{}", output);
state.logger.log(&output, log::LogLevel::Info);
return true; return true;
} }
if ui.checkbox("Selected", &mut (Some(state.objects[idx].id) == state.active_model)) { if ui.checkbox("Selected", &mut (Some(state.objects[idx].id) == state.active_model)) {
@@ -256,8 +254,9 @@ fn draw_console(ui: &imgui::Ui, state: &mut State) {
ui.child_window("###ConsoleHistory") ui.child_window("###ConsoleHistory")
.size([0.0, -27.0]) .size([0.0, -27.0])
.build(|| { .build(|| {
for line in state.logger.history.iter() { for line in state.logger.arc.read().unwrap().history.iter() {
let style = ui.push_style_color(imgui::StyleColor::Text, line.level.clone()); let style = ui.push_style_color(imgui::StyleColor::Text, line.level);
ui.text_wrapped(line.message.clone()); ui.text_wrapped(line.message.clone());
style.pop(); style.pop();
} }
@@ -268,7 +267,8 @@ fn draw_console(ui: &imgui::Ui, state: &mut State) {
ui.separator(); ui.separator();
if ui.button("Clear") { if ui.button("Clear") {
state.logger.clear(); let mut logger = state.logger.arc.write().unwrap();
logger.clear();
} }
}); });
} }
@@ -369,21 +369,13 @@ fn draw_viewport(ui: &imgui::Ui, state: &mut State, texture: u32) {
let _ = capture.save(save_path); let _ = capture.save(save_path);
let elapsed = now.elapsed(); let elapsed = now.elapsed();
state.logger.log( info!("Scene capture saved to: {} successfully", save_path
format!("Scene capture saved to: {} successfully", .canonicalize()
save_path .expect("Capture path to be canonicalized")
.canonicalize() .to_str()
.expect("Capture path to be canonicalized") .expect("Capture path to be valid unicode"));
.to_str()
.expect("Capture path to be valid unicode"))
.as_str(),
log::LogLevel::Info);
state.logger.log( debug!("Scene capture took: {}ms", elapsed.as_millis());
format!("Scene capture took: {}ms",
elapsed.as_millis())
.as_str(),
log::LogLevel::Debug);
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
+7 -11
View File
@@ -3,8 +3,9 @@ use std::path::PathBuf;
use glad_gl::gl; use glad_gl::gl;
use glm; use glm;
use anyhow::{Result, Context}; use anyhow::{Result, Context};
use ::log::{info, error};
use crate::{log, model, ui, importer}; use crate::{model, ui, importer};
pub enum SupportedFileExtensions { pub enum SupportedFileExtensions {
OBJ, OBJ,
@@ -66,18 +67,18 @@ pub fn import_models_from_paths(paths: &Vec<PathBuf>, state: &mut ui::ui::State)
for model_path in paths { for model_path in paths {
let filename = model_path.file_name(); let filename = model_path.file_name();
if model_path.is_dir() { if model_path.is_dir() {
state.logger.log(&format!("Skipping directory \"{}\"", filename.unwrap().to_str().unwrap()), log::LogLevel::Info); info!("Skipping directory \"{}\"", filename.unwrap().to_str().unwrap());
continue; continue;
} }
match model_path.extension() { match model_path.extension() {
Some(ext) => { Some(ext) => {
if SupportedFileExtensions::from_str(ext.to_str().unwrap()).is_none() { if SupportedFileExtensions::from_str(ext.to_str().unwrap()).is_none() {
state.logger.log(&format!("Skipping file \"{}\" because it is not an OBJ or STL file", filename.unwrap().to_str().unwrap()), log::LogLevel::Info); info!("Skipping file \"{}\" because it is not an OBJ or STL file", filename.unwrap().to_str().unwrap());
continue; continue;
} }
}, },
None => { None => {
state.logger.log(&format!("Skipping file \"{}\" because it has no extension", filename.unwrap().to_str().unwrap()), log::LogLevel::Info); info!("Skipping file \"{}\" because it has no extension", filename.unwrap().to_str().unwrap());
continue; continue;
} }
} }
@@ -88,19 +89,14 @@ pub fn import_models_from_paths(paths: &Vec<PathBuf>, state: &mut ui::ui::State)
state.active_model = Some(m.id); state.active_model = Some(m.id);
if let Some(model_name) = filename { if let Some(model_name) = filename {
let msg = format!("Loaded model \"{}\"", model_name.to_str().unwrap()); info!("Loaded model \"{}\"", model_name.to_str().unwrap());
println!("{}", msg);
state.logger.log(&msg, log::LogLevel::Info);
m.name = model_name.to_str().unwrap().to_string(); m.name = model_name.to_str().unwrap().to_string();
} }
state.objects.push(m); state.objects.push(m);
state.camera.focus_on_selected_model(state.active_model, &state.objects); state.camera.focus_on_selected_model(state.active_model, &state.objects);
}, },
Err(e) => { Err(e) => {
let error = format!("Error loading model \"{}\": {}", model_path.to_str().unwrap(), e); error!("Error loading model \"{}\": {}", model_path.to_str().unwrap(), e);
println!("{}", error);
state.logger.log(&error, log::LogLevel::Error);
} }
} }
} }