mirror of
https://github.com/IllusionMan1212/3dobs.git
synced 2026-10-24 10:12:35 +00:00
only allow one instance of the program and use IPC to load models from other instances
This commit is contained in:
Generated
+54
-8
@@ -37,7 +37,7 @@ dependencies = [
|
|||||||
"log 0.4.20",
|
"log 0.4.20",
|
||||||
"parking",
|
"parking",
|
||||||
"polling",
|
"polling",
|
||||||
"rustix",
|
"rustix 0.37.25",
|
||||||
"slab",
|
"slab",
|
||||||
"socket2",
|
"socket2",
|
||||||
"waker-fn",
|
"waker-fn",
|
||||||
@@ -70,6 +70,15 @@ 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 = "bincode"
|
||||||
|
version = "1.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
@@ -82,6 +91,12 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block"
|
name = "block"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@@ -316,6 +331,16 @@ dependencies = [
|
|||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs4"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7"
|
||||||
|
dependencies = [
|
||||||
|
"rustix 0.38.20",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-cprng"
|
name = "fuchsia-cprng"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -433,7 +458,7 @@ version = "0.51.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "919ebc7bdbf60a529689a5e58f80d9dcde27e3d2ab4f2f7ce711ec439fe789c5"
|
checksum = "919ebc7bdbf60a529689a5e58f80d9dcde27e3d2ab4f2f7ce711ec439fe789c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"glfw-sys",
|
"glfw-sys",
|
||||||
"objc",
|
"objc",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
@@ -551,7 +576,7 @@ version = "0.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "122d677d0efcd64ca15f12907beaf46b26bbd2cdc855ee5b227f29cf50f75bb5"
|
checksum = "122d677d0efcd64ca15f12907beaf46b26bbd2cdc855ee5b227f29cf50f75bb5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"imgui-sys",
|
"imgui-sys",
|
||||||
"mint",
|
"mint",
|
||||||
@@ -646,6 +671,12 @@ version = "0.3.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.10"
|
version = "0.4.10"
|
||||||
@@ -909,7 +940,7 @@ version = "0.17.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
|
checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"fdeflate",
|
"fdeflate",
|
||||||
"flate2",
|
"flate2",
|
||||||
@@ -923,7 +954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1049,7 +1080,7 @@ version = "0.3.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1108,11 +1139,24 @@ version = "0.37.25"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035"
|
checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"errno",
|
"errno",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys 0.3.8",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys 0.4.10",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1245,6 +1289,8 @@ name = "threedobs"
|
|||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"bincode",
|
||||||
|
"fs4",
|
||||||
"glad-gl",
|
"glad-gl",
|
||||||
"glfw",
|
"glfw",
|
||||||
"glm",
|
"glm",
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ glm = "0.2.3"
|
|||||||
mint = "0.5.9"
|
mint = "0.5.9"
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.71"
|
||||||
rfd = "0.11.3"
|
rfd = "0.11.3"
|
||||||
|
bincode = "1.3.3"
|
||||||
|
fs4 = "0.7.0"
|
||||||
|
|
||||||
[dependencies.imgui]
|
[dependencies.imgui]
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
- [x] Smaller console area
|
- [x] Smaller console area
|
||||||
- [ ] Better object rotation
|
- [ ] Better object rotation
|
||||||
- [ ] Ability to change rotation pivot point (needs raycasting and shit)
|
- [ ] Ability to change rotation pivot point (needs raycasting and shit)
|
||||||
- [ ] 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)
|
- [ ] Config for consistent settings between restarts (home dir preferred)
|
||||||
@@ -27,9 +27,10 @@
|
|||||||
- 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
|
||||||
- [ ] Have the program accept model files as CLI args
|
- [x] Have the program accept model files as CLI args
|
||||||
- [ ] 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
|
||||||
- [ ] Show how many memory each loaded model is using
|
- [ ] Toggle for dis/allowing the one instance option
|
||||||
|
- [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
|
||||||
|
|
||||||
- [ ] Bring back the regular camera movement (can maybe be a switch between them) (for later)
|
- [ ] Bring back the regular camera movement (can maybe be a switch between them) (for later)
|
||||||
|
|||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
use std::{os::unix::net::{UnixListener, UnixStream}, path::PathBuf, io::{Write, Read}, fs::File, process::exit, thread, sync::mpsc::Receiver};
|
||||||
|
|
||||||
|
use fs4::FileExt;
|
||||||
|
|
||||||
|
fn create_named_pipe(pipe_path: PathBuf) -> UnixListener {
|
||||||
|
if pipe_path.exists() {
|
||||||
|
// Remove the existing pipe if it exists.
|
||||||
|
std::fs::remove_file(&pipe_path).expect("Failed to remove existing pipe");
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener = UnixListener::bind(&pipe_path).expect("Failed to create named pipe");
|
||||||
|
|
||||||
|
listener
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_args_to_existing_instance(pipe_path: PathBuf, args_paths: Vec<PathBuf>) {
|
||||||
|
let mut stream = UnixStream::connect(pipe_path).expect("Failed to connect to named pipe");
|
||||||
|
let data = bincode::serialize(&args_paths).expect("Failed to serialize arguments");
|
||||||
|
|
||||||
|
// Send the arguments to the first instance.
|
||||||
|
stream
|
||||||
|
.write_all(&data)
|
||||||
|
.expect("Failed to send arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(lock_file: &File, args_paths: Vec<PathBuf>) -> Receiver<Vec<PathBuf>> {
|
||||||
|
let pipe_name = "3dobs_pipe";
|
||||||
|
|
||||||
|
let pipe_path = std::env::temp_dir().join(pipe_name);
|
||||||
|
|
||||||
|
match lock_file.try_lock_exclusive() {
|
||||||
|
Ok(_) => {},
|
||||||
|
Err(_) => {
|
||||||
|
println!("An instance of the program is already running");
|
||||||
|
send_args_to_existing_instance(pipe_path, args_paths);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let pipe = create_named_pipe(pipe_path);
|
||||||
|
let (ipc_tx, ipc_rx) = std::sync::mpsc::channel::<Vec<PathBuf>>();
|
||||||
|
|
||||||
|
// thread is not joined because it blocks anyway
|
||||||
|
// and there's no cleanup to do or anything
|
||||||
|
let _ = thread::spawn(move || {
|
||||||
|
for stream in pipe.incoming() {
|
||||||
|
match stream {
|
||||||
|
Ok(mut stream) => {
|
||||||
|
let mut serialized_paths = Vec::new();
|
||||||
|
let _ = stream.read_to_end(&mut serialized_paths);
|
||||||
|
|
||||||
|
let paths: Vec<PathBuf> = bincode::deserialize(&serialized_paths).unwrap();
|
||||||
|
|
||||||
|
ipc_tx.send(paths).unwrap();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error: {:?}", err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipc_rx
|
||||||
|
}
|
||||||
@@ -11,3 +11,4 @@ pub mod ui;
|
|||||||
pub mod log;
|
pub mod log;
|
||||||
pub mod aabb;
|
pub mod aabb;
|
||||||
pub mod importer;
|
pub mod importer;
|
||||||
|
pub mod ipc;
|
||||||
|
|||||||
+33
-11
@@ -1,11 +1,25 @@
|
|||||||
use glfw::{Action, Context, Key, Modifiers};
|
use glfw::{Action, Context, Key, Modifiers};
|
||||||
use glad_gl::gl;
|
use glad_gl::gl;
|
||||||
use anyhow;
|
use anyhow;
|
||||||
|
use std::fs::File;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use threedobs::{shader, ui::ui, utils};
|
|
||||||
|
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 args: Vec<String> = env::args().collect();
|
||||||
|
let args_paths: Vec<PathBuf> = args
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.map(|arg| std::fs::canonicalize(PathBuf::from(arg)).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let lock_file_name = "3dobs.lock";
|
||||||
|
let lock_file_path = std::env::temp_dir().join(lock_file_name);
|
||||||
|
let lock_file = File::create(&lock_file_path)?;
|
||||||
|
let ipc_rx = ipc::init(&lock_file, args_paths.clone());
|
||||||
|
|
||||||
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)?;
|
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS)?;
|
||||||
|
|
||||||
glfw::WindowHint::ContextVersion(3, 3);
|
glfw::WindowHint::ContextVersion(3, 3);
|
||||||
@@ -184,15 +198,8 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let scene_fb = create_scene_framebuffer();
|
let scene_fb = create_scene_framebuffer();
|
||||||
|
|
||||||
// Import models from launch arguments
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
let paths: Vec<PathBuf> = args
|
utils::import_models_from_paths(&args_paths, &mut state);
|
||||||
.iter()
|
|
||||||
.skip(1)
|
|
||||||
.map(|arg| PathBuf::from(arg))
|
|
||||||
.collect();
|
|
||||||
utils::import_models_from_paths(&paths, &mut state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
@@ -209,6 +216,21 @@ 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() {
|
||||||
|
Ok(paths) => {
|
||||||
|
window.focus();
|
||||||
|
utils::import_models_from_paths(&paths, &mut state);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
match e {
|
||||||
|
std::sync::mpsc::TryRecvError::Empty => {},
|
||||||
|
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
|
||||||
// we need to handle window events first to have an updated
|
// we need to handle window events first to have an updated
|
||||||
@@ -236,10 +258,10 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
|
|||||||
state.camera.move_camera(xoffset, yoffset);
|
state.camera.move_camera(xoffset, yoffset);
|
||||||
} else {
|
} else {
|
||||||
if let Some(active_model) = state.active_model {
|
if let Some(active_model) = state.active_model {
|
||||||
let model = state.objects.iter_mut().find(|m| m.id == active_model).unwrap();
|
|
||||||
// let x_rotation = glm::quat_angle_axis(xoffset * state.camera.sensitivity, &state.camera.up);
|
|
||||||
let x_rotation = xoffset * state.camera.sensitivity * state.rotation_speed;
|
let x_rotation = xoffset * state.camera.sensitivity * state.rotation_speed;
|
||||||
let y_rotation = yoffset * state.camera.sensitivity * state.rotation_speed;
|
let y_rotation = yoffset * state.camera.sensitivity * state.rotation_speed;
|
||||||
|
let model = state.objects.iter_mut().find(|m| m.id == active_model).unwrap();
|
||||||
|
// let x_rotation = glm::quat_angle_axis(xoffset * state.camera.sensitivity, &state.camera.up);
|
||||||
model.rotate(x_rotation, y_rotation);
|
model.rotate(x_rotation, y_rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user