Merge pull request 'Improve rendering and reduce rendering related crashes' from error_handling into main
This commit is contained in:
commit
43b8e75ad7
14 changed files with 1240 additions and 484 deletions
|
@ -1 +1,4 @@
|
|||
[alias]
|
||||
|
||||
[build]
|
||||
rustflags = ["-Ctarget-cpu=native"]
|
||||
|
|
243
Cargo.lock
generated
243
Cargo.lock
generated
|
@ -43,7 +43,7 @@ dependencies = [
|
|||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
"zerocopy 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -112,6 +112,15 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.9"
|
||||
|
@ -315,7 +324,7 @@ version = "0.18.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"approx 0.4.0",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
|
@ -443,6 +452,34 @@ dependencies = [
|
|||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
|
@ -523,6 +560,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "endian-type"
|
||||
version = "0.1.2"
|
||||
|
@ -752,6 +795,44 @@ dependencies = [
|
|||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glyph_brush"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0060f4ed4ef64a5876d9836d7d6c9ed43a463f3ca431682bec1c326064c8c93e"
|
||||
dependencies = [
|
||||
"glyph_brush_draw_cache",
|
||||
"glyph_brush_layout",
|
||||
"ordered-float 5.0.0",
|
||||
"rustc-hash 2.1.1",
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glyph_brush_draw_cache"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb6c910def52365fef3f439a6b50a4d5c11b28eec4cf6c191f6dfea18e88d7f"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"linked-hash-map",
|
||||
"rayon",
|
||||
"rustc-hash 2.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glyph_brush_layout"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1e288bfd2f6c0313f78bf5aa538356ad481a3bb97e9b7f93220ab0066c5992"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"approx 0.5.1",
|
||||
"xi-unicode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpu-alloc"
|
||||
version = "0.6.0"
|
||||
|
@ -1111,6 +1192,12 @@ dependencies = [
|
|||
"redox_syscall 0.5.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.15"
|
||||
|
@ -1213,7 +1300,7 @@ dependencies = [
|
|||
"hexf-parse",
|
||||
"indexmap",
|
||||
"log",
|
||||
"rustc-hash",
|
||||
"rustc-hash 1.1.0",
|
||||
"spirv",
|
||||
"strum",
|
||||
"termcolor",
|
||||
|
@ -1566,6 +1653,15 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
@ -1669,6 +1765,15 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "presser"
|
||||
version = "0.3.1"
|
||||
|
@ -1727,6 +1832,36 @@ dependencies = [
|
|||
"nibble_vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "range-alloc"
|
||||
version = "0.1.4"
|
||||
|
@ -1739,6 +1874,26 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
|
@ -1815,6 +1970,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.44"
|
||||
|
@ -2188,6 +2349,16 @@ dependencies = [
|
|||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tobj"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04aca6092e5978e708ee784e8ab9b5cf3cdb598b28f99a2f257446e7081a7025"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.44.1"
|
||||
|
@ -2195,6 +2366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"tokio-macros",
|
||||
|
@ -2291,6 +2463,21 @@ version = "0.25.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
||||
|
||||
[[package]]
|
||||
name = "twox-hash"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7b17f197b3050ba473acf9181f7b1d3b66d1cf7356c6cc57886662276e65908"
|
||||
dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
|
@ -2628,7 +2815,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"profiling",
|
||||
"raw-window-handle",
|
||||
"rustc-hash",
|
||||
"rustc-hash 1.1.0",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"wgpu-hal",
|
||||
|
@ -2665,13 +2852,13 @@ dependencies = [
|
|||
"ndk-sys 0.5.0+25.2.9519653",
|
||||
"objc",
|
||||
"once_cell",
|
||||
"ordered-float",
|
||||
"ordered-float 4.6.0",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"renderdoc-sys",
|
||||
"rustc-hash",
|
||||
"rustc-hash 1.1.0",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"wasm-bindgen",
|
||||
|
@ -2693,6 +2880,18 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu_text"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccd192487eb81eb51f8f0eb82fea0865e71ab4f002f7942bee0bba04fc2a0b8c"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"glyph_brush",
|
||||
"log",
|
||||
"wgpu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -3119,6 +3318,12 @@ version = "0.3.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61"
|
||||
|
||||
[[package]]
|
||||
name = "xi-unicode"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a"
|
||||
|
||||
[[package]]
|
||||
name = "xkbcommon-dl"
|
||||
version = "0.4.2"
|
||||
|
@ -3181,6 +3386,7 @@ dependencies = [
|
|||
name = "zenyx"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
"backtrace",
|
||||
"bytemuck",
|
||||
|
@ -3196,10 +3402,13 @@ dependencies = [
|
|||
"regex",
|
||||
"rustyline",
|
||||
"thiserror 2.0.12",
|
||||
"tobj",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"typenum",
|
||||
"wgpu",
|
||||
"wgpu_text",
|
||||
"winit",
|
||||
]
|
||||
|
||||
|
@ -3209,7 +3418,16 @@ version = "0.7.35"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3223,6 +3441,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.6"
|
||||
|
|
39
Cargo.toml
39
Cargo.toml
|
@ -2,41 +2,16 @@
|
|||
resolver = "2"
|
||||
members = ["engine","subcrates/zen_core"]
|
||||
|
||||
[profile.dev]
|
||||
|
||||
rpath = false
|
||||
panic = "abort"
|
||||
lto = "off"
|
||||
opt-level = 0
|
||||
debug = false
|
||||
overflow-checks = false
|
||||
incremental = true
|
||||
codegen-units = 512
|
||||
|
||||
|
||||
strip = "symbols"
|
||||
debug-assertions = true
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 0
|
||||
debug = false
|
||||
overflow-checks = false
|
||||
incremental = true
|
||||
codegen-units = 512
|
||||
|
||||
|
||||
strip = "symbols"
|
||||
debug-assertions = true
|
||||
[profile.dev.build-override]
|
||||
opt-level = 0
|
||||
debug = false
|
||||
overflow-checks = false
|
||||
incremental = true
|
||||
codegen-units = 512
|
||||
|
||||
[workspace.dependencies]
|
||||
lazy_static = "1.5.0"
|
||||
parking_lot = "0.12.3"
|
||||
|
||||
[profile.release]
|
||||
debug-assertions = false
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
split-debuginfo = "off"
|
||||
|
||||
[profile.dev]
|
||||
debug = 0
|
||||
|
|
|
@ -40,7 +40,6 @@ in
|
|||
doCheck = false;
|
||||
LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath buildInputs}";
|
||||
|
||||
|
||||
fixupPhase = ''
|
||||
wrapProgram $out/bin/${pname} --set PATH ${bash}/bin:\$PATH --set LD_LIBRARY_PATH ${pkgs.lib.makeLibraryPath buildInputs}
|
||||
'';
|
||||
|
|
|
@ -3,32 +3,42 @@ name = "zenyx"
|
|||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
repository = "https://github.com/Zenyx-Engine/Zenyx"
|
||||
|
||||
[dependencies]
|
||||
# TBR
|
||||
anyhow = "1.0.94"
|
||||
# TBR (if possible)
|
||||
backtrace = "0.3.74"
|
||||
# TBR (if possible)
|
||||
chrono = "0.4.39"
|
||||
colored = "3.0.0"
|
||||
# TBR (if possible)
|
||||
crashreport = "1.0.1"
|
||||
# TBR
|
||||
dirs-next = "2.0.0"
|
||||
|
||||
# TBR == (To be removed)
|
||||
# TBR
|
||||
lazy_static.workspace = true
|
||||
# TBR
|
||||
once_cell = "1.21.1"
|
||||
parking_lot.workspace = true
|
||||
# TBR (if possible)
|
||||
regex = "1.11.1"
|
||||
# TBR (if possible)
|
||||
rustyline = { version = "15.0.0", features = ["derive", "rustyline-derive"] }
|
||||
thiserror = "2.0.11"
|
||||
tokio = { version = "1.44.1", features = ["macros", "parking_lot","rt-multi-thread"] }
|
||||
# Tokio is heavy but so far its the best option, we should make better use of it or switch to another runtime.
|
||||
tokio = { version = "1.44.1", features = ["fs", "macros", "parking_lot", "rt-multi-thread"] }
|
||||
wgpu = "24.0.3"
|
||||
winit = "0.30.9"
|
||||
bytemuck = "1.21.0"
|
||||
# TBR (if possible)
|
||||
futures = "0.3.31"
|
||||
cgmath = "0.18.0"
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = "0.3.19"
|
||||
|
||||
|
||||
[profile.dev]
|
||||
debug-assertions = true
|
||||
|
||||
[profile.release]
|
||||
debug-assertions = false
|
||||
# TBR
|
||||
typenum = { version = "1.18.0", features = ["const-generics"] }
|
||||
tobj = { version = "4.0.3", features = ["tokio"] }
|
||||
ahash = "0.8.11"
|
||||
wgpu_text = "0.9.2"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::error::Error;
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::mem;
|
||||
|
||||
|
@ -8,50 +9,43 @@ use regex::Regex;
|
|||
static INIT: parking_lot::Once = Once::new();
|
||||
|
||||
pub fn set_panic_hook() {
|
||||
use std::io::Write;
|
||||
|
||||
use colored::Colorize;
|
||||
|
||||
use crate::workspace;
|
||||
|
||||
INIT.call_once(|| {
|
||||
let default_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |info| {
|
||||
let log_path = workspace::get_working_dir().unwrap_or_else(|_| {
|
||||
if let Err(e) = process_panic(info) {
|
||||
eprintln!("Error in panic hook: {}", e);
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
if !log_path.exists() {
|
||||
std::fs::create_dir_all(&log_path).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
}
|
||||
let log_path = log_path.join("panic.log");
|
||||
std::process::exit(0);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
let mut file = std::fs::File::create(&log_path).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
let payload = info.payload();
|
||||
let payload_str = if let Some(s) = payload.downcast_ref::<&str>() {
|
||||
*s
|
||||
} else if let Some(s) = payload.downcast_ref::<String>() {
|
||||
s
|
||||
} else {
|
||||
"<non-string panic payload>"
|
||||
};
|
||||
fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Error>> {
|
||||
use crate::workspace;
|
||||
use colored::Colorize;
|
||||
use std::io::Write;
|
||||
|
||||
writeln!(file, "{}", payload_str).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
writeln!(file, "{}", render_backtrace().sanitize_path()).unwrap_or_else(|_| {
|
||||
default_hook(info);
|
||||
std::process::exit(0);
|
||||
});
|
||||
let log_dir = workspace::get_working_dir()?;
|
||||
if !log_dir.exists() {
|
||||
std::fs::create_dir_all(&log_dir)?;
|
||||
}
|
||||
let log_path = log_dir.join("panic.log");
|
||||
|
||||
let panic_msg = format!(
|
||||
let mut file = std::fs::File::create(&log_path)?;
|
||||
let payload = info.payload();
|
||||
let payload_str = if let Some(s) = payload.downcast_ref::<&str>() {
|
||||
*s
|
||||
} else if let Some(s) = payload.downcast_ref::<String>() {
|
||||
s
|
||||
} else {
|
||||
"<non-string panic payload>"
|
||||
};
|
||||
|
||||
writeln!(file, "{}", payload_str)?;
|
||||
writeln!(file, "{}", render_backtrace().sanitize_path())?;
|
||||
|
||||
let panic_msg = format!(
|
||||
"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
|
||||
|
||||
We have generated a report file at \"{}\". Submit an issue or email with the subject of \"Zenyx Crash Report\" and include the report as an attachment.
|
||||
|
@ -63,11 +57,12 @@ https://github.com/Zenyx-Engine/Zenyx/issues
|
|||
We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.
|
||||
|
||||
Thank you kindly!", log_path.display());
|
||||
println!("{}", panic_msg.red().bold());
|
||||
println!("\nFor future reference, the error summary is as follows:\n{}", payload_str.red().bold());
|
||||
std::process::exit(0);
|
||||
}));
|
||||
});
|
||||
println!("{}", panic_msg.red().bold());
|
||||
println!(
|
||||
"\nFor future reference, the error summary is as follows:\n{}",
|
||||
payload_str.red().bold()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_backtrace() -> String {
|
||||
|
@ -130,7 +125,7 @@ trait Sanitize {
|
|||
impl Sanitize for str {
|
||||
fn sanitize_path(&self) -> String {
|
||||
let username_pattern = r"(?i)(/home/|/Users/|\\Users\\)([^/\\]+)";
|
||||
let re = Regex::new(username_pattern).expect("Failed to sanitize path, aborting operation");
|
||||
let re = Regex::new(username_pattern).expect("Failed to compile regex for sanitization");
|
||||
re.replace_all(self, "${1}<USER>").to_string()
|
||||
}
|
||||
}
|
||||
|
|
BIN
engine/src/core/render/DejaVuSans.ttf
Normal file
BIN
engine/src/core/render/DejaVuSans.ttf
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -1,19 +1,32 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ctx::WgpuCtx;
|
||||
use ctx::{Renderer, Vertex};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use tobj::{LoadOptions, Model};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use wgpu::rwh::HasWindowHandle;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop::ControlFlow;
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use winit::window::{Window, WindowId};
|
||||
use winit::event::{KeyEvent, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||
use winit::window::Window;
|
||||
use winit::window::WindowId;
|
||||
|
||||
pub mod ctx;
|
||||
|
||||
struct WindowContext<'window> {
|
||||
window: Arc<Window>,
|
||||
ctx: WgpuCtx<'window>,
|
||||
main_window: bool
|
||||
ctx: Renderer<'window>,
|
||||
main_window: bool,
|
||||
}
|
||||
impl Deref for WindowContext<'_> {
|
||||
type Target = winit::window::Window;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.window.as_ref()
|
||||
}
|
||||
}
|
||||
impl WindowContext<'_> {
|
||||
pub fn is_main_window(&self) -> bool {
|
||||
|
@ -23,28 +36,284 @@ impl WindowContext<'_> {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct App<'window> {
|
||||
windows: HashMap<WindowId, WindowContext<'window>>,
|
||||
windows: ahash::AHashMap<WindowId, WindowContext<'window>>,
|
||||
}
|
||||
|
||||
static CUBE_OBJ: &str = "
|
||||
# Blender 4.2.3 LTS
|
||||
# www.blender.org
|
||||
mtllib cube.mtl
|
||||
o Cube
|
||||
v 1.000000 1.000000 -1.000000
|
||||
v 1.000000 -1.000000 -1.000000
|
||||
v 1.000000 1.000000 1.000000
|
||||
v 1.000000 -1.000000 1.000000
|
||||
v -1.000000 1.000000 -1.000000
|
||||
v -1.000000 -1.000000 -1.000000
|
||||
v -1.000000 1.000000 1.000000
|
||||
v -1.000000 -1.000000 1.000000
|
||||
vn -0.0000 1.0000 -0.0000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
vn -0.0000 -1.0000 -0.0000
|
||||
vn 1.0000 -0.0000 -0.0000
|
||||
vn -0.0000 -0.0000 -1.0000
|
||||
vt 0.625000 0.500000
|
||||
vt 0.875000 0.500000
|
||||
vt 0.875000 0.750000
|
||||
vt 0.625000 0.750000
|
||||
vt 0.375000 0.750000
|
||||
vt 0.625000 1.000000
|
||||
vt 0.375000 1.000000
|
||||
vt 0.375000 0.000000
|
||||
vt 0.625000 0.000000
|
||||
vt 0.625000 0.250000
|
||||
vt 0.375000 0.250000
|
||||
vt 0.125000 0.500000
|
||||
vt 0.375000 0.500000
|
||||
vt 0.125000 0.750000
|
||||
s 0
|
||||
usemtl Material
|
||||
f 1/1/1 5/2/1 7/3/1 3/4/1
|
||||
f 4/5/2 3/4/2 7/6/2 8/7/2
|
||||
f 8/8/3 7/9/3 5/10/3 6/11/3
|
||||
f 6/12/4 2/13/4 4/5/4 8/14/4
|
||||
f 2/13/5 1/1/5 3/4/5 4/5/5
|
||||
f 6/11/6 5/10/6 1/1/6 2/13/6
|
||||
";
|
||||
|
||||
impl App<'_> {
|
||||
fn create_main_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let win_attr = Window::default_attributes().with_title("Zenyx");
|
||||
match event_loop.create_window(win_attr) {
|
||||
Ok(window) => {
|
||||
let window = Arc::new(window);
|
||||
let window_id = window.id();
|
||||
match Renderer::new_blocking(window.clone()) {
|
||||
Ok(mut wgpu_ctx) => {
|
||||
let obj = match tobj::load_obj(
|
||||
"Pumpkin.obj",
|
||||
&LoadOptions {
|
||||
triangulate: true,
|
||||
single_index: true,
|
||||
..Default::default()
|
||||
},
|
||||
) {
|
||||
Ok(obj) => obj,
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
panic!()
|
||||
}
|
||||
};
|
||||
let (combined_vertices, combined_indices) = parse_obj(&obj.0);
|
||||
|
||||
wgpu_ctx.add_model(&combined_vertices, &combined_indices);
|
||||
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: true,
|
||||
},
|
||||
);
|
||||
info!("Main window created: {:?}", window_id);
|
||||
}
|
||||
Err(e) => error!("Failed to create WGPU context: {:?}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to create main window: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_close_requested(&mut self, window_id: WindowId) {
|
||||
if self.windows.remove(&window_id).is_some() {
|
||||
debug!("Window {:?} closed", window_id);
|
||||
} else {
|
||||
warn!("Tried to close non-existent window {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_keyboard_input(
|
||||
&mut self,
|
||||
event_loop: &ActiveEventLoop,
|
||||
window_id: WindowId,
|
||||
key_event: KeyEvent,
|
||||
) {
|
||||
if !key_event.state.is_pressed() {
|
||||
return;
|
||||
}
|
||||
match key_event.physical_key {
|
||||
winit::keyboard::PhysicalKey::Code(code) => match code {
|
||||
winit::keyboard::KeyCode::Space => {
|
||||
self.toggle_background(window_id);
|
||||
}
|
||||
winit::keyboard::KeyCode::Escape => {
|
||||
self.spawn_child_window(event_loop);
|
||||
}
|
||||
other => error!("Unimplemented keycode: {:?}", other),
|
||||
},
|
||||
_ => debug!("Received a keyboard event with no physical key"),
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_background(&mut self, window_id: WindowId) {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
let current_color = window_context.ctx.bg_color();
|
||||
|
||||
let new_color = match current_color {
|
||||
&wgpu::Color::WHITE => wgpu::Color::BLACK,
|
||||
&wgpu::Color::BLACK => wgpu::Color::WHITE,
|
||||
_ => wgpu::Color::WHITE,
|
||||
};
|
||||
let new_text_color = match window_context.ctx.text_color() {
|
||||
&wgpu::Color::WHITE => wgpu::Color::BLACK,
|
||||
&wgpu::Color::BLACK => wgpu::Color::WHITE,
|
||||
_ => wgpu::Color::WHITE,
|
||||
};
|
||||
|
||||
println!("new text color {new_text_color:#?}");
|
||||
window_context.ctx.set_bg_color(new_color);
|
||||
window_context.ctx.set_text_color(new_text_color);
|
||||
debug!("Toggled background color for window {:?}", window_id);
|
||||
} else {
|
||||
warn!("No window context for toggling background: {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
||||
let title = format!("Zenyx - New Window {}", self.windows.len());
|
||||
// TODO: Verify that this is safe instead of matching on it
|
||||
let win_attr = unsafe {
|
||||
let base = Window::default_attributes().with_title(title);
|
||||
match main_ctx.window_handle() {
|
||||
Ok(handle) => base.with_parent_window(Some(handle.as_raw())),
|
||||
Err(_) => base,
|
||||
}
|
||||
};
|
||||
match event_loop.create_window(win_attr) {
|
||||
Ok(window) => {
|
||||
let window = Arc::new(window);
|
||||
let window_id = window.id();
|
||||
match Renderer::new_blocking(window.clone()) {
|
||||
Ok(mut wgpu_ctx) => {
|
||||
{
|
||||
let mut tmp_path: PathBuf = env::temp_dir();
|
||||
tmp_path.push("cube.obj");
|
||||
if let Err(e) = fs::write(&tmp_path, CUBE_OBJ) {
|
||||
error!("Failed to write cube OBJ to temp: {:?}", e);
|
||||
}
|
||||
|
||||
let load_options = tobj::LoadOptions {
|
||||
triangulate: true,
|
||||
single_index: true,
|
||||
..Default::default()
|
||||
};
|
||||
match tobj::load_obj(tmp_path.to_str().unwrap(), &load_options) {
|
||||
Ok(cube_model) => {
|
||||
let (cube_vertices, cube_indices) =
|
||||
parse_obj(&cube_model.0);
|
||||
wgpu_ctx.add_model(&cube_vertices, &cube_indices);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to load cube OBJ from temp file: {:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: false,
|
||||
},
|
||||
);
|
||||
debug!("Spawned new child window: {:?}", window_id);
|
||||
}
|
||||
Err(e) => error!("Failed to create WGPU context for child window: {:?}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to create child window: {:?}", e),
|
||||
}
|
||||
} else {
|
||||
error!("No main window found. Cannot spawn a child window.");
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_redraw_requested(&mut self, window_id: WindowId) {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.draw();
|
||||
window_context.request_redraw();
|
||||
trace!(
|
||||
"Redrew window {:?} with title: {}",
|
||||
window_id,
|
||||
window_context.window.title()
|
||||
);
|
||||
} else {
|
||||
warn!("Received redraw for unknown window {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_resize(&mut self, window_id: WindowId, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.resize(new_size.into());
|
||||
window_context.window.request_redraw();
|
||||
debug!(
|
||||
"Resized window {:?} to {}x{}",
|
||||
window_id, new_size.width, new_size.height
|
||||
);
|
||||
} else {
|
||||
warn!("Received resize for unknown window {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_destroyed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if self.windows.is_empty() || !self.windows.iter().any(|(_, ctx)| ctx.is_main_window()) {
|
||||
self.windows.clear();
|
||||
debug!("All main windows are closed. Exiting event loop.");
|
||||
event_loop.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_obj(obj: &Vec<Model>) -> (Vec<Vertex>, Vec<u32>) {
|
||||
let mut combined_vertices = Vec::new();
|
||||
let mut combined_indices = Vec::new();
|
||||
let mut vertex_offset = 0;
|
||||
|
||||
for object in obj {
|
||||
let mesh: &_ = &object.mesh;
|
||||
let vertices: Vec<Vertex> = (0..mesh.positions.len() / 3)
|
||||
.map(|i| Vertex {
|
||||
position: [
|
||||
mesh.positions[i * 3],
|
||||
mesh.positions[i * 3 + 1],
|
||||
mesh.positions[i * 3 + 2],
|
||||
],
|
||||
normal: if !mesh.normals.is_empty() {
|
||||
[
|
||||
mesh.normals[i * 3],
|
||||
mesh.normals[i * 3 + 1],
|
||||
mesh.normals[i * 3 + 2],
|
||||
]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
combined_vertices.extend(vertices);
|
||||
combined_indices.extend(mesh.indices.iter().map(|&index| index + vertex_offset));
|
||||
vertex_offset += (mesh.positions.len() as u32) / 3;
|
||||
}
|
||||
|
||||
(combined_vertices, combined_indices)
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App<'_> {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if self.windows.is_empty() {
|
||||
let win_attr = Window::default_attributes().with_title("Zenyx");
|
||||
let window = Arc::new(
|
||||
event_loop
|
||||
.create_window(win_attr)
|
||||
.expect("create window err."),
|
||||
);
|
||||
let window_id = window.id();
|
||||
let wgpu_ctx = WgpuCtx::new_blocking(window.clone()).unwrap();
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: true,
|
||||
},
|
||||
);
|
||||
self.create_main_window(event_loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,88 +325,31 @@ impl ApplicationHandler for App<'_> {
|
|||
) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
if let Some(window_context) = self.windows.remove(&window_id) {
|
||||
|
||||
drop(window_context);
|
||||
debug!("Window: {:?} closed, exiting", window_id);
|
||||
}
|
||||
self.handle_close_requested(window_id);
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id,
|
||||
event,
|
||||
is_synthetic,
|
||||
} => match event.physical_key {
|
||||
winit::keyboard::PhysicalKey::Code(code) => {
|
||||
if event.state.is_pressed() == false {
|
||||
return;
|
||||
}
|
||||
match code {
|
||||
winit::keyboard::KeyCode::Space => {
|
||||
debug!("Space key pressed");
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id){
|
||||
match window_context.ctx.bg_color() {
|
||||
wgpu::Color::WHITE => {
|
||||
window_context.ctx.change_bg_color(wgpu::Color::BLACK)
|
||||
}
|
||||
wgpu::Color::BLACK => {
|
||||
window_context.ctx.change_bg_color(wgpu::Color::WHITE)
|
||||
}
|
||||
_ => window_context.ctx.change_bg_color(wgpu::Color::WHITE),
|
||||
}
|
||||
}
|
||||
}
|
||||
winit::keyboard::KeyCode::Escape => {
|
||||
debug!("Escape key pressed, spawning new window");
|
||||
let win_attr = Window::default_attributes()
|
||||
.with_title(format!("Zenyx - New Window {}", self.windows.len()));
|
||||
let new_window = Arc::new(
|
||||
event_loop
|
||||
.create_window(win_attr)
|
||||
.expect("create window err."),
|
||||
);
|
||||
let window_id = new_window.id();
|
||||
let wgpu_ctx = WgpuCtx::new_blocking(new_window.clone()).unwrap();
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window: new_window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => info!("Unimplemented keycode: {:?}", code),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
WindowEvent::RedrawRequested => {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.draw();
|
||||
window_context.window.request_redraw();
|
||||
}
|
||||
event: key_event, ..
|
||||
} => {
|
||||
self.handle_keyboard_input(event_loop, window_id, key_event);
|
||||
}
|
||||
WindowEvent::Resized(size) => {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.resize(size.into());
|
||||
window_context.window.request_redraw();
|
||||
let size_str: String = size.height.to_string() + "x" + &size.width.to_string();
|
||||
debug!("Window resized to {:?}", size_str);
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
self.handle_redraw_requested(window_id);
|
||||
}
|
||||
WindowEvent::Resized(new_size) => {
|
||||
self.handle_resize(window_id, new_size);
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
if !self.windows.iter().any(|(_,ctx)| ctx.is_main_window()) || self.windows.is_empty() {
|
||||
self.windows.clear();
|
||||
event_loop.exit();
|
||||
}
|
||||
self.handle_destroyed(event_loop);
|
||||
}
|
||||
_ => trace!("Unhandled window event"),
|
||||
_ => trace!("Unhandled window event for window {:?}", window_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_renderer(event_loop: EventLoop<()>) {
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
let mut app = App::default();
|
||||
event_loop.run_app(&mut app).unwrap();
|
||||
if let Err(e) = event_loop.run_app(&mut app) {
|
||||
error!("Failed to run application: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
|
42
engine/src/core/render/shader.wgsl
Normal file
42
engine/src/core/render/shader.wgsl
Normal file
|
@ -0,0 +1,42 @@
|
|||
struct CameraUniform {
|
||||
view: mat4x4<f32>,
|
||||
proj: mat4x4<f32>,
|
||||
};
|
||||
|
||||
struct ModelUniform {
|
||||
model: mat4x4<f32>,
|
||||
};
|
||||
|
||||
@group(0) @binding(0)
|
||||
var<uniform> camera: CameraUniform;
|
||||
|
||||
@group(1) @binding(0)
|
||||
var<uniform> model: ModelUniform;
|
||||
|
||||
struct VertexInput {
|
||||
@location(0) position: vec3<f32>,
|
||||
@location(1) normal: vec3<f32>,
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) clip_position: vec4<f32>,
|
||||
@location(0) normal: vec3<f32>,
|
||||
};
|
||||
|
||||
@vertex
|
||||
fn vs_main(input: VertexInput) -> VertexOutput {
|
||||
var output: VertexOutput;
|
||||
let model_pos = model.model * vec4<f32>(input.position, 1.0);
|
||||
output.clip_position = camera.proj * camera.view * model_pos;
|
||||
output.normal = input.normal;
|
||||
return output;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let ambient: f32 = 0.2;
|
||||
let light_dir = normalize(vec3<f32>(0.5, 1.0, 0.5));
|
||||
let diffuse = clamp(dot(normalize(input.normal), light_dir), 0.0, 1.0);
|
||||
let brightness = ambient + (1.0 - ambient) * diffuse;
|
||||
return vec4<f32>(0.7 * brightness, 0.7 * brightness, 0.9 * brightness, 1.0);
|
||||
}
|
|
@ -5,7 +5,6 @@ use tokio::runtime;
|
|||
#[allow(unused_imports)]
|
||||
use tracing::{debug, error, info, warn};
|
||||
use tracing::{level_filters::LevelFilter, subscriber::set_global_default};
|
||||
use tracing_subscriber::{layer::Filter, util::SubscriberInitExt};
|
||||
use winit::event_loop::EventLoop;
|
||||
pub mod core;
|
||||
|
||||
|
@ -45,7 +44,6 @@ async fn main() -> anyhow::Result<()> {
|
|||
info!("Type 'help' for a list of commands.");
|
||||
|
||||
core::render::init_renderer(event_loop);
|
||||
|
||||
if let Err(_) = repl_thread.join() {
|
||||
eprintln!("REPL thread panicked");
|
||||
}
|
||||
|
|
12
flake.lock
generated
12
flake.lock
generated
|
@ -77,11 +77,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1742422364,
|
||||
"narHash": "sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ=",
|
||||
"lastModified": 1743095683,
|
||||
"narHash": "sha256-gWd4urRoLRe8GLVC/3rYRae1h+xfQzt09xOfb0PaHSk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a84ebe20c6bc2ecbcfb000a50776219f48d134cc",
|
||||
"rev": "5e5402ecbcb27af32284d4a62553c019a3a49ea6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -138,11 +138,11 @@
|
|||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742610648,
|
||||
"narHash": "sha256-9jWi3gw3fEIgEslnFjH/s1I+Iyf1+4t5B1Ed1FOiy8o=",
|
||||
"lastModified": 1743215516,
|
||||
"narHash": "sha256-52qbrkG65U1hyrQWltgHTgH4nm0SJL+9TWv2UDCEPNI=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "c60d41987df3c853e2a842de2c63ded40400979b",
|
||||
"rev": "524463199fdee49338006b049bc376b965a2cfed",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -52,7 +52,9 @@
|
|||
devShells.default = pkgs.mkShell {
|
||||
name = "zenyx";
|
||||
nativeBuildInputs = with pkgs; [
|
||||
rust-bin.stable.latest.default
|
||||
(rust-bin.stable.latest.default.override {
|
||||
extensions = ["rust-src" "cargo" "rustfmt" "clippy"];
|
||||
})
|
||||
pkg-config
|
||||
];
|
||||
buildInputs = buildInputs;
|
||||
|
|
2
test.mtl
Normal file
2
test.mtl
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Blender 4.2.3 LTS MTL File: 'None'
|
||||
# www.blender.org
|
Loading…
Add table
Add a link
Reference in a new issue