From 87b9d7c7bd60aef1bace57ae1d4b7da801a311dc Mon Sep 17 00:00:00 2001 From: Chance Date: Thu, 10 Apr 2025 14:26:52 -0400 Subject: [PATCH] feat: basic GUI terminal when pressing F12 --- Cargo.lock | 768 ++++--------------------------- engine/Cargo.toml | 65 +-- engine/build.rs | 7 - engine/src/cli/mod.rs | 27 ++ engine/src/core/mod.rs | 16 + engine/src/core/panic.rs | 69 ++- engine/src/core/render/ctx.rs | 172 +++++-- engine/src/core/render/mod.rs | 131 +++++- engine/src/core/repl/commands.rs | 77 ++-- engine/src/core/repl/handler.rs | 24 +- engine/src/core/repl/input.rs | 38 +- engine/src/error.rs | 2 +- engine/src/main.rs | 48 +- engine/src/metadata.rs | 209 ++++++++- zenyx.toml | 0 15 files changed, 808 insertions(+), 845 deletions(-) create mode 100644 engine/src/cli/mod.rs create mode 100644 zenyx.toml diff --git a/Cargo.lock b/Cargo.lock index bc921db..6081867 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,12 +46,6 @@ dependencies = [ "zerocopy 0.7.35", ] -[[package]] -name = "aligned-vec" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" - [[package]] name = "android-activity" version = "0.6.0" @@ -94,6 +88,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + [[package]] name = "anyhow" version = "1.0.97" @@ -118,41 +118,12 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" - -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "as-raw-xcb-connection" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" - [[package]] name = "ascii" version = "1.1.0" @@ -180,29 +151,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "av1-grain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" -dependencies = [ - "arrayvec", -] - [[package]] name = "backtrace" version = "0.3.74" @@ -233,12 +181,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - [[package]] name = "bitflags" version = "1.3.2" @@ -254,12 +196,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitstream-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" - [[package]] name = "block" version = "0.1.6" @@ -287,7 +223,9 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" dependencies = [ + "cargo-lock", "chrono", + "git2", ] [[package]] @@ -368,9 +306,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.17" +version = "1.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" dependencies = [ "jobserver", "libc", @@ -383,16 +321,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -427,6 +355,31 @@ dependencies = [ "windows-link", ] +[[package]] +name = "clap" +version = "4.5.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + [[package]] name = "clipboard-win" version = "5.4.0" @@ -476,12 +429,6 @@ dependencies = [ "unicode-width 0.1.14", ] -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "colored" version = "3.0.0" @@ -561,9 +508,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -593,12 +540,6 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - [[package]] name = "cursor-icon" version = "1.1.0" @@ -693,9 +634,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -707,21 +648,6 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" -[[package]] -name = "exr" -version = "1.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - [[package]] name = "fd-lock" version = "4.0.4" @@ -842,17 +768,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "futures-sink" version = "0.3.31" @@ -874,7 +789,6 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", - "futures-macro", "futures-sink", "futures-task", "memchr", @@ -883,16 +797,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gethostname" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" -dependencies = [ - "libc", - "windows-targets 0.48.5", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -916,32 +820,25 @@ dependencies = [ "wasi 0.14.2+wasi-0.2.4", ] -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "git2" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5220b8ba44c68a9a7f7a7659e864dd73692e417ef0211bea133c7b74e031eeb9" +dependencies = [ + "bitflags 2.9.0", + "libc", + "libgit2-sys", + "log", + "url", +] + [[package]] name = "gl_generator" version = "0.14.0" @@ -1063,16 +960,6 @@ dependencies = [ "bitflags 2.9.0", ] -[[package]] -name = "half" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.15.2" @@ -1280,58 +1167,20 @@ checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" dependencies = [ "bytemuck", "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", "num-traits", "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core", - "zune-jpeg", ] -[[package]] -name = "image-webp" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" - [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", ] -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "itertools" version = "0.11.0" @@ -1341,15 +1190,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "jni" version = "0.21.1" @@ -1382,12 +1222,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - [[package]] name = "js-sys" version = "0.3.77" @@ -1421,12 +1255,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - [[package]] name = "libc" version = "0.2.171" @@ -1434,13 +1262,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] -name = "libfuzzer-sys" -version = "0.4.9" +name = "libgit2-sys" +version = "0.18.1+1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" dependencies = [ - "arbitrary", "cc", + "libc", + "libz-sys", + "pkg-config", ] [[package]] @@ -1461,7 +1291,19 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.9.0", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.11", +] + +[[package]] +name = "libz-sys" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] @@ -1478,9 +1320,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" @@ -1510,24 +1352,6 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - [[package]] name = "malloc_buf" version = "0.0.6" @@ -1537,16 +1361,6 @@ dependencies = [ "libc", ] -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "memchr" version = "2.7.4" @@ -1585,9 +1399,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", "simd-adler32", @@ -1677,12 +1491,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "nibble_vec" version = "0.1.0" @@ -1714,12 +1522,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - [[package]] name = "ntapi" version = "0.4.1" @@ -1739,47 +1541,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2126,7 +1887,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.11", "smallvec", "windows-targets 0.52.6", ] @@ -2247,34 +2008,6 @@ name = "profiling" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" @@ -2346,56 +2079,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" -[[package]] -name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.12.1", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "once_cell", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "system-deps", - "thiserror 1.0.69", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - [[package]] name = "raw-cpuid" version = "11.5.0" @@ -2448,9 +2131,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags 2.9.0", ] @@ -2472,12 +2155,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" -[[package]] -name = "rgb" -version = "0.8.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2518,7 +2195,7 @@ dependencies = [ "bitflags 2.9.0", "errno", "libc", - "linux-raw-sys 0.9.3", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -2538,7 +2215,6 @@ dependencies = [ "cfg-if", "clipboard-win", "fd-lock", - "home", "libc", "log", "memchr", @@ -2583,19 +2259,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sctk-adwaita" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" -dependencies = [ - "ab_glyph", - "log", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", -] - [[package]] name = "semver" version = "1.0.26" @@ -2655,15 +2318,6 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - [[package]] name = "slab" version = "0.4.9" @@ -2684,9 +2338,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "smithay-client-toolkit" @@ -2743,12 +2397,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strict-num" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" - [[package]] name = "strum" version = "0.26.3" @@ -2806,25 +2454,6 @@ dependencies = [ "windows 0.57.0", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "termcolor" version = "1.4.1" @@ -2884,42 +2513,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "tiny-skia" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - [[package]] name = "tinystr" version = "0.7.6" @@ -2935,10 +2528,6 @@ name = "tobj" version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04aca6092e5978e708ee784e8ab9b5cf3cdb598b28f99a2f257446e7081a7025" -dependencies = [ - "ahash", - "tokio", -] [[package]] name = "tokio" @@ -2947,8 +2536,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", - "bytes", - "parking_lot", "pin-project-lite", "tokio-macros", ] @@ -3005,21 +2592,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" version = "0.1.33" @@ -3027,18 +2602,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", ] [[package]] @@ -3049,10 +2612,8 @@ checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "nu-ansi-term", "sharded-slab", - "smallvec", "thread_local", "tracing-core", - "tracing-log", ] [[package]] @@ -3130,27 +2691,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "v_frame" -version = "0.3.8" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" @@ -3164,7 +2708,7 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c73a36bc44e3039f51fbee93e39f41225f6b17b380eb70cc2aab942df06b34dd" dependencies = [ - "itertools 0.11.0", + "itertools", "nom", ] @@ -3369,7 +2913,6 @@ checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" dependencies = [ "dlib", "log", - "once_cell", "pkg-config", ] @@ -3393,12 +2936,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - [[package]] name = "wfd" version = "0.1.7" @@ -3462,9 +2999,9 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "24.0.2" +version = "24.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4317a17171dc20e6577bf606796794580accae0716a69edbc7388c86a3ec9f23" +checksum = "f112f464674ca69f3533248508ee30cb84c67cf06c25ff6800685f5e0294e259" dependencies = [ "android_system_properties", "arrayvec", @@ -3791,21 +3328,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -3828,12 +3350,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3846,12 +3362,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3864,12 +3374,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3888,12 +3392,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3906,12 +3404,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3924,12 +3416,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3942,12 +3428,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3965,7 +3445,6 @@ dependencies = [ "atomic-waker", "bitflags 2.9.0", "block2", - "bytemuck", "calloop", "cfg_aliases", "concurrent-queue", @@ -3982,12 +3461,10 @@ dependencies = [ "objc2-foundation", "objc2-ui-kit", "orbclient", - "percent-encoding", "pin-project", "raw-window-handle 0.6.2", "redox_syscall 0.4.1", "rustix 0.38.44", - "sctk-adwaita", "smithay-client-toolkit", "smol_str", "tracing", @@ -4001,16 +3478,14 @@ dependencies = [ "web-sys", "web-time", "windows-sys 0.52.0", - "x11-dl", - "x11rb", "xkbcommon-dl", ] [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] @@ -4036,38 +3511,6 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" -dependencies = [ - "as-raw-xcb-connection", - "gethostname", - "libc", - "libloading", - "once_cell", - "rustix 0.38.44", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" - [[package]] name = "xcursor" version = "0.3.8" @@ -4101,9 +3544,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "yoke" @@ -4149,6 +3592,7 @@ dependencies = [ "bytemuck", "cargo-lock", "cgmath", + "clap", "colored", "futures", "image", @@ -4251,27 +3695,3 @@ dependencies = [ "quote", "syn", ] - -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "zune-jpeg" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" -dependencies = [ - "zune-core", -] diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 1c1230c..7b54062 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -2,39 +2,42 @@ name = "zenyx" version = "0.1.0" edition = "2024" -repository = "https://github.com/Zenyx-Engine/Zenyx" +authors = ["Caznix (Chance) "] +description = "A memory safe, opinionated Game Engine/Framework, written in Rust." +keywords = ["engine", "graphics", "game"] +categories = ["game-development", "graphics"] +license = "MIT" +homepage = "https://zenyx-engine.github.io/" +documentation = "https://zenyx-engine.github.io/docs" +repository = "https://codeberg.org/Caznix/Zenyx" [dependencies] -# TBR (if possible) -backtrace = "0.3.74" -# TBR (if possible) -colored = "3.0.0" +backtrace = { version = "0.3.74", default-features = false } +colored = { version = "3.0.0", default-features = false } parking_lot.workspace = true -# TBR (if possible) -rustyline = { version = "15.0.0", features = ["derive", "rustyline-derive"] } -thiserror = "2.0.11" -# 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.2", features = ["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" -# TBR -tobj = { version = "4.0.3", features = ["tokio"] } -ahash = "0.8.11" -wgpu_text = "0.9.2" -toml = "0.8.20" -serde = { version = "1.0.219", features = ["derive"] } -native-dialog = "0.7.0" -sysinfo = "0.34.2" -raw-cpuid = "11.5.0" -image = "0.25.6" +rustyline = { version = "15.0.0", default-features = false, features = ["custom-bindings", "derive","with-file-history"] } +thiserror = { version = "2.0.11", default-features = false } +tokio = { version = "1.44.2", default-features = false, features = ["macros", "rt", "rt-multi-thread"] } +# Will be updated to 25.x.x when other dependencies are updated to be supported +wgpu = { version = "24.0.3", default-features = false } +winit = { version = "0.30.9", default-features = false, features = ["rwh_06", "wayland"] } +bytemuck = { version = "1.21.0", default-features = false } +futures = { version = "0.3.31", default-features = false, features = ["executor"] } +cgmath = { version = "0.18.0", default-features = false } +tracing = { version = "0.1.41", default-features = false } +tracing-subscriber = { version = "0.3.19", default-features = false, features = ["ansi", "fmt"] } +tobj = { version = "4.0.3", default-features = false } +ahash = { version = "0.8.11", default-features = false } +wgpu_text = { version = "0.9.2", default-features = false } +toml = { version = "0.8.20", default-features = false } +serde = { version = "1.0.219", default-features = false, features = ["derive"] } +native-dialog = { version = "0.7.0", default-features = false } +sysinfo = { version = "0.34.2", default-features = false, features = ["system"] } +raw-cpuid = { version = "11.5.0", default-features = false } +image = { version = "0.25.6", default-features = false, features = ["png"] } +clap = { version = "4.5.35", default-features = false, features = ["std"] } [build-dependencies] -built = { version = "0.7.7", features = ["chrono"] } -build-print = "0.1.1" -cargo-lock = "10.1.0" +built = { version = "0.7.7", default-features = false, features = ["cargo-lock", "chrono", "git2"] } +build-print = { version = "0.1.1", default-features = false } +cargo-lock = { version = "10.1.0", default-features = false } diff --git a/engine/build.rs b/engine/build.rs index ff9e5b4..cd7efea 100644 --- a/engine/build.rs +++ b/engine/build.rs @@ -82,13 +82,6 @@ fn main() { } }; - writeln!( - built_rs, - "{}pub static GIT_COMMIT_HASH: &str = \"{}\";", - ALLOW_DEAD_CODE, git_info - ) - .unwrap(); - match Lockfile::load(lockfile_path) { Ok(lockfile) => { let dependencies_to_track = ["tokio", "winit", "wgpu"]; diff --git a/engine/src/cli/mod.rs b/engine/src/cli/mod.rs new file mode 100644 index 0000000..af94365 --- /dev/null +++ b/engine/src/cli/mod.rs @@ -0,0 +1,27 @@ +use clap::{Arg, Command}; + +#[derive(Debug)] +pub struct Cli {} + +pub fn parse() { + let matches = Command::new("zenyx") + .version(env!("CARGO_PKG_VERSION")) + .author(env!("CARGO_PKG_AUTHORS")) + .about(env!("CARGO_PKG_DESCRIPTION")) + .arg( + Arg::new("name") + .short('n') + .long("name") + .value_name("NAME") + .help("Sets a custom name"), + ) + .subcommand( + Command::new("greet").about("Greets the given name").arg( + Arg::new("person") + .value_name("PERSON") + .help("The person to greet") + .required(true), + ), + ) + .get_matches(); +} diff --git a/engine/src/core/mod.rs b/engine/src/core/mod.rs index e08a06c..7b797a5 100644 --- a/engine/src/core/mod.rs +++ b/engine/src/core/mod.rs @@ -1,6 +1,22 @@ +use serde::{Deserialize, Serialize}; + pub mod ecs; pub mod panic; pub mod repl; pub mod splash; pub mod render; + +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +pub struct EngineState { + log_level: LogLevel, +} +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] + +enum LogLevel { + Info, + Debug, + Error, + Trace, +} +impl EngineState {} diff --git a/engine/src/core/panic.rs b/engine/src/core/panic.rs index 3c5abb6..7c494c4 100644 --- a/engine/src/core/panic.rs +++ b/engine/src/core/panic.rs @@ -1,5 +1,5 @@ use std::str::FromStr; -use std::{error::Error, path::PathBuf}; +use std::{env, error::Error, path::PathBuf, thread}; use native_dialog::{MessageDialog, MessageType}; use parking_lot::Once; @@ -15,7 +15,7 @@ pub fn set_panic_hook() { eprintln!("Error in panic hook: {}", e); default_hook(info); } - std::process::exit(0); + std::process::exit(1); })); }); } @@ -41,13 +41,53 @@ fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box" }; - writeln!(file, "{}", payload_str)?; + writeln!(file, "Panic Occurred: {}", payload_str)?; + + if let Some(location) = info.location() { + writeln!(file, "Panic Location: {}", location)?; + } + writeln!(file, "{}", capture_backtrace().sanitize_path())?; + // Add more contextual information + writeln!(file, "\n--- Additional Information ---")?; + + // Rust Version + if let Ok(rust_version) = rust_version() { + writeln!(file, "Rust Version: {}", rust_version)?; + } + + // Command-line Arguments + writeln!(file, "Command-line Arguments:")?; + for arg in env::args() { + writeln!(file, " {}", arg)?; + } + + // Environment Variables (consider filtering sensitive ones) + writeln!(file, "\nEnvironment Variables (selected):")?; + let interesting_env_vars = ["PATH", "RUST_VERSION", "CARGO_TARGET_DIR", "HOME", "USER"]; + for (key, value) in env::vars() { + if interesting_env_vars.contains(&key.as_str()) { + writeln!(file, " {}: {}", key, value)?; + } + } + + // Current Working Directory + if let Ok(cwd) = env::current_dir() { + writeln!(file, "\nCurrent Working Directory: {}", cwd.display())?; + } + + // Thread Information + if let Some(thread) = thread::current().name() { + writeln!(file, "\nThread Name: {}", thread)?; + } else { + writeln!(file, "\nThread ID: {:?}", thread::current().id())?; + } + let panic_msg = format!( r#"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. +We have generated a detailed report file at '{}'. Submit an issue or email with the subject of 'Zenyx Crash Report' and include the report as an attachment. To submit the crash report: https://codeberg.org/Caznix/Zenyx/issues @@ -61,7 +101,9 @@ Thank you kindly!"#, r#"{} For future reference, the error summary is as follows: -{}"#, +{} + +More details can be found in the crash report file."#, panic_msg, payload_str ); @@ -78,15 +120,24 @@ For future reference, the error summary is as follows: Ok(()) } + +fn rust_version() -> Result> { + let version = env!("CARGO_PKG_RUST_VERSION"); + Ok(version.to_string()) +} + fn capture_backtrace() -> String { let mut backtrace = String::new(); let sysinfo = crate::metadata::SystemMetadata::current(); - backtrace.push_str(&sysinfo.verbose_summary()); + backtrace.push_str(&format!( + "--- System Information ---\n{}\n", + sysinfo.verbose_summary() + )); - let trace = backtrace::Backtrace::new(); - let message = format!("\nBacktrace:\n\n"); + let trace = std::backtrace::Backtrace::force_capture(); + let message = format!("\n--- Backtrace ---\n\n"); backtrace.push_str(&message); - backtrace.push_str(&format!("{trace:?}")); + backtrace.push_str(&format!("{trace:#}")); backtrace } diff --git a/engine/src/core/render/ctx.rs b/engine/src/core/render/ctx.rs index cee048c..aab9606 100644 --- a/engine/src/core/render/ctx.rs +++ b/engine/src/core/render/ctx.rs @@ -16,6 +16,8 @@ use winit::window::Window; use crate::error::Result; use crate::error::{ZenyxError, ZenyxErrorKind}; +use super::TerminalState; + const SHADER_SRC: &str = include_str!("shader.wgsl"); #[repr(C)] @@ -148,7 +150,7 @@ impl Model { let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Index Buffer"), - contents: bytemuck::cast_slice(indices), // Use proper indices + contents: bytemuck::cast_slice(indices), usage: wgpu::BufferUsages::INDEX, }); @@ -215,11 +217,12 @@ pub struct Renderer<'window> { struct FontState { brush: TextBrush>, - section: OwnedSection, + output_section: OwnedSection, + input_section: OwnedSection, + fps_section: OwnedSection, scale: f32, color: wgpu::Color, } - impl<'window> Renderer<'window> { pub async fn new(window: Arc) -> Result { let instance = wgpu::Instance::new(&InstanceDescriptor { @@ -385,7 +388,7 @@ impl<'window> Renderer<'window> { let scale = base_scale * (surface_config.width as f32 / base_width as f32).clamp(0.5, 2.0); let color = wgpu::Color::WHITE; - let section = OwnedSection::default() + let fps_section = OwnedSection::default() .add_text(OwnedText::new("FPS: 0.00").with_scale(scale).with_color([ color.r as f32, color.g as f32, @@ -393,7 +396,25 @@ impl<'window> Renderer<'window> { color.a as f32, ])) .with_screen_position((10.0, 10.0)) - .with_bounds((base_scale * 200.0, base_scale * 2.0)) + .with_bounds((200.0, 50.0)) + .with_layout( + Layout::default() + .h_align(HorizontalAlign::Left) + .v_align(VerticalAlign::Top), + ); + + let output_section = OwnedSection::default() + .with_screen_position((10.0, 50.0)) + .with_bounds((width as f32 - 20.0, f32::MAX)) + .with_layout( + Layout::default() + .h_align(HorizontalAlign::Left) + .v_align(VerticalAlign::Top), + ); + + let input_section = OwnedSection::default() + .with_screen_position((10.0, height as f32 - 50.0)) + .with_bounds((width as f32 - 20.0, f32::MAX)) .with_layout( Layout::default() .h_align(HorizontalAlign::Left) @@ -424,7 +445,9 @@ impl<'window> Renderer<'window> { fps: 0f32, font_state: FontState { brush, - section, + fps_section, + output_section, + input_section, scale, color, }, @@ -458,35 +481,37 @@ impl<'window> Renderer<'window> { self.font_state .brush .resize_view(width as f32, height as f32, &self.queue); - let base_width = 1280.0; - let base_scale = 30.0; - let scale = base_scale * (width as f32 / base_width as f32).clamp(0.5, 2.0); - self.font_state.scale = scale; + self.font_state.output_section.bounds = (width as f32 - 20.0, height as f32 - 60.0); + self.font_state.input_section.screen_position = (10.0, height as f32 - 50.0); self.camera.resize(width, height); } - pub fn draw(&mut self) { + pub fn draw(&mut self, terminal_state: Option<&mut TerminalState>) { let elapsed = self.start_time.elapsed().as_secs_f32(); + if let Some(terminal_state) = terminal_state { + let delta_time = self.last_frame_instant.elapsed().as_secs_f32(); + self.draw_terminal(terminal_state, delta_time); + } else { + self.camera.update(&self.queue); - self.camera.update(&self.queue); - - for (i, model) in self.models.iter_mut().enumerate() { - let angle = Rad(elapsed * 0.8 + i as f32 * 0.3); - if i % 2 == 0 { - model.set_transform(Matrix4::from_angle_y(angle)); - } else { - model.set_transform(Matrix4::from_angle_x(angle) * Matrix4::from_angle_y(angle)); + for (i, model) in self.models.iter_mut().enumerate() { + let angle = Rad(elapsed * 0.8 + i as f32 * 0.3); + if i % 2 == 0 { + model.set_transform(Matrix4::from_angle_y(angle)); + } else { + model + .set_transform(Matrix4::from_angle_x(angle) * Matrix4::from_angle_y(angle)); + } + } + for (i, model) in self.models.iter().enumerate() { + if model.version > self.model_versions[i] { + model.update(&self.queue); + #[cfg(debug_assertions)] + trace!("Updating model: {:#?}", model); + self.model_versions[i] = model.version; + } } } - for (i, model) in self.models.iter().enumerate() { - if model.version > self.model_versions[i] { - model.update(&self.queue); - #[cfg(debug_assertions)] - trace!("Updating model: {:#?}", model); - self.model_versions[i] = model.version; - } - } - let surface_texture = self .surface .get_current_texture() @@ -508,8 +533,8 @@ impl<'window> Renderer<'window> { label: Some("Render Encoder"), }); let fps_text = format!("FPS: {:.2}", self.fps); - self.font_state.section.text.clear(); - self.font_state.section.text.push( + self.font_state.fps_section.text.clear(); + self.font_state.fps_section.text.push( OwnedText::new(fps_text) .with_scale(self.font_state.scale) .with_color([ @@ -522,7 +547,11 @@ impl<'window> Renderer<'window> { if let Err(e) = self.font_state.brush.queue( &self.device, &self.queue, - &[self.font_state.section.clone()], + &[ + self.font_state.fps_section.clone(), + self.font_state.input_section.clone(), + self.font_state.output_section.clone(), + ], ) { error!("Failed to queue text: {}", e); } @@ -594,7 +623,88 @@ impl<'window> Renderer<'window> { self.last_frame_instant = Instant::now(); } } + fn draw_terminal(&mut self, terminal_state: &mut TerminalState, delta_time: f32) { + terminal_state.cursor_blink_timer += delta_time; + if terminal_state.cursor_blink_timer >= 0.5 { + terminal_state.show_cursor = !terminal_state.show_cursor; + terminal_state.cursor_blink_timer = 0.0; + } + let line_height = self.font_state.scale * 1.5; + let max_visible_lines = (self.surface_config.height as f32 / line_height) as usize; + terminal_state.max_history_lines = max_visible_lines; + + self.font_state.output_section.text.clear(); + let mut current_line = 0; + let mut output_y = 0.0; + + for line in terminal_state.output_history.iter().rev() { + let sublines = line.split('\n').collect::>(); + + for subline in sublines.iter().rev() { + if current_line >= terminal_state.scroll_offset + max_visible_lines { + break; + } + + if current_line >= terminal_state.scroll_offset { + let processed = subline.replace('\t', " "); + self.font_state.output_section.text.push( + OwnedText::new(processed) + .with_scale(self.font_state.scale) + .with_color([1.0, 1.0, 1.0, 1.0]), + ); + output_y += line_height; + } + + current_line += 1; + } + + if current_line >= terminal_state.scroll_offset + max_visible_lines { + break; + } + } + + self.font_state.input_section.text.clear(); + let mut input_y = 0.0; + let input_text = format!( + "> {}{}", + terminal_state.input_buffer.replace('\t', " "), + if terminal_state.show_cursor { "_" } else { "" } + ); + + for (line_num, subline) in input_text.split('\n').enumerate() { + self.font_state.input_section.text.push( + OwnedText::new(subline) + .with_scale(self.font_state.scale) + .with_color([0.0, 1.0, 0.0, 1.0]), // .with_position((0.0, input_y)), + ); + input_y += line_height; + + if line_num >= 2 { + break; + } + } + + self.font_state.output_section.bounds = ( + self.surface_config.width as f32 - 20.0, + self.surface_config.height as f32 - 60.0, + ); + + self.font_state.input_section.bounds = + (self.surface_config.width as f32 - 20.0, line_height * 3.0); + + if let Err(e) = self.font_state.brush.queue( + &self.device, + &self.queue, + &[ + self.font_state.output_section.clone(), + self.font_state.input_section.clone(), + self.font_state.fps_section.clone(), + ], + ) { + error!("Failed to queue text: {}", e); + } + } pub fn set_bg_color(&mut self, color: wgpu::Color) { self.bg_color = color; } diff --git a/engine/src/core/render/mod.rs b/engine/src/core/render/mod.rs index 56538ad..86ee9cd 100644 --- a/engine/src/core/render/mod.rs +++ b/engine/src/core/render/mod.rs @@ -16,6 +16,7 @@ use winit::dpi::LogicalSize; use winit::dpi::Size; use winit::event::{KeyEvent, WindowEvent}; use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; +use winit::keyboard::NamedKey; #[cfg(target_os = "windows")] use winit::platform::windows::WindowAttributesExtWindows; use winit::window::Fullscreen; @@ -23,13 +24,17 @@ use winit::window::Icon; use winit::window::Window; use winit::window::WindowId; +use super::repl::input::evaluate_command; + pub mod ctx; -struct WindowContext<'window> { +pub struct WindowContext<'window> { window: Arc, ctx: Renderer<'window>, main_window: bool, + terminal_state: Option, } + impl Deref for WindowContext<'_> { type Target = winit::window::Window; @@ -42,7 +47,18 @@ impl WindowContext<'_> { self.main_window } } - +#[derive(Default)] +pub struct TerminalState { + input_buffer: String, + output_history: Vec, + scroll_offset: usize, + show_cursor: bool, + cursor_blink_timer: f32, + command_queue: Vec, + needs_execution: bool, + max_history_lines: usize, + input_history: Vec, +} #[derive(Default)] pub struct App<'window> { windows: ahash::AHashMap>, @@ -122,7 +138,6 @@ impl App<'_> { Ok(obj) => obj, Err(e) => { error!("Failed to load Pumpkin.obj: {e}"); - // Fallback to CUBE_OBJ let fallback_obj = CUBE_OBJ.to_string(); tobj::load_obj_buf( &mut fallback_obj.as_bytes(), @@ -147,6 +162,7 @@ impl App<'_> { window, ctx: wgpu_ctx, main_window: true, + terminal_state: None, }, ); info!("Main window created: {:?}", window_id); @@ -158,6 +174,69 @@ impl App<'_> { } } + fn create_terminal_window(&mut self, event_loop: &ActiveEventLoop) { + let icon = self.load_icon_from_bytes(Self::ICON).unwrap(); + + let win_attr = Window::default_attributes() + .with_title("Zenyx Terminal") + .with_inner_size(Size::Logical(LogicalSize::new(800.0, 600.0))) + .with_window_icon(icon); + + 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) => { + wgpu_ctx.set_bg_color(wgpu::Color::BLACK); + wgpu_ctx.set_text_color(wgpu::Color::GREEN); + self.windows.insert( + window_id, + WindowContext { + window, + ctx: wgpu_ctx, + main_window: false, + terminal_state: Some(TerminalState::default()), + }, + ); + } + Err(e) => error!("Failed to create terminal WGPU context: {}", e), + } + } + Err(e) => error!("Failed to create terminal window: {}", e), + } + } + + fn handle_terminal_input(&mut self, window_id: WindowId, key_event: KeyEvent) { + let Some(window_context) = self.windows.get_mut(&window_id) else { + return; + }; + let state = window_context.terminal_state.as_mut().unwrap(); + + if key_event.state.is_pressed() { + match key_event.logical_key { + winit::keyboard::Key::Named(NamedKey::Enter) => { + if !state.input_buffer.is_empty() { + state.command_queue.push(state.input_buffer.clone()); + state.input_history.push("\n\n".to_string()); + state.input_buffer.clear(); + state.needs_execution = true; + } + } + winit::keyboard::Key::Named(NamedKey::Backspace) => { + state.input_buffer.pop(); + } + winit::keyboard::Key::Named(NamedKey::Space) => { + state.input_buffer.push(' '); + } + winit::keyboard::Key::Character(c) => { + state.input_buffer.push_str(&c); + } + _ => {} + } + } + } + fn handle_close_requested(&mut self, window_id: WindowId) { if self.windows.remove(&window_id).is_some() { debug!("Window {:?} closed", window_id); @@ -175,6 +254,12 @@ impl App<'_> { if !key_event.state.is_pressed() || key_event.repeat { return; } + if let Some(window_context) = self.windows.get(&window_id) { + if window_context.terminal_state.is_some() { + self.handle_terminal_input(window_id, key_event); + return; + } + } match key_event.physical_key { winit::keyboard::PhysicalKey::Code(code) => match code { winit::keyboard::KeyCode::Space => { @@ -184,9 +269,10 @@ impl App<'_> { self.spawn_child_window(event_loop); } winit::keyboard::KeyCode::F11 => self.toggle_fullscreen(window_id), + winit::keyboard::KeyCode::F12 => self.create_terminal_window(event_loop), other => error!("Unimplemented keycode: {:?}", other), }, - _ => debug!("Received a keyboard event with no physical key"), + _ => error!("Unhandled key event: {:?}", key_event), } } @@ -268,9 +354,9 @@ impl App<'_> { let win_attr = unsafe { let base = Window::default_attributes() .with_title(title) + // .with_taskbar_icon(icon) .with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0))) .with_window_icon(icon.clone()); - // .with_taskbar_icon(icon); match main_ctx.window_handle() { Ok(handle) => { @@ -321,6 +407,7 @@ impl App<'_> { window, ctx: wgpu_ctx, main_window: false, + terminal_state: None, }, ); debug!("Spawned new child window: {:?}", window_id); @@ -337,21 +424,39 @@ impl App<'_> { fn handle_redraw_requested(&mut self, window_id: WindowId) { if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.ctx.draw(); + if let Some(terminal_state) = window_context.terminal_state.as_mut() { + if terminal_state.needs_execution { + for command in terminal_state.command_queue.drain(..) { + match evaluate_command(&command) { + Ok(output) => { + for line in output.lines() { + terminal_state.output_history.push(line.to_string()); + } + } + Err(e) => { + terminal_state.output_history.push(format!("Error: {}", e)); + } + } + } + terminal_state.needs_execution = false; + + terminal_state.scroll_offset = terminal_state + .output_history + .len() + .saturating_sub(terminal_state.max_history_lines); + } + } + + let terminal_state = window_context.terminal_state.as_mut(); + window_context.ctx.draw(terminal_state); 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) { if let Some(window_context) = self.windows.get_mut(&window_id) { // if we dont ignore size 0 this WILL cause a crash. DO NOT REMOVE + if new_size.height == 0 || new_size.width == 0 { error!("Attempted to resize a window to 0x0!"); return; diff --git a/engine/src/core/repl/commands.rs b/engine/src/core/repl/commands.rs index 4d64fdb..8c28a6c 100644 --- a/engine/src/core/repl/commands.rs +++ b/engine/src/core/repl/commands.rs @@ -10,27 +10,28 @@ use crate::error::{ZenyxError, ZenyxErrorKind}; pub struct HelpCommand; impl Command for HelpCommand { - fn execute(&self, _args: Option>) -> Result<(), ZenyxError> { + fn execute(&self, _args: Option>) -> Result { let manager = COMMAND_MANAGER.read(); - println!("Available commands:\n"); + let mut output = String::new(); + output.push_str("Available commands:\n\n"); for (_, command) in manager.get_commands() { - println!( - "Command: {}\n\tDescription: {}\n\tParameters: {}\n\tHelp: {}\n", + output.push_str(&format!( + "Command: {}\n\tDescription: {}\n\tParameters: {}\n\tHelp: {}\n\n", command.get_name().to_lowercase(), command.get_description(), command.get_params(), command.get_help() - ); + )); } if !manager.aliases.is_empty() { - println!("Aliases:"); + output.push_str("Aliases:\n"); for (alias, command) in &manager.aliases { - println!("\t{} -> {}", alias, command); + output.push_str(&format!("\t{} -> {}\n", alias, command)); } } - Ok(()) + Ok(output) } fn undo(&self) {} @@ -58,8 +59,7 @@ impl Command for HelpCommand { pub struct ClearCommand; impl Command for ClearCommand { - fn execute(&self, _args: Option>) -> Result<(), ZenyxError> { - println!("Clearing screen..., running command"); + fn execute(&self, _args: Option>) -> Result { let _result = if cfg!(target_os = "windows") { std::process::Command::new("cmd") .args(["/c", "cls"]) @@ -67,7 +67,7 @@ impl Command for ClearCommand { } else { std::process::Command::new("clear").spawn() }; - Ok(()) + Ok(String::from("Screen cleared.")) } fn undo(&self) {} @@ -95,7 +95,7 @@ impl Command for ClearCommand { pub struct ExitCommand; impl Command for ExitCommand { - fn execute(&self, args: Option>) -> Result<(), ZenyxError> { + fn execute(&self, args: Option>) -> Result { match args { Some(args) => { let exit_code = args[0].parse().map_err(|e| { @@ -141,7 +141,7 @@ impl Command for ExitCommand { pub struct ExecFile; impl Command for ExecFile { - fn execute(&self, args: Option>) -> Result<(), ZenyxError> { + fn execute(&self, args: Option>) -> Result { match args { Some(args) => { let file_path = PathBuf::from_str(&args[0]).map_err(|e| { @@ -161,23 +161,30 @@ impl Command for ExecFile { .with_source(e) .build() })?; - if let Ok(command) = eval(zscript) { - println!("{:#?}", command); - for (cmd_name, cmd_args) in command { + let mut script_output = String::new(); + if let Ok(commands_to_execute) = eval(zscript) { + for (cmd_name, cmd_args) in commands_to_execute { match COMMAND_MANAGER.read().execute(&cmd_name, cmd_args) { - Ok(_) => (), + Ok(output) => script_output.push_str(&output), Err(e) => { - println!( - "Error executing command returned an error: {}. Aborting script", - e - ); - break; + return Err(ZenyxError::builder( + ZenyxErrorKind::CommandExecution, + ) + .with_message(format!( + "Error executing command '{}' in script: {}", + cmd_name, e + )) + .build()); } } } + return Ok(script_output); + } else { + return Err(ZenyxError::builder(ZenyxErrorKind::CommandExecution) + .with_message("Failed to evaluate script") + .build()); } } - Ok(()) } None => Err(ZenyxError::builder(ZenyxErrorKind::CommandParsing) .with_message("Not enough arguments") @@ -212,12 +219,13 @@ pub struct CounterCommand { } impl Command for CounterCommand { - fn execute(&self, _args: Option>) -> Result<(), ZenyxError> { - // Increment the counter + fn execute(&self, _args: Option>) -> Result { let mut count = self.counter.write(); *count += 1; - println!("CounterCommand executed. Current count: {}", *count); - Ok(()) + Ok(format!( + "CounterCommand executed. Current count: {}", + *count + )) } fn undo(&self) { @@ -248,14 +256,15 @@ impl Command for CounterCommand { #[derive(Default)] pub struct PanicCommmand; impl Command for PanicCommmand { - fn execute(&self, args: Option>) -> Result<(), ZenyxError> { - if args.is_some() { - let panic_msg = &args.unwrap()[0]; - panic!("{}", panic_msg) + fn execute(&self, args: Option>) -> Result { + if let Some(args) = args { + let panic_msg = &args[0]; + panic!("{}", panic_msg); + } else { + let option: Option = None; + println!("Unwrapping None: {}", option.unwrap()); + panic!("Panic command was called"); } - let option: Option = None; - println!("Unwrapping None: {}", option.unwrap()); - panic!("Panic command was called") } fn undo(&self) {} diff --git a/engine/src/core/repl/handler.rs b/engine/src/core/repl/handler.rs index 45784ff..943e44b 100644 --- a/engine/src/core/repl/handler.rs +++ b/engine/src/core/repl/handler.rs @@ -1,6 +1,6 @@ -use std::collections::HashMap; use std::sync::LazyLock; +use ahash::AHashMap; use colored::Colorize; use parking_lot::RwLock; @@ -93,15 +93,15 @@ fn check_similarity(target: &str) -> Option { } pub struct CommandManager { - pub commands: HashMap>, - pub aliases: HashMap, + pub commands: AHashMap>, + pub aliases: AHashMap, } impl CommandManager { pub fn init() -> CommandManager { CommandManager { - commands: HashMap::new(), - aliases: HashMap::new(), + commands: AHashMap::new(), + aliases: AHashMap::new(), } } @@ -113,10 +113,10 @@ impl CommandManager { &self, command: &str, args: Option>, - ) -> Result<(), ZenyxError> { + ) -> Result { if let Some(command) = self.commands.get(command) { - command.execute(args)?; - Ok(()) + let output = command.execute(args)?; + Ok(output) } else { let corrected_cmd = check_similarity(command); if let Some(corrected_cmd) = corrected_cmd { @@ -132,12 +132,12 @@ impl CommandManager { } } - pub fn execute(&self, command: &str, args: Option>) -> Result<(), ZenyxError> { + pub fn execute(&self, command: &str, args: Option>) -> Result { match self.aliases.get(command) { Some(command) => self.execute(command, args), None => { - self.execute_command(command, args)?; - Ok(()) + let output = self.execute_command(command, args)?; + Ok(output) } } } @@ -156,7 +156,7 @@ impl CommandManager { } pub trait Command: Send + Sync { - fn execute(&self, args: Option>) -> Result<(), ZenyxError>; + fn execute(&self, args: Option>) -> Result; fn undo(&self); fn redo(&self); fn get_description(&self) -> String; diff --git a/engine/src/core/repl/input.rs b/engine/src/core/repl/input.rs index 627ad88..ebe932f 100644 --- a/engine/src/core/repl/input.rs +++ b/engine/src/core/repl/input.rs @@ -16,13 +16,8 @@ use tracing::{debug, error, info, warn}; use super::handler::COMMAND_MANAGER; use crate::error::{Result, ZenyxError, ZenyxErrorKind}; - +#[derive(Default)] struct CommandCompleter; -impl CommandCompleter { - fn new() -> Self { - CommandCompleter {} - } -} impl Completer for CommandCompleter { type Candidate = String; @@ -138,15 +133,19 @@ pub fn parse_command(input: &str) -> Result> { Ok(commands) } -pub fn evaluate_command(input: &str) -> Result<()> { +pub fn evaluate_command(input: &str) -> std::result::Result { if input.trim().is_empty() { - return Ok(()); + let err = ZenyxError::builder(ZenyxErrorKind::CommandParsing) + .with_message("Input was empty") + .build(); + return Err(err); } let commands = input .split(|c| c == ';' || c == '\n') .map(|slice| slice.to_string()) .collect::>(); + let mut output = String::new(); for command in commands { let command = command.trim(); @@ -166,20 +165,16 @@ pub fn evaluate_command(input: &str) -> Result<()> { } else { None }; - COMMAND_MANAGER - .read() - .execute(cmd_name, args) - .map_err(|e| { - ZenyxError::builder(ZenyxErrorKind::CommandExecution) - .with_message(format!("Failed to execute command: {cmd_name}")) - .with_context(format!("{e}")) - .build() - })?; + match COMMAND_MANAGER.read().execute(cmd_name, args) { + Ok(command_output) => output.push_str(&command_output), + Err(e) => { + return Err(e); + } + } } - Ok(()) + Ok(output) } - -fn format_time() -> String { +pub fn format_time() -> String { let now = SystemTime::now(); let duration = now.duration_since(UNIX_EPOCH).unwrap(); let total_seconds = duration.as_secs(); @@ -201,7 +196,7 @@ pub async fn handle_repl() -> Result<()> { let mut rl = Editor::::new()?; rl.set_helper(Some(MyHelper { hinter: HistoryHinter::new(), - completer: CommandCompleter::new(), + completer: CommandCompleter::default(), })); rl.bind_sequence( @@ -218,6 +213,7 @@ pub async fn handle_repl() -> Result<()> { loop { let time = format_time(); let prompt = format!("[{}/{}] {}", time, "SHELL", ">>\t"); + let sig = rl.readline(&prompt.bright_white()); match sig { diff --git a/engine/src/error.rs b/engine/src/error.rs index 3595964..f0b717f 100644 --- a/engine/src/error.rs +++ b/engine/src/error.rs @@ -115,7 +115,7 @@ impl std::fmt::Display for ZenyxError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "Error: {}{}{}{}", + "{}{}{}{}", self.kind, self.message .as_ref() diff --git a/engine/src/main.rs b/engine/src/main.rs index c654a72..d01326d 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -1,35 +1,65 @@ use core::{panic::set_panic_hook, repl::setup, splash}; +use std::{fs::OpenOptions, io::BufWriter}; use colored::Colorize; use tokio::runtime; +use tracing::level_filters::LevelFilter; #[allow(unused_imports)] use tracing::{debug, error, info, warn}; -use tracing::{level_filters::LevelFilter, subscriber::set_global_default}; +use tracing_subscriber::{Registry, fmt, layer::SubscriberExt}; use winit::event_loop::EventLoop; +pub mod cli; pub mod core; pub mod error; pub mod metadata; fn init_logger() { - let subscriber = tracing_subscriber::fmt() - .with_max_level(LevelFilter::DEBUG) + let stdout_layer = fmt::layer() .with_level(true) .compact() .pretty() .log_internal_errors(false) .without_time() - .with_thread_names(true) - .finish(); + .with_thread_names(true); - set_global_default(subscriber).expect("Failed to set default subscriber"); + let file_layer = fmt::layer() + .with_level(true) + .compact() + .with_ansi(false) + .log_internal_errors(false) + .without_time() + .with_writer(|| { + let file = OpenOptions::new() + .write(true) + .append(true) + .open("zenyx.log") + .unwrap_or_else(|_| { + eprintln!("Couldn't open log file, creating a new one."); + OpenOptions::new() + .write(true) + .create(true) + .open("zenyx.log") + .expect("Failed to create log file") + }); + BufWriter::new(file) + }) + .with_thread_names(true); + + let subscriber = Registry::default() + .with(LevelFilter::DEBUG) + .with(stdout_layer) + .with(file_layer); + + tracing::subscriber::set_global_default(subscriber).expect("Failed to set global subscriber"); } -#[tokio::main(flavor = "current_thread")] +#[tokio::main] async fn main() { init_logger(); + cli::parse(); let sysinfo = crate::metadata::SystemMetadata::current(); - set_panic_hook(); + // set_panic_hook(); setup(); splash::print_splash(); @@ -51,8 +81,6 @@ async fn main() { }; rt.block_on(core::repl::input::handle_repl()) }); - splash::print_splash(); - info!("Type 'help' for a list of commands."); match EventLoop::new() { Ok(event_loop) => { diff --git a/engine/src/metadata.rs b/engine/src/metadata.rs index a44b862..6dfb1fc 100644 --- a/engine/src/metadata.rs +++ b/engine/src/metadata.rs @@ -1,15 +1,183 @@ use std::collections::HashSet; use std::fmt; use std::str::FromStr; +use std::{env, error::Error, path::PathBuf, thread}; +use native_dialog::{MessageDialog, MessageType}; +use parking_lot::Once; use raw_cpuid::CpuId; use sysinfo::{CpuRefreshKind, RefreshKind, System}; +use tracing::error; use wgpu::DeviceType; mod build_info { include!(concat!(env!("OUT_DIR"), "/built.rs")); } +static INIT: parking_lot::Once = Once::new(); + +pub fn set_panic_hook() { + INIT.call_once(|| { + let default_hook = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |info| { + if let Err(e) = process_panic(info) { + eprintln!("Error in panic hook: {}", e); + default_hook(info); + } + std::process::exit(1); + })); + }); +} + +fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box> { + use std::io::Write; + + use colored::Colorize; + + let log_dir = PathBuf::from_str("./").expect("wtf, The current directory no longer exists?"); + if !log_dir.exists() { + std::fs::create_dir_all(&log_dir)?; + } + let log_path = log_dir.join("panic.log"); + + 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::() { + s + } else { + "" + }; + + writeln!(file, "Panic Occurred: {}", payload_str)?; + + if let Some(location) = info.location() { + writeln!(file, "Panic Location: {}", location)?; + } + + writeln!(file, "{}", capture_backtrace().sanitize_path())?; + + // Add more contextual information + writeln!(file, "\n--- Additional Information ---")?; + + // Rust Version + if let Ok(rust_version) = rust_version() { + writeln!(file, "Rust Version: {}", rust_version)?; + } + + // Command-line Arguments + writeln!(file, "Command-line Arguments:")?; + for arg in env::args() { + writeln!(file, " {}", arg)?; + } + + // Environment Variables (consider filtering sensitive ones) + writeln!(file, "\nEnvironment Variables (selected):")?; + let interesting_env_vars = ["PATH", "RUST_VERSION", "CARGO_TARGET_DIR", "HOME", "USER"]; + for (key, value) in env::vars() { + if interesting_env_vars.contains(&key.as_str()) { + writeln!(file, " {}: {}", key, value)?; + } + } + + // Current Working Directory + if let Ok(cwd) = env::current_dir() { + writeln!(file, "\nCurrent Working Directory: {}", cwd.display())?; + } + + // Thread Information + if let Some(thread) = thread::current().name() { + writeln!(file, "\nThread Name: {}", thread)?; + } else { + writeln!(file, "\nThread ID: {:?}", thread::current().id())?; + } + + let panic_msg = format!( + r#"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report. + +We have generated a detailed report file at '{}'. Submit an issue or email with the subject of 'Zenyx Crash Report' and include the report as an attachment. + +To submit the crash report: +https://codeberg.org/Caznix/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() + ); + + let final_msg = format!( + r#"{} + +For future reference, the error summary is as follows: +{} + +More details can be found in the crash report file."#, + panic_msg, payload_str + ); + + println!("{}", final_msg.red().bold()); + + if let Err(e) = MessageDialog::new() + .set_type(MessageType::Error) + .set_title("A fatal error in Zenyx has occurred") + .set_text(&final_msg) + .show_confirm() + { + error!("Failed to show message dialog: {e}") + } + + Ok(()) +} + +fn rust_version() -> Result> { + let version = env!("CARGO_PKG_RUST_VERSION"); + Ok(version.to_string()) +} + +fn capture_backtrace() -> String { + let mut backtrace = String::new(); + let sysinfo = crate::metadata::SystemMetadata::current(); + backtrace.push_str(&format!( + "--- System Information ---\n{}\n", + sysinfo.verbose_summary() + )); + + let trace = std::backtrace::Backtrace::force_capture(); + let message = format!("\n--- Backtrace ---\n\n"); + backtrace.push_str(&message); + backtrace.push_str(&format!("{trace:#}")); + + backtrace +} + +trait Sanitize { + fn sanitize_path(&self) -> String; +} + +impl Sanitize for str { + fn sanitize_path(&self) -> String { + let prefixes = ["/home/", "/Users/", "\\Users\\", "/opt/home/"]; + let mut result = String::from(self); + + for prefix in prefixes { + if let Some(start_index) = result.find(prefix) { + let start_of_user = start_index + prefix.len(); + let mut end_of_user = result[start_of_user..] + .find(|c| c == '/' || c == '\\') + .map(|i| start_of_user + i) + .unwrap_or(result.len()); + if end_of_user == start_of_user && start_of_user < result.len() { + end_of_user = result.len(); + } + result.replace_range(start_of_user..end_of_user, ""); + break; + } + } + result + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Memory { bytes: u64, @@ -489,7 +657,9 @@ impl EngineInfo { rustc_version: build_info::RUSTC_VERSION.to_string(), wgpu_version: build_info::WGPU_VERSION.to_string(), winit_version: build_info::WGPU_VERSION.to_string(), - commit_hash: build_info::GIT_COMMIT_HASH.to_string(), + commit_hash: build_info::GIT_COMMIT_HASH + .unwrap_or(&format!("UNKNOWN-{:?}", std::time::SystemTime::now())) + .to_string(), } } @@ -524,6 +694,38 @@ pub struct SystemMetadata { pub memory: SystemMemory, pub gpus: Vec, pub compile_info: EngineInfo, + pub os_info: OSInfo, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct OSInfo { + pub name: String, + pub version: Option, + pub kernel_version: Option, +} + +impl OSInfo { + pub fn current() -> Self { + let mut system = System::new(); + system.refresh_all(); + Self { + name: sysinfo::System::name().unwrap_or_else(|| build_info::TARGET.to_string()), + version: sysinfo::System::os_version(), + kernel_version: sysinfo::System::kernel_version(), + } + } + + pub fn verbose_info(&self) -> String { + format!( + "Operating System Information:\n\ + - Name: {}\n\ + - Version: {}\n\ + - Kernel Version: {}", + self.name, + self.version.as_deref().unwrap_or("Unknown"), + self.kernel_version.as_deref().unwrap_or("Unknown") + ) + } } impl SystemMetadata { @@ -533,6 +735,7 @@ impl SystemMetadata { memory: SystemMemory::current(), gpus: GPU::current(), compile_info: EngineInfo::current(), + os_info: OSInfo::current(), } } @@ -572,7 +775,8 @@ impl SystemMetadata { }; format!( - "System Information:\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}", + "System Information:\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}", + self.os_info.verbose_info(), self.cpu.verbose_info(), main_gpu_info, other_gpu_list, @@ -600,5 +804,6 @@ mod tests { assert!(!metadata.cpu.name.is_empty()); assert!(metadata.memory.total.as_bytes() > 0); assert!(!metadata.compile_info.pkg_version.is_empty()); + assert!(!metadata.os_info.name.is_empty()); } } diff --git a/zenyx.toml b/zenyx.toml new file mode 100644 index 0000000..e69de29