settings/ui: add consistent config and settings window. add toggleable single instance option

This commit is contained in:
2023-10-24 03:14:19 +02:00
parent 54cac634e8
commit 23e127e908
6 changed files with 184 additions and 19 deletions
Generated
+113 -1
View File
@@ -70,6 +70,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
[[package]] [[package]]
name = "bincode" name = "bincode"
version = "1.3.3" version = "1.3.3"
@@ -96,6 +102,9 @@ name = "bitflags"
version = "2.4.1" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "block" name = "block"
@@ -186,6 +195,18 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "confy"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e37668cb35145dcfaa1931a5f37fde375eeae8068b4c0d2f289da28a270b2d2c"
dependencies = [
"directories",
"ron",
"serde",
"thiserror",
]
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.3.2" version = "1.3.2"
@@ -234,6 +255,26 @@ 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 = "directories"
version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "dispatch" name = "dispatch"
version = "0.2.0" version = "0.2.0"
@@ -425,6 +466,17 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]] [[package]]
name = "gif" name = "gif"
version = "0.12.0" version = "0.12.0"
@@ -911,7 +963,7 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"redox_syscall", "redox_syscall 0.3.5",
"smallvec", "smallvec",
"windows-targets 0.48.5", "windows-targets 0.48.5",
] ]
@@ -1074,6 +1126,15 @@ dependencies = [
"rand_core 0.3.1", "rand_core 0.3.1",
] ]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags 1.3.2",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.3.5" version = "0.3.5"
@@ -1083,6 +1144,17 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]]
name = "redox_users"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall 0.2.16",
"thiserror",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "0.1.80" version = "0.1.80"
@@ -1127,6 +1199,18 @@ dependencies = [
"windows", "windows",
] ]
[[package]]
name = "ron"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64",
"bitflags 2.4.1",
"serde",
"serde_derive",
]
[[package]] [[package]]
name = "rustc-serialize" name = "rustc-serialize"
version = "0.3.24" version = "0.3.24"
@@ -1265,6 +1349,26 @@ 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 = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "thread-id" name = "thread-id"
version = "2.0.0" version = "2.0.0"
@@ -1290,6 +1394,7 @@ version = "0.1.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"confy",
"fs4", "fs4",
"glad-gl", "glad-gl",
"glfw", "glfw",
@@ -1298,6 +1403,7 @@ dependencies = [
"imgui", "imgui",
"mint", "mint",
"rfd", "rfd",
"serde",
] ]
[[package]] [[package]]
@@ -1369,6 +1475,12 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.87" version = "0.2.87"
+9
View File
@@ -22,3 +22,12 @@ fs4 = "0.7.0"
[dependencies.imgui] [dependencies.imgui]
version = "0.11.0" version = "0.11.0"
features = ["docking", "tables-api"] features = ["docking", "tables-api"]
[dependencies.confy]
version = "0.5.1"
features = ["ron_conf"]
default-features = false
[dependencies.serde]
version = "1.0.189"
features = ["derive"]
+2 -2
View File
@@ -22,14 +22,14 @@
- [x] There might be memory leaks somewhere (tracked it down to russimp, will have to write my own .obj and .stl readers) - [x] There might be memory leaks somewhere (tracked it down to russimp, will have to write my own .obj and .stl readers)
- [x] Reset object rotation when changing active model - [x] Reset object rotation when changing active model
- [x] Drag'n'Drop models - [x] Drag'n'Drop models
- [ ] Config for consistent settings between restarts (home dir preferred) - [x] Config for consistent settings between restarts (home dir preferred)
- [x] (BUG) when removing a model that's not selected and the selected model is not the last, we select the last one - [x] (BUG) when removing a model that's not selected and the selected model is not the last, we select the last one
- only select the last one if we removed the selected model - only select the last one if we removed the selected model
- [x] Use filename for the root node - [x] Use filename for the root node
- [x] Ship shaders directly in the executable - [x] Ship shaders directly in the executable
- [x] Have the program accept model files as CLI args - [x] Have the program accept model files as CLI args
- [x] Have it so that when an instance of 3dobs is open, any other file associated with 3dobs is opened in the same instance - [x] Have it so that when an instance of 3dobs is open, any other file associated with 3dobs is opened in the same instance
- [ ] Toggle for dis/allowing the one instance option - [x] Toggle for dis/allowing the one instance option
- [x] Show how much memory each loaded model is using - [x] Show how much memory each loaded model is using
- [ ] Move the invisible point lights to be around selected object from all sides so it's nicely illuminated - [ ] Move the invisible point lights to be around selected object from all sides so it's nicely illuminated
+6 -2
View File
@@ -23,7 +23,11 @@ fn send_args_to_existing_instance(pipe_path: PathBuf, args_paths: Vec<PathBuf>)
.expect("Failed to send arguments"); .expect("Failed to send arguments");
} }
pub fn init(lock_file: &File, args_paths: Vec<PathBuf>) -> Receiver<Vec<PathBuf>> { pub fn init(lock_file: &File, args_paths: Vec<PathBuf>, one_instance: bool) -> Option<Receiver<Vec<PathBuf>>> {
if !one_instance {
return None;
}
let pipe_name = "3dobs_pipe"; let pipe_name = "3dobs_pipe";
let pipe_path = std::env::temp_dir().join(pipe_name); let pipe_path = std::env::temp_dir().join(pipe_name);
@@ -61,5 +65,5 @@ pub fn init(lock_file: &File, args_paths: Vec<PathBuf>) -> Receiver<Vec<PathBuf>
} }
}); });
ipc_rx Some(ipc_rx)
} }
+20 -12
View File
@@ -8,6 +8,8 @@ use std::path::PathBuf;
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 settings: ui::Settings = confy::load("3dobs", "settings")?;
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let args_paths: Vec<PathBuf> = args let args_paths: Vec<PathBuf> = args
.iter() .iter()
@@ -18,7 +20,7 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
let lock_file_name = "3dobs.lock"; let lock_file_name = "3dobs.lock";
let lock_file_path = std::env::temp_dir().join(lock_file_name); let lock_file_path = std::env::temp_dir().join(lock_file_name);
let lock_file = File::create(&lock_file_path)?; let lock_file = File::create(&lock_file_path)?;
let ipc_rx = ipc::init(&lock_file, args_paths.clone()); let ipc_rx = ipc::init(&lock_file, args_paths.clone(), settings.one_instance);
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)?; let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)?;
@@ -32,7 +34,10 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
window.set_cursor_mode(glfw::CursorMode::Disabled); window.set_cursor_mode(glfw::CursorMode::Disabled);
window.make_current(); window.make_current();
let mut state = ui::State::default(); let mut state = ui::State{
settings,
..Default::default()
};
glfw.set_swap_interval(glfw::SwapInterval::Sync(1)); glfw.set_swap_interval(glfw::SwapInterval::Sync(1));
@@ -128,20 +133,23 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
let view_mat = glm::ext::look_at(state.camera.position, state.camera.position + state.camera.front, state.camera.up); let view_mat = glm::ext::look_at(state.camera.position, state.camera.position + state.camera.front, state.camera.up);
let projection_mat = glm::ext::perspective(glm::radians(state.camera.fov), state.viewport_size[0] / state.viewport_size[1], 0.01, 200.0); let projection_mat = glm::ext::perspective(glm::radians(state.camera.fov), state.viewport_size[0] / state.viewport_size[1], 0.01, 200.0);
match ipc_rx.try_recv() { if let Some(rx) = &ipc_rx {
Ok(paths) => { match rx.try_recv() {
window.focus(); Ok(paths) => {
utils::import_models_from_paths(&paths, &mut state); window.focus();
}, utils::import_models_from_paths(&paths, &mut state);
Err(e) => { },
match e { Err(e) => {
std::sync::mpsc::TryRecvError::Empty => {}, match e {
std::sync::mpsc::TryRecvError::Disconnected => { std::sync::mpsc::TryRecvError::Empty => {},
panic!("Error: IPC thread channel disconnected"); std::sync::mpsc::TryRecvError::Disconnected => {
panic!("Error: IPC thread channel disconnected");
}
} }
} }
} }
} }
for (_, event) in glfw::flush_messages(&events) { for (_, event) in glfw::flush_messages(&events) {
// order of handling events is important here // order of handling events is important here
+34 -2
View File
@@ -1,13 +1,20 @@
use std::time::{SystemTime, UNIX_EPOCH};
use glad_gl::gl; use glad_gl::gl;
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, log, utils};
use std::time::{SystemTime, UNIX_EPOCH}; #[derive(Default, Debug, Serialize, Deserialize, Clone)]
pub struct Settings {
pub one_instance: bool,
}
pub struct State { pub struct State {
pub active_model: Option<u32>, pub active_model: Option<u32>,
pub show_console: bool, pub show_console: bool,
pub show_help_menu_about: bool, pub show_help_menu_about: bool,
pub show_settings: bool,
pub is_cursor_captured: bool, pub is_cursor_captured: bool,
pub can_capture_cursor: bool, pub can_capture_cursor: bool,
pub draw_grid: bool, pub draw_grid: bool,
@@ -20,6 +27,7 @@ pub struct State {
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: log::Log,
pub settings: Settings,
} }
impl Default for State { impl Default for State {
@@ -27,6 +35,8 @@ impl Default for State {
Self { Self {
active_model: None, active_model: None,
show_console: false, show_console: false,
show_help_menu_about: false,
show_settings: false,
first_frame_drawn: false, first_frame_drawn: false,
is_cursor_captured: false, is_cursor_captured: false,
can_capture_cursor: false, can_capture_cursor: false,
@@ -34,12 +44,12 @@ impl Default for State {
draw_aabb: false, draw_aabb: false,
fov_zoom: true, fov_zoom: true,
rotation_speed: 1.0, rotation_speed: 1.0,
show_help_menu_about: false,
wireframe: false, wireframe: false,
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: log::Log::default(),
settings: Settings::default(),
} }
} }
} }
@@ -102,6 +112,9 @@ pub fn draw_main_menu_bar(ui: &imgui::Ui, state: &mut State, window: &mut glfw::
if ui.menu_item_config("Import Model(s)").shortcut("Ctrl+O").build() { if ui.menu_item_config("Import Model(s)").shortcut("Ctrl+O").build() {
import_model(state); import_model(state);
} }
if ui.menu_item_config("Settings").build() {
state.show_settings = !state.show_settings;
}
if ui.menu_item_config("Quit").shortcut("Ctrl+Q").build() { if ui.menu_item_config("Quit").shortcut("Ctrl+Q").build() {
window.set_should_close(true); window.set_should_close(true);
} }
@@ -124,6 +137,24 @@ pub fn draw_main_menu_bar(ui: &imgui::Ui, state: &mut State, window: &mut glfw::
}); });
} }
pub fn draw_settings_window(ui: &imgui::Ui, state: &mut State) {
if !state.show_settings {
return;
}
let display_size = ui.io().display_size;
ui.window("Settings")
.size([500.0, 100.0], imgui::Condition::FirstUseEver)
.opened(&mut state.show_settings)
.position([display_size[0] / 2.0, display_size[1] / 2.0], imgui::Condition::FirstUseEver)
.position_pivot([0.5, 0.5])
.build(|| {
if ui.checkbox("Only allow one program instance (Reboot required when enabling)", &mut state.settings.one_instance) {
confy::store("3dobs", "settings", state.settings.clone()).unwrap();
}
});
}
fn draw_transformations(ui: &imgui::Ui, mesh: &mut mesh::Mesh) { fn draw_transformations(ui: &imgui::Ui, mesh: &mut mesh::Mesh) {
imgui::Drag::new("###XPos") imgui::Drag::new("###XPos")
.range(f32::NEG_INFINITY, f32::INFINITY) .range(f32::NEG_INFINITY, f32::INFINITY)
@@ -428,6 +459,7 @@ pub fn draw_ui(
draw_viewport(ui, state, scene_fb_texture); draw_viewport(ui, state, scene_fb_texture);
draw_objects_window(ui, state); draw_objects_window(ui, state);
draw_console(ui, state); draw_console(ui, state);
draw_settings_window(ui, state);
ui.end_frame_early(); ui.end_frame_early();