diff --git a/.vscode/launch.json b/.vscode/launch.json index dbb4757..fbc7892 100755 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,24 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug lyra lua-scripting", + "cargo": { + "args": [ + "build", + "--manifest-path", "${workspaceFolder}/examples/lua-scripting/Cargo.toml" + //"--bin=testbed", + ], + "filter": { + "name": "lua-scripting", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}/examples/lua-scripting" + }, { "type": "lldb", "request": "launch", diff --git a/Cargo.lock b/Cargo.lock index 960bd8b..4c305de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,15 +18,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" -[[package]] -name = "addr2line" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -39,17 +30,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" version = "0.8.11" @@ -417,21 +397,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide 0.8.0", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base64" version = "0.13.1" @@ -444,12 +409,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - [[package]] name = "bind_match" version = "0.1.2" @@ -532,6 +491,16 @@ dependencies = [ "piper", ] +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "built" version = "0.7.4" @@ -582,27 +551,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "calloop" version = "0.13.0" @@ -674,16 +622,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -750,12 +688,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "core-foundation" version = "0.9.4" @@ -781,7 +713,7 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "libc", ] @@ -920,7 +852,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", - "subtle", ] [[package]] @@ -983,37 +914,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f4e5af126dafd0741c2ad62d47f68b28602550102e5f0dd45c8a97fc8b49c29" -[[package]] -name = "elua" -version = "0.1.0" -dependencies = [ - "elua-derive", - "mlua-sys", - "thiserror", -] - -[[package]] -name = "elua-derive" -version = "0.1.0" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "reqwest", - "syn 2.0.77", - "tempdir", - "zip", -] - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1080,7 +980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2472baa9796d2ee497bd61690e3093a26935390d8ce0dd0ddc2db9b47a65898f" dependencies = [ "kiddo", - "rand 0.8.5", + "rand", "rand_distr", "rand_xoshiro", ] @@ -1142,7 +1042,7 @@ dependencies = [ "async-std", "fps_counter", "lyra-engine", - "rand 0.8.5", + "rand", "tracing", ] @@ -1171,21 +1071,6 @@ dependencies = [ "spin", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -1193,7 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -1207,27 +1092,12 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "fps_counter" version = "3.0.0" @@ -1246,12 +1116,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures-channel" version = "0.3.30" @@ -1286,33 +1150,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-core", - "futures-io", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - [[package]] name = "generator" version = "0.8.3" @@ -1367,12 +1204,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "gimli" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" - [[package]] name = "gl_generator" version = "0.14.0" @@ -1517,25 +1348,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "half" version = "2.4.1" @@ -1577,12 +1389,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1595,96 +1401,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "image" version = "0.25.2" @@ -1766,15 +1482,6 @@ dependencies = [ "libc", ] -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - [[package]] name = "instant" version = "0.1.13" @@ -1795,12 +1502,6 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "ipnet" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" - [[package]] name = "itertools" version = "0.12.1" @@ -1904,7 +1605,7 @@ dependencies = [ "log", "min-max-heap", "num-traits", - "rand 0.8.5", + "rand", "rayon", ] @@ -2065,7 +1766,7 @@ dependencies = [ "async-std", "fps_counter", "lyra-engine", - "rand 0.8.5", + "rand", "tracing", ] @@ -2078,7 +1779,7 @@ dependencies = [ "lyra-ecs-derive", "lyra-math", "paste", - "rand 0.8.5", + "rand", "thiserror", "tracing", ] @@ -2195,7 +1896,7 @@ dependencies = [ "notify", "notify-debouncer-full", "percent-encoding", - "rand 0.8.5", + "rand", "thiserror", "tracing", "uuid", @@ -2217,13 +1918,14 @@ version = "0.1.0" dependencies = [ "anyhow", "atomic_refcell", - "elua", "itertools 0.12.1", "lyra-ecs", "lyra-game", "lyra-reflect", "lyra-resource", "lyra-scripting-derive", + "mlua", + "parking_lot", "paste", "thiserror", "tracing", @@ -2257,7 +1959,7 @@ dependencies = [ "async-std", "fps_counter", "lyra-engine", - "rand 0.8.5", + "rand", "tracing", ] @@ -2303,7 +2005,7 @@ dependencies = [ "bitflags 2.6.0", "block", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -2359,22 +2061,21 @@ dependencies = [ ] [[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +name = "mlua" +version = "0.10.0-beta.2" +source = "git+https://github.com/mlua-rs/mlua?rev=4dddf3c18d4590f7c92214fa592c3faca3d2c812#4dddf3c18d4590f7c92214fa592c3faca3d2c812" dependencies = [ - "hermit-abi 0.3.9", - "libc", - "wasi", - "windows-sys 0.52.0", + "bstr", + "mlua-sys", + "num-traits", + "parking_lot", + "rustc-hash 2.0.0", ] [[package]] name = "mlua-sys" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16a9ba1dd2c6ac971b204262d434c24d65067038598f0638b64e5dca28d52b8" +version = "0.6.3" +source = "git+https://github.com/mlua-rs/mlua?rev=4dddf3c18d4590f7c92214fa592c3faca3d2c812#4dddf3c18d4590f7c92214fa592c3faca3d2c812" dependencies = [ "cc", "cfg-if", @@ -2402,23 +2103,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "ndk" version = "0.9.0" @@ -2494,7 +2178,7 @@ dependencies = [ "kqueue", "libc", "log", - "mio 0.8.11", + "mio", "walkdir", "windows-sys 0.48.0", ] @@ -2813,65 +2497,12 @@ dependencies = [ "objc2-foundation", ] -[[package]] -name = "object" -version = "0.36.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "orbclient" version = "0.3.47" @@ -2925,35 +2556,12 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash", - "sha2", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3085,7 +2693,7 @@ checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", "rustix", "tracing", @@ -3183,19 +2791,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -3204,7 +2799,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -3214,24 +2809,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -3248,7 +2828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.5", + "rand", ] [[package]] @@ -3257,7 +2837,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -3292,7 +2872,7 @@ dependencies = [ "once_cell", "paste", "profiling", - "rand 0.8.5", + "rand", "rand_chacha", "simd_helpers", "system-deps", @@ -3341,15 +2921,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3412,61 +2983,12 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "renderdoc-sys" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - [[package]] name = "rgb" version = "0.8.50" @@ -3485,12 +3007,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -3525,15 +3041,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustversion" version = "1.0.17" @@ -3555,15 +3062,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -3589,29 +3087,6 @@ dependencies = [ "tiny-skia", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.23" @@ -3659,29 +3134,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha2" version = "0.10.8" @@ -3810,16 +3262,6 @@ dependencies = [ "serde", ] -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "spin" version = "0.9.8" @@ -3856,12 +3298,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "1.0.109" @@ -3884,33 +3320,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "system-deps" version = "6.2.2" @@ -3930,29 +3339,6 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -dependencies = [ - "rand 0.4.6", - "remove_dir_all", -] - -[[package]] -name = "tempfile" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" -dependencies = [ - "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -4069,59 +3455,6 @@ dependencies = [ "strict-num", ] -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio 1.0.2", - "pin-project-lite", - "socket2", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - [[package]] name = "toml" version = "0.8.19" @@ -4156,12 +3489,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - [[package]] name = "tracing" version = "0.1.40" @@ -4266,12 +3593,6 @@ dependencies = [ "cc", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "ttf-parser" version = "0.24.1" @@ -4290,27 +3611,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -4335,17 +3641,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d360722e1f3884f5b14d332185f02ff111f771f0c76a313268fe6af1409aba96" -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - [[package]] name = "urlencoding" version = "2.1.3" @@ -4359,7 +3654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", - "rand 0.8.5", + "rand", ] [[package]] @@ -4385,12 +3680,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version-compare" version = "0.2.0" @@ -4413,15 +3702,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5143,16 +4423,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "x11-dl" version = "2.21.0" @@ -5237,55 +4507,6 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "zune-core" version = "0.4.12" diff --git a/examples/lua-scripting/scripts/test.lua b/examples/lua-scripting/scripts/test.lua index bac6e90..43fe413 100644 --- a/examples/lua-scripting/scripts/test.lua +++ b/examples/lua-scripting/scripts/test.lua @@ -1,9 +1,18 @@ ----Return the userdata's name from its metatable +---Return the userdata's name from its metatable. +--- +---Returns nil if the userdata doesn't have a metatable. ---@param val userdata ----@return string +---@return string|nil function udname(val) - return getmetatable(val).__name + local tbl = debug.getmetatable(val) + + if tbl == nil then + return nil + end + + return tbl.__name end + function on_init() local cube = world:request_res("../assets/cube-texture-embedded.gltf") diff --git a/examples/lua-scripting/src/main.rs b/examples/lua-scripting/src/main.rs index 1a4ed03..bf23e64 100644 --- a/examples/lua-scripting/src/main.rs +++ b/examples/lua-scripting/src/main.rs @@ -1,6 +1,6 @@ use lyra_engine::{ assets::{gltf::Gltf, ResourceManager}, - game::Game, + game::App, input::{ Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput, @@ -33,75 +33,73 @@ async fn main() { .bind( ACTLBL_MOVE_FORWARD_BACKWARD, &[ - ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0), - ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0), + ActionSource::Keyboard(KeyCode::KeyW).into_binding_modifier(1.0), + ActionSource::Keyboard(KeyCode::KeyS).into_binding_modifier(-1.0), ], ) .bind( ACTLBL_MOVE_LEFT_RIGHT, &[ - ActionSource::Keyboard(KeyCode::A).into_binding_modifier(-1.0), - ActionSource::Keyboard(KeyCode::D).into_binding_modifier(1.0), + ActionSource::Keyboard(KeyCode::KeyA).into_binding_modifier(-1.0), + ActionSource::Keyboard(KeyCode::KeyD).into_binding_modifier(1.0), ], ) .bind( ACTLBL_MOVE_UP_DOWN, &[ - ActionSource::Keyboard(KeyCode::C).into_binding_modifier(1.0), - ActionSource::Keyboard(KeyCode::Z).into_binding_modifier(-1.0), + ActionSource::Keyboard(KeyCode::KeyC).into_binding_modifier(1.0), + ActionSource::Keyboard(KeyCode::KeyZ).into_binding_modifier(-1.0), ], ) .bind( ACTLBL_LOOK_LEFT_RIGHT, &[ ActionSource::Mouse(MouseInput::Axis(MouseAxis::X)).into_binding(), - ActionSource::Keyboard(KeyCode::Left).into_binding_modifier(-1.0), - ActionSource::Keyboard(KeyCode::Right).into_binding_modifier(1.0), + ActionSource::Keyboard(KeyCode::ArrowLeft).into_binding_modifier(-1.0), + ActionSource::Keyboard(KeyCode::ArrowRight).into_binding_modifier(1.0), ], ) .bind( ACTLBL_LOOK_UP_DOWN, &[ ActionSource::Mouse(MouseInput::Axis(MouseAxis::Y)).into_binding(), - ActionSource::Keyboard(KeyCode::Up).into_binding_modifier(-1.0), - ActionSource::Keyboard(KeyCode::Down).into_binding_modifier(1.0), + ActionSource::Keyboard(KeyCode::ArrowUp).into_binding_modifier(-1.0), + ActionSource::Keyboard(KeyCode::ArrowDown).into_binding_modifier(1.0), ], ) .bind( ACTLBL_LOOK_ROLL, &[ - ActionSource::Keyboard(KeyCode::E).into_binding_modifier(-1.0), - ActionSource::Keyboard(KeyCode::Q).into_binding_modifier(1.0), + ActionSource::Keyboard(KeyCode::KeyE).into_binding_modifier(-1.0), + ActionSource::Keyboard(KeyCode::KeyQ).into_binding_modifier(1.0), ], ) .bind( "Debug", - &[ActionSource::Keyboard(KeyCode::B).into_binding()], + &[ActionSource::Keyboard(KeyCode::KeyB).into_binding()], ) .finish(), ) .finish(); - let world = game.world_mut(); + let world = &mut app.world; world.add_resource(action_handler); - game.with_plugin(InputActionPlugin); + app.with_plugin(InputActionPlugin); }; - Game::initialize() - .await - .with_plugin(lyra_engine::DefaultPlugins) - .with_plugin(setup_scene_plugin) - .with_plugin(action_handler_plugin) - .with_plugin(setup_script_plugin) - //.with_plugin(camera_debug_plugin) - .with_plugin(FreeFlyCameraPlugin) - .run() - .await; + let mut app = App::new(); + app.with_plugin(lyra_engine::DefaultPlugins); + app.with_plugin(setup_scene_plugin); + app.with_plugin(action_handler_plugin); + app.with_plugin(setup_script_plugin); + //app.with_plugin(camera_debug_plugin); + app.with_plugin(FreeFlyCameraPlugin); + app.run(); } fn setup_scene_plugin(app: &mut App) { - let world = game.world_mut(); - let resman = world.get_resource_mut::(); + let world = &mut app.world; + let resman = world.get_resource_mut::().unwrap(); let camera_gltf = resman .request::("../assets/AntiqueCamera.glb") .unwrap(); @@ -137,10 +135,10 @@ fn setup_scene_plugin(app: &mut App) { } fn setup_script_plugin(app: &mut App) { - game.with_plugin(LuaScriptingPlugin); + app.with_plugin(LuaScriptingPlugin); - let world = game.world_mut(); - let res_man = world.get_resource_mut::(); + let world = &mut app.world; + let res_man = world.get_resource_mut::().unwrap(); let script = res_man.request::("scripts/test.lua").unwrap(); res_man.watch("scripts/test.lua", false).unwrap(); drop(res_man); diff --git a/lyra-ecs/src/world.rs b/lyra-ecs/src/world.rs index 6c1a73e..7c048d5 100644 --- a/lyra-ecs/src/world.rs +++ b/lyra-ecs/src/world.rs @@ -509,7 +509,11 @@ impl World { /// Attempts to find a resource in the world and returns a NonNull pointer to it pub unsafe fn get_resource_ptr(&self) -> Option> { self.resources.get(&TypeId::of::()) - .map(|d| unsafe { NonNull::new_unchecked(d.data.as_ptr() as *mut T) }) + .map(|d| unsafe { + let data = d.data.borrow(); + let ptr = NonNull::from(&data.res); + NonNull::new_unchecked(ptr.as_ptr() as *mut T) + }) } pub fn archetype_count(&self) -> usize { diff --git a/lyra-game/src/game.rs b/lyra-game/src/game.rs index 3fbe90c..63c25a4 100755 --- a/lyra-game/src/game.rs +++ b/lyra-game/src/game.rs @@ -72,7 +72,7 @@ impl App { t.with(filter::Targets::new() // done by prefix, so it includes all lyra subpackages .with_target("lyra", Level::DEBUG) - .with_target("wgsl_preprocessor", Level::DEBUG) + .with_target("wgsl_preprocessor", Level::INFO) .with_target("wgpu", Level::WARN) .with_target("winit", Level::DEBUG) .with_default(Level::INFO)) diff --git a/lyra-game/src/input/system.rs b/lyra-game/src/input/system.rs index 6d719e9..a30d73a 100755 --- a/lyra-game/src/input/system.rs +++ b/lyra-game/src/input/system.rs @@ -21,6 +21,12 @@ fn write_scroll_delta(mouse_scroll_ev: &mut EventWriter, delta: &Mo mouse_scroll_ev.write(event); } +fn write_key_event(key_buttons: &mut ResMut>, physical_key: winit::keyboard::PhysicalKey, state: winit::event::ElementState) { + if let PhysicalKey::Code(code) = physical_key { + key_buttons.add_input_from_winit(code, state); + } +} + pub fn input_system( mut key_code_res: ResMut>, mut mouse_btn_res: ResMut>, @@ -37,9 +43,7 @@ pub fn input_system( while let Some(event) = window_ev.read() { match event.deref() { WindowEvent::KeyboardInput { event, .. } => { - if let PhysicalKey::Code(code) = event.physical_key { - key_code_res.add_input_from_winit(code, event.state); - } + write_key_event(&mut key_code_res, event.physical_key, event.state); }, WindowEvent::CursorMoved { position, .. } => { let exact = MouseExact { @@ -100,6 +104,9 @@ pub fn input_system( winit::event::DeviceEvent::MouseWheel { delta } => { write_scroll_delta(&mut mouse_scroll_ev, delta); }, + winit::event::DeviceEvent::Key(key) => { + write_key_event(&mut key_code_res, key.physical_key, key.state); + }, _ => { todo!("unhandled device event: {:?}", device.event); } diff --git a/lyra-reflect/src/impls/impl_std.rs b/lyra-reflect/src/impls/impl_std.rs index 4d68c05..cffb530 100644 --- a/lyra-reflect/src/impls/impl_std.rs +++ b/lyra-reflect/src/impls/impl_std.rs @@ -37,13 +37,13 @@ impl_reflect_trait_value!(String); impl_reflect_trait_value!(::core::option::Option); impl_reflect_trait_value!(::core::result::Result); -impl_reflect_trait_value!(::core::marker::PhantomData); +impl_reflect_trait_value!(::core::marker::PhantomData); impl_reflect_trait_value!(::std::sync::Arc); //impl_reflect_trait_value!(::std::sync::Arc>); //impl_reflect_trait_value!(::std::sync::RwLock); -impl_reflect_trait_value!(::core::ptr::NonNull); +//impl_reflect_trait_value!(::core::ptr::NonNull); impl Reflect for [T; N] { fn name(&self) -> String { diff --git a/lyra-reflect/src/lib.rs b/lyra-reflect/src/lib.rs index 8dedd78..a34da77 100644 --- a/lyra-reflect/src/lib.rs +++ b/lyra-reflect/src/lib.rs @@ -52,7 +52,7 @@ pub use registry::*; pub mod impls; -pub trait Reflect: Any { +pub trait Reflect: Any + Send + Sync { fn name(&self) -> String; fn type_id(&self) -> TypeId; diff --git a/lyra-scripting/Cargo.toml b/lyra-scripting/Cargo.toml index d57e2ed..dd23f12 100644 --- a/lyra-scripting/Cargo.toml +++ b/lyra-scripting/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" [features] default = ["lua"] -lua = ["dep:elua"] -teal = ["lua", "elua/teal"] +lua = ["dep:mlua"] +#teal = ["lua", "mlua/teal"] [dependencies] lyra-scripting-derive = { path = "lyra-scripting-derive" } @@ -22,11 +22,13 @@ tracing = "0.1.37" atomic_refcell = "0.1.13" # enabled with lua feature -#mlua = { version = "0.9.2", features = ["lua54"], optional = true } # luajit maybe? -elua = { path = "./elua", optional = true } +# +#mlua = { version = "0.9.9", features = ["lua54", "send"], optional = true } # luajit maybe? +mlua = { git = "https://github.com/mlua-rs/mlua", rev = "4dddf3c18d4590f7c92214fa592c3faca3d2c812", features = ["lua54", "send"], optional = true } # luajit maybe? +#elua = { path = "./elua", optional = true } itertools = "0.12.0" paste = "1.0.14" - +parking_lot = "0.12.3" [dev-dependencies] tracing-subscriber = { version = "0.3.16", features = [ "tracing-log" ] } diff --git a/lyra-scripting/lyra-scripting-derive/src/handle_macro.rs b/lyra-scripting/lyra-scripting-derive/src/handle_macro.rs index a00323e..9ee8ab2 100644 --- a/lyra-scripting/lyra-scripting-derive/src/handle_macro.rs +++ b/lyra-scripting/lyra-scripting-derive/src/handle_macro.rs @@ -145,24 +145,24 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro let field_creator = match &g.wrapper_type { Some(wrap) => { - quote!(#wrap(data.#field).as_lua(lua)) + quote!(#wrap(data.#field).into_lua(lua)) }, None => match &g.body { Some(body) => { quote!(#body) }, None => { - quote!(data.#field.clone().as_lua(lua)) + quote!(data.#field.clone().into_lua(lua)) } } }; quote! { - builder.field_getter(stringify!($field), |lua, this| { + fields.add_field_method_get(stringify!($field), |lua, this| { if let Some(data) = this.0.data_ref() { #field_creator } else { - Ok(Value::Nil) + Ok(mlua::Value::Nil) } }); } @@ -186,16 +186,12 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro } } - impl elua::Userdata for #wrapper_name { - fn name() -> String { - #ud_name.to_string() - } - - fn build<'a>(builder: &mut elua::UserdataBuilder<'a, Self>) { - builder.field_getter("path", |_, this| Ok(this.path())); - builder.field_getter("version", |_, this| Ok(this.version())); - builder.field_getter("uuid", |_, this| Ok(this.uuid().to_string())); - builder.field_getter("state", |_, this| { + impl mlua::UserData for #wrapper_name { + fn add_fields>(fields: &mut F) { + fields.add_field_method_get("path", |_, this| Ok(this.path())); + fields.add_field_method_get("version", |_, this| Ok(this.version())); + fields.add_field_method_get("uuid", |_, this| Ok(this.uuid().to_string())); + fields.add_field_method_get("state", |_, this| { let name = if this.is_loaded() { "ready" } else if this.get_error().is_some() { @@ -206,29 +202,31 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro }); #(#custom_getters)* + } - builder.method("is_watched", |_, this, ()| { + fn add_methods>(methods: &mut M) { + methods.add_method("is_watched", |_, this, ()| { Ok(this.is_watched()) }); - builder.method("is_loaded", |_, this, ()| { + methods.add_method("is_loaded", |_, this, ()| { Ok(this.is_loaded()) }); - builder.method("is_loaded", |_, this, ()| { + methods.add_method("is_loaded", |_, this, ()| { Ok(this.is_loaded()) }); - builder.method("wait_until_loaded", |_, this, ()| { + methods.add_method("wait_until_loaded", |_, this, ()| { this.wait_recurse_dependencies_load(); Ok(()) }); - builder.function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { + methods.add_function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { Ok(ScriptBorrow::from_component::>(None)) }); - builder.method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| { + methods.add_method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| { Ok(ScriptBorrow::from_component(Some(this.0.clone()))) }); @@ -236,12 +234,12 @@ pub(crate) fn lua_wrap_handle_impl(input: proc_macro::TokenStream) -> proc_macro } } - impl<'a> FromLua<'a> for #wrapper_name { - fn from_lua(_: &'a elua::State, val: elua::Value<'a>) -> elua::Result { + impl mlua::FromLua for #wrapper_name { + fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result { let tyname = val.type_name(); let ud = val.as_userdata() - .ok_or(elua::Error::type_mismatch(#ud_name, &tyname))?; - let ud = ud.as_ref::<#wrapper_name>()?; + .ok_or(mlua::Error::external(crate::lua::Error::type_mismatch(#ud_name, &tyname)))?; + let ud = ud.borrow::<#wrapper_name>()?; Ok(ud.clone()) } diff --git a/lyra-scripting/lyra-scripting-derive/src/lua_macro.rs b/lyra-scripting/lyra-scripting-derive/src/lua_macro.rs index a4ad512..2658ffb 100644 --- a/lyra-scripting/lyra-scripting-derive/src/lua_macro.rs +++ b/lyra-scripting/lyra-scripting-derive/src/lua_macro.rs @@ -156,13 +156,13 @@ impl MetaMethod { if Self::does_metamethod_have_arg(&self.name) { quote! { - builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (#wrapper_ident,)| { + methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (#wrapper_ident,)| { #body }); } } else { quote! { - builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, ()| { + methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, ()| { #body }); } @@ -173,12 +173,12 @@ impl MetaMethod { let body = Self::get_body_for_arg(&self.name, first, quote!(v)); quote! { - builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (#first,)| { + methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (#first,)| { #body }); } } else { - // an optional match arm that matches elua::Value:Number + // an optional match arm that matches mlua::Value:Number let number_arm = { let num_ident = self.arg.iter().find(|i| { let is = i.to_string(); @@ -195,7 +195,7 @@ impl MetaMethod { let body = Self::get_body_for_arg(&self.name, num_ident, quote!(n as #num_ident)); quote! { - elua::Value::Number(n) => { + mlua::Value::Number(n) => { #body }, } @@ -211,7 +211,7 @@ impl MetaMethod { let body = Self::get_method_body(&self.name, quote!(other.0)); quote! { - if let Ok(other) = ud.as_ref::<#i>() { + if let Ok(other) = ud.borrow::<#i>() { #body } } @@ -219,30 +219,30 @@ impl MetaMethod { }); quote! { - elua::Value::Userdata(ud) => { + mlua::Value::UserData(ud) => { #(#if_statements else)* // this is the body of the else statement { // try to get the name of the userdata for the error message - if let Ok(mt) = ud.get_metatable() { - if let Ok(name) = mt.get::<_, String>("__name") { - return Err(elua::Error::BadArgument { - func: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)), - arg_index: 2, - arg_name: Some("rhs".to_string()), - error: std::sync::Arc::new(elua::Error::Runtime( + if let Ok(mt) = ud.metatable() { + if let Ok(name) = mt.get::("__name") { + return Err(mlua::Error::BadArgument { + to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)), + pos: 2, + name: Some("rhs".to_string()), + cause: std::sync::Arc::new(mlua::Error::runtime( format!("cannot multiply with unknown userdata named {}", name) )) }); } } - Err(elua::Error::BadArgument { - func: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)), - arg_index: 2, - arg_name: Some("rhs".to_string()), - error: std::sync::Arc::new( - elua::Error::runtime("cannot multiply with unknown userdata") + Err(mlua::Error::BadArgument { + to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)), + pos: 2, + name: Some("rhs".to_string()), + cause: std::sync::Arc::new( + mlua::Error::runtime("cannot multiply with unknown userdata") ) }) } @@ -251,16 +251,16 @@ impl MetaMethod { }; quote! { - builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (elua::Value,)| { + methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (mlua::Value,)| { match v { #number_arm #userdata_arm - _ => Err(elua::Error::BadArgument { - func: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)), - arg_index: 2, - arg_name: Some("rhs".to_string()), - error: std::sync::Arc::new( - elua::Error::Runtime(format!("cannot multiply with {}", v.type_name())) + _ => Err(mlua::Error::BadArgument { + to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)), + pos: 2, + name: Some("rhs".to_string()), + cause: std::sync::Arc::new( + mlua::Error::runtime(format!("cannot multiply with {}", v.type_name())) ) }) } @@ -410,10 +410,10 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token let field_get_set_pairs = input.auto_fields.iter().map(|i| { let is = i.to_string(); quote! { - builder.field_getter(#is, |_, this| { + fields.add_field_method_get(#is, |_, this| { Ok(this.#i) }); - builder.field_setter(#is, |_, this, #i| { + fields.add_field_method_set(#is, |_, this, #i| { this.#i = #i; Ok(()) }); @@ -431,7 +431,7 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token quote! { // arguments for function are not specified since they can be implied from the call // to new(...) - builder.function("new", |_, ( #(#arg_names_clone),* )| { + methods.add_function("new", |_, ( #(#arg_names_clone),* )| { Ok(#wrapper_typename(#path::new( #(#arg_names),* ))) }); } @@ -452,11 +452,11 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token quote!() } else { quote! { - builder.method(#FN_NAME_INTERNAL_REFLECT, |_, this, ()| { + methods.add_method(#FN_NAME_INTERNAL_REFLECT, |_, this, ()| { Ok(crate::ScriptBorrow::from_component::<#path>(Some(this.0.clone()))) }); - builder.function(#FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { + methods.add_function(#FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { Ok(crate::ScriptBorrow::from_component::<#path>(None)) }); } @@ -480,22 +480,21 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token } } - impl<'lua> elua::FromLua<'lua> for #wrapper_typename { - fn from_lua(_lua: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result { + impl mlua::FromLua for #wrapper_typename { + fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result { match value { - elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), _ => panic!("Attempt to get {} from a {} value", stringify!(#wrapper_typename), value.type_name()), } } } - impl elua::Userdata for #wrapper_typename { - fn name() -> String { - stringify!(#type_name).to_string() + impl mlua::UserData for #wrapper_typename { + fn add_fields>(fields: &mut F) { + #(#field_get_set_pairs)* } - fn build<'a>(builder: &mut elua::UserdataBuilder<'a, Self>) { - #(#field_get_set_pairs)* + fn add_methods>(methods: &mut M) { #lua_reflects #new_func_tokens @@ -509,20 +508,5 @@ pub fn wrap_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::Token std::any::TypeId::of::<#path>() } } - - impl<'a> elua::FromLuaVec<'a> for #wrapper_typename { - fn from_lua_value_vec(state: &'a elua::State, mut values: elua::ValueVec<'a>) -> elua::Result { - use elua::FromLua; - - if let Some(val) = values.pop_front() { - #wrapper_typename::from_lua(state, val) - } else { - Err(elua::Error::IncorrectArgCount { - arg_expected: 1, - arg_count: values.len() as i32, - }) - } - } - } }) } \ No newline at end of file diff --git a/lyra-scripting/lyra-scripting-derive/src/vec_wrapper.rs b/lyra-scripting/lyra-scripting-derive/src/vec_wrapper.rs index abd217b..65ef6d0 100644 --- a/lyra-scripting/lyra-scripting-derive/src/vec_wrapper.rs +++ b/lyra-scripting/lyra-scripting-derive/src/vec_wrapper.rs @@ -49,8 +49,8 @@ impl VecWrapper { if axis_type_name.contains("b") { return quote! { - builder.field("FALSE", #wrapper_ident(#wrapped_path::FALSE)); - builder.field("TRUE", #wrapper_ident(#wrapped_path::TRUE)); + fields.add_field_method_get("FALSE", #wrapper_ident(#wrapped_path::FALSE)); + fields.add_field_method_get("TRUE", #wrapper_ident(#wrapped_path::TRUE)); }; } @@ -87,7 +87,7 @@ impl VecWrapper { let const_name = cnst.to_string(); quote! { - builder.field(#const_name, #wrapper_ident(#wrapped_path::#cnst)); + fields.add_field_method_get(#const_name, #wrapper_ident(#wrapped_path::#cnst)); } }); @@ -112,27 +112,37 @@ impl VecWrapper { optional_methods.push( quote! { - builder.method("clamp_length", + methods.add_method("clamp_length", |_, this, (min, max): (#type_id, #type_id)| { Ok(#wrapper_ident(this.clamp_length(min, max))) }); - builder.method("abs_diff_eq", + methods.add_method("abs_diff_eq", |_, this, (rhs, max_abs_diff): (#wrapper_ident, #type_id)| { Ok(this.abs_diff_eq(rhs.0, max_abs_diff)) }); - builder.method("ceil", + methods.add_method("ceil", |_, this, (): ()| { Ok(#wrapper_ident(this.ceil())) }); } ); - if vec_size != 4 { + if vec_size == 2 { + // angle_between is deprecated for Vec2, must use angle_to instead. optional_methods.push( quote! { - builder.method("angle_between", + methods.add_method("angle_to", + |_, this, (rhs,): (#wrapper_ident,)| { + Ok(this.angle_to(rhs.0)) + }); + } + ) + } else if vec_size != 4 { + optional_methods.push( + quote! { + methods.add_method("angle_between", |_, this, (rhs,): (#wrapper_ident,)| { Ok(this.angle_between(rhs.0)) }); @@ -144,7 +154,7 @@ impl VecWrapper { if !axis_type_name.contains("u") { optional_methods.push( quote! { - builder.method("abs", + methods.add_method("abs", |_, this, (): ()| { Ok(#wrapper_ident(this.abs())) }); @@ -154,21 +164,18 @@ impl VecWrapper { let optional_methods_iter = optional_methods.iter(); quote! { - - - builder.method("clamp", + methods.add_method("clamp", |_, this, (min, max): (#wrapper_ident, #wrapper_ident)| { Ok(#wrapper_ident(this.clamp(min.0, max.0))) }); // TODO: Not all Vecs have this - /* builder.method("clamp_length", + /* methods.add_method("clamp_length", |_, this, (min, max): (f32, f32)| { Ok(#wrapper_ident(this.clamp_length(min, max))) }); */ - - builder.method("to_array", + methods.add_method("to_array", |_, this, (): ()| { Ok(this.to_array()) }); diff --git a/lyra-scripting/src/host.rs b/lyra-scripting/src/host.rs index edbf590..f0cbf33 100644 --- a/lyra-scripting/src/host.rs +++ b/lyra-scripting/src/host.rs @@ -8,16 +8,23 @@ use crate::ScriptWorldPtr; pub enum ScriptError { #[error("{0}")] #[cfg(feature = "lua")] - MluaError(elua::Error), + LuaError(crate::lua::Error), #[error("{0}")] Other(anyhow::Error), } #[cfg(feature = "lua")] -impl From for ScriptError { - fn from(value: elua::Error) -> Self { - ScriptError::MluaError(value) +impl From for ScriptError { + fn from(value: mlua::Error) -> Self { + ScriptError::LuaError(crate::lua::Error::Mlua(value)) + } +} + +#[cfg(feature = "lua")] +impl From for ScriptError { + fn from(value: crate::lua::Error) -> Self { + ScriptError::LuaError(value) } } diff --git a/lyra-scripting/src/lib.rs b/lyra-scripting/src/lib.rs index 6d6a77a..5d2709b 100644 --- a/lyra-scripting/src/lib.rs +++ b/lyra-scripting/src/lib.rs @@ -16,7 +16,7 @@ pub use host::*; pub mod script; pub use script::*; -use lyra_game::game::Game; +use lyra_game::game::App; // required for some proc macros :( #[allow(unused_imports)] @@ -136,15 +136,15 @@ pub trait GameScriptExt { P: ScriptApiProvider + 'static; } -impl GameScriptExt for Game { +impl GameScriptExt for App { fn add_script_api_provider(&mut self, mut provider: P) where T: ScriptHost, P: ScriptApiProvider + 'static { - let world = self.world_mut(); + let world = &mut self.world; provider.prepare_world(world); - let mut providers = world.get_resource_mut::>(); + let mut providers = world.get_resource_mut::>().unwrap(); providers.add_provider(provider); } } \ No newline at end of file diff --git a/lyra-scripting/src/lua/dynamic_iter.rs b/lyra-scripting/src/lua/dynamic_iter.rs index 364b9fa..9eba864 100644 --- a/lyra-scripting/src/lua/dynamic_iter.rs +++ b/lyra-scripting/src/lua/dynamic_iter.rs @@ -6,44 +6,41 @@ use lyra_reflect::TypeRegistry; #[cfg(feature = "lua")] use super::ReflectLuaProxy; -use crate::ScriptWorldPtr; - #[cfg(feature = "lua")] -pub struct ReflectedItem<'a> { +pub struct ReflectedItem { //pub proxy: &'a ReflectLuaProxy, pub comp_ptr: NonNull, - pub comp_val: elua::Value<'a>, + pub comp_val: mlua::Value, } #[cfg(feature = "lua")] -pub struct ReflectedRow<'a> { +pub struct ReflectedRow { pub entity: Entity, - pub row: Vec>, + pub row: Vec, } -pub struct ReflectedIterator { - pub world: ScriptWorldPtr, +pub struct ReflectedIterator<'a> { + pub world: &'a lyra_ecs::World, pub dyn_view: DynamicViewStateIter, pub reflected_components: Option> } -impl ReflectedIterator { +impl<'a> ReflectedIterator<'a> { #[cfg(feature = "lua")] - pub fn next_lua<'a>(&mut self, lua: &'a elua::State) -> Option> { - use elua::AsLua; + pub fn next_lua(&mut self, lua: &mlua::Lua) -> Option { + use mlua::IntoLua; + + //let world = self.world.read(); + let n = self.dyn_view.next(&self.world); - let world = self.world.as_ref(); - let n = self.dyn_view.next(world); - - if let Some(row) = n { + if let Some((en, row)) = n { if self.reflected_components.is_none() { - let world = self.world.as_ref(); - self.reflected_components = world.try_get_resource::() + self.reflected_components = self.world.get_resource::() .map(|r| NonNull::from(r.deref())); } let mut dynamic_row = vec![]; - for d in row.row.iter() { + for d in row.iter() { let id = d.info.type_id().as_rust(); let reflected_components = unsafe { self.reflected_components.as_ref().unwrap().as_ref() }; @@ -54,7 +51,7 @@ impl ReflectedIterator { // TODO: properly handle this error .expect("Type does not have ReflectLuaProxy as a TypeData"); let value = (proxy.fn_as_lua)(lua, d.ptr.cast()).unwrap() - .as_lua(lua).unwrap(); + .into_lua(lua).unwrap(); dynamic_row.push(ReflectedItem { comp_ptr: d.ptr, @@ -63,7 +60,7 @@ impl ReflectedIterator { } let row = ReflectedRow { - entity: row.entity, + entity: en, row: dynamic_row }; diff --git a/lyra-scripting/src/lua/mod.rs b/lyra-scripting/src/lua/mod.rs index ce37ef5..6ab3803 100644 --- a/lyra-scripting/src/lua/mod.rs +++ b/lyra-scripting/src/lua/mod.rs @@ -2,7 +2,7 @@ pub mod dynamic_iter; pub use dynamic_iter::*; pub mod world; -use elua::FromLua; +use mlua::ObjectLike; pub use world::*; pub mod script; @@ -22,13 +22,48 @@ pub use system::*; use std::{any::TypeId, sync::Mutex}; -use lyra_ecs::{ - Component, ComponentInfo, World -}; +use lyra_ecs::World; use lyra_reflect::{Reflect, TypeRegistry}; use crate::ScriptBorrow; -pub type LuaContext = Mutex; +pub type LuaContext = Mutex; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("mismatched type, expected `{expected}`, got: `{got}`")] + TypeMismatch { + expected: String, + got: String, + }, + #[error("received nil value from Lua")] + Nil, + #[error("{0}")] + Mlua(#[from] mlua::Error) +} + +/* impl Into for Error { + fn into(self) -> mlua::Error { + match self { + Error::Mlua(error) => error, + _ => mlua::Error::external(self) + } + } +} + */ +impl From for mlua::Error { + fn from(value: Error) -> Self { + match value { + Error::Mlua(error) => error, + _ => mlua::Error::external(value) + } + } +} + +impl Error { + pub fn type_mismatch(expected: &str, got: &str) -> Self { + Self::TypeMismatch { expected: expected.into(), got: got.into() } + } +} /// Name of a Lua function that is used to Reflect the Userdata, but without a value. /// @@ -47,7 +82,7 @@ pub const FN_NAME_INTERNAL_REFLECT: &str = "__lyra_internal_reflect"; /// /// This is used for types that can be converted into components. When implementing this function, /// you must return a [`ScriptBorrow`] that contains the component for this userdata. -/// You can return [`elua::Value::Nil`] if for some reason the type could not be converted +/// You can return [`mlua::Value::Nil`] if for some reason the type could not be converted /// into a component. /// /// A good example of this is `LuaResHandle`. The resource handle is requested from the @@ -78,32 +113,26 @@ pub trait RegisterLuaType { /// Register a type to Lua that **is not wrapped**. fn register_lua_type<'a, T>(&mut self) where - T: Reflect + LuaProxy + Clone + elua::FromLua<'a> + elua::Userdata; + T: Reflect + LuaProxy + Clone + mlua::FromLua + mlua::UserData; /// Registers a type to Lua that is wrapped another type. /// This would be used for something like `UserdataRef`. fn register_lua_wrapper<'a, W>(&mut self) where - W: Reflect + LuaProxy + LuaWrapper + Clone + elua::FromLua<'a> + elua::Userdata; + W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua + mlua::UserData; /// Registers a type to Lua that can be converted into and from Lua types. fn register_lua_convert(&mut self) where - T: Clone + for<'a> elua::FromLua<'a> + for<'a> elua::AsLua<'a> + LuaWrapper + 'static; - - /// Registers a type to Lua that implements [`elua::TableProxy`] - fn register_lua_table_proxy<'a, T, W>(&mut self) - where - T: elua::TableProxy + 'static, - W: Component; + T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static; } impl RegisterLuaType for World { fn register_lua_type<'a, T>(&mut self) where - T: Reflect + LuaProxy + Clone + elua::FromLua<'a> + elua::Userdata + T: Reflect + LuaProxy + Clone + mlua::FromLua + mlua::UserData { - let mut registry = self.get_resource_mut::(); + let mut registry = self.get_resource_mut::().unwrap(); let type_id = TypeId::of::(); @@ -113,72 +142,40 @@ impl RegisterLuaType for World { fn register_lua_wrapper<'a, W>(&mut self) where - W: Reflect + LuaProxy + LuaWrapper + Clone + elua::FromLua<'a> + elua::Userdata + W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua + mlua::UserData { - let mut registry = self.get_resource_mut::(); + let mut registry = self.get_resource_mut::().unwrap(); let reg_type = registry.get_type_or_default(W::wrapped_type_id()); reg_type.add_data(ReflectLuaProxy::from_lua_proxy::()); - } + } fn register_lua_convert(&mut self) where - T: Clone + for<'a> elua::FromLua<'a> + for<'a> elua::AsLua<'a> + LuaWrapper + 'static, + T: Clone + mlua::FromLua + mlua::IntoLua + LuaWrapper + 'static, { - let mut registry = self.get_resource_mut::(); + let mut registry = self.get_resource_mut::().unwrap(); let reg_type = registry.get_type_or_default(T::wrapped_type_id()); reg_type.add_data(ReflectLuaProxy::from_as_and_from_lua::()); } - - fn register_lua_table_proxy<'a, T, C>(&mut self) - where - T: elua::TableProxy + 'static, - C: Component - { - let mut registry = self.get_resource_mut::(); - - let reg_type = registry.get_type_or_default(TypeId::of::()); - reg_type.add_data(ReflectLuaProxy::from_table_proxy::()); - drop(registry); - - let mut lookup = self.get_resource_or_else::(LuaTableProxyLookup::default); - lookup.typeid_from_name.insert(T::table_name(), TypeId::of::()); - - let info = ComponentInfo::new::(); - lookup.comp_info_from_name.insert(T::table_name(), info); - } } -impl<'lua> elua::FromLua<'lua> for ScriptBorrow { - fn from_lua(_: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result { +impl mlua::FromLua for ScriptBorrow { + fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result { match value { - elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), _ => unreachable!(), } } } -impl<'lua> elua::FromLuaVec<'lua> for ScriptBorrow { - fn from_lua_value_vec(state: &'lua elua::State, mut values: elua::ValueVec<'lua>) -> elua::Result { - if let Some(v) = values.pop_front() { - ScriptBorrow::from_lua(state, v) - } else { - Err(elua::Error::Nil) - } - } -} - -impl elua::Userdata for ScriptBorrow { - fn name() -> String { - "ScriptBorrow".to_string() - } - - fn build<'a>(_: &mut elua::UserdataBuilder<'a, Self>) { } +impl mlua::UserData for ScriptBorrow { + } /// Helper function used for reflecting userdata as a ScriptBorrow -pub fn reflect_user_data(ud: &elua::AnyUserdata) -> ScriptBorrow { - ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ()) +pub fn reflect_user_data(ud: &mlua::AnyUserData) -> ScriptBorrow { + ud.call_method::(FN_NAME_INTERNAL_REFLECT, ()) .expect("Type does not implement internal reflect method properly") } \ No newline at end of file diff --git a/lyra-scripting/src/lua/providers/ecs.rs b/lyra-scripting/src/lua/providers/ecs.rs index e01bba6..7e23477 100644 --- a/lyra-scripting/src/lua/providers/ecs.rs +++ b/lyra-scripting/src/lua/providers/ecs.rs @@ -17,7 +17,7 @@ impl ScriptApiProvider for LyraEcsApiProvider { world.register_lua_wrapper::(); world.register_lua_wrapper::(); - let mut registry = world.get_resource_mut::(); + let mut registry = world.get_resource_mut::().unwrap(); let reg_type = registry.get_type_or_default(TypeId::of::()); reg_type.add_data(ReflectLuaProxy::from_lua_proxy::()); @@ -39,7 +39,7 @@ impl ScriptApiProvider for LyraEcsApiProvider { fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { let ctx = ctx.lock().unwrap(); - let globals = ctx.globals()?; + let globals = ctx.globals(); globals.set("World", ctx.create_proxy::()?)?; globals.set("DynamicBundle", ctx.create_proxy::()?)?; globals.set("SceneComponent", ctx.create_proxy::()?)?; @@ -60,7 +60,7 @@ impl ScriptApiProvider for LyraEcsApiProvider { } } -fn create_reflect_table(lua: &elua::State) -> elua::Result { +fn create_reflect_table(lua: &mlua::Lua) -> mlua::Result { let table = lua.create_table()?; table.set(FN_NAME_INTERNAL_REFLECT_TYPE, lua.create_function(|_, ()| { Ok(ScriptBorrow::from_resource::(None)) diff --git a/lyra-scripting/src/lua/providers/math.rs b/lyra-scripting/src/lua/providers/math.rs index f0a33b7..3a675a3 100644 --- a/lyra-scripting/src/lua/providers/math.rs +++ b/lyra-scripting/src/lua/providers/math.rs @@ -23,7 +23,7 @@ impl ScriptApiProvider for LyraMathApiProvider { /* let bytes = include_bytes!("../../../scripts/lua/math/transform.lua"); ctx.load("lyra/math/transform.lua", bytes.as_slice())?.execute(())?; */ - let globals = ctx.globals()?; + let globals = ctx.globals(); globals.set("Vec3", ctx.create_proxy::()?)?; globals.set("Quat", ctx.create_proxy::()?)?; globals.set("Transform", ctx.create_proxy::()?)?; diff --git a/lyra-scripting/src/lua/providers/util.rs b/lyra-scripting/src/lua/providers/util.rs index 2ef6bc9..ebb92c1 100644 --- a/lyra-scripting/src/lua/providers/util.rs +++ b/lyra-scripting/src/lua/providers/util.rs @@ -1,11 +1,12 @@ -use std::sync::{Mutex, Arc}; +use std::{ops::Deref, sync::{Arc, Mutex}}; -use tracing::{debug_span, debug}; +use mlua::{AnyUserData, ObjectLike}; +use tracing::{debug, debug_span}; use crate::{ScriptApiProvider, ScriptData}; /// This Api provider provides some nice utility functions. -/// +/// /// Functions: /// ```lua /// ---@param str (string) A format string. @@ -17,99 +18,122 @@ use crate::{ScriptApiProvider, ScriptData}; pub struct UtilityApiProvider; impl ScriptApiProvider for UtilityApiProvider { - type ScriptContext = Mutex; + type ScriptContext = Mutex; - fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn expose_api( + &mut self, + data: &ScriptData, + ctx: &mut Self::ScriptContext, + ) -> Result<(), crate::ScriptError> { let ctx = ctx.lock().unwrap(); - //fn printf(lua: &elua::State, (mut text, formats): (String, elua::Variadic)) -> elua::Result<()> { - let printf = |lua: &elua::State, (mut text, formats): (String, elua::Variadic)| { - let mut formatted = String::new(); - let mut arg_num = 0; + //fn printf(lua: &mlua::State, (mut text, formats): (String, mlua::Variadic)) -> mlua::Result<()> { + let printf = + |lua: &mlua::Lua, (mut text, formats): (String, mlua::Variadic)| { + let mut formatted = String::new(); + let mut arg_num = 0; - while let Some(start) = text.find("{}") { - let val_str = match formats.get(arg_num) { - Some(v) => match v { - elua::Value::Nil => "nil".to_string(), - elua::Value::Boolean(b) => b.to_string(), - elua::Value::Number(n) => n.to_string(), - elua::Value::String(s) => s.clone(), - elua::Value::Table(_) => { - return Err(elua::Error::runtime("unable to get string representation of Table")); + while let Some(start) = text.find("{}") { + let val_str = match formats.get(arg_num) { + Some(v) => match v { + mlua::Value::Nil => "nil".to_string(), + mlua::Value::Boolean(b) => b.to_string(), + mlua::Value::Integer(n) => n.to_string(), + mlua::Value::Number(n) => n.to_string(), + mlua::Value::String(s) => s.to_string_lossy().to_string(), + mlua::Value::Table(_) => { + return Err(mlua::Error::runtime( + "unable to get string representation of Table", + )); + }, + mlua::Value::Function(_) => { + return Err(mlua::Error::runtime( + "unable to get string representation of Function", + )); + }, + mlua::Value::Thread(_) => { + return Err(mlua::Error::runtime( + "unable to get string representation of Thread", + )); + }, + mlua::Value::UserData(ud) => { + if let Ok(tos) = + ud.get::(mlua::MetaMethod::ToString.name()) + { + tos.call::(())? + } else { + return Err(mlua::Error::runtime( + "UserData does not implement MetaMethod '__tostring'", + )); + } + }, + mlua::Value::LightUserData(_) => { + return Err(mlua::Error::runtime( + "unable to get string representation of LightUserData", + )); + }, + mlua::Value::Error(error) => { + return Err(error.deref().clone()); + }, }, - elua::Value::Function(_) => { - return Err(elua::Error::runtime("unable to get string representation of Function")); - }, - elua::Value::Thread(_) => { - return Err(elua::Error::runtime("unable to get string representation of Thread")); - }, - elua::Value::Userdata(ud) => { - if let Ok(tos) = ud.get::<_, elua::Function>(elua::MetaMethod::ToString) { - tos.exec::<_, String>(())? - } else { - return Err(elua::Error::runtime("UserData does not implement MetaMethod '__tostring'")); + None => { + let got_args = arg_num; // - 1; + + // continue searching for {} to get the number of format spots for the error message. + while let Some(start) = text.find("{}") { + text = text[start + 2..].to_string(); + arg_num += 1; } - }, - elua::Value::None => "None".to_string(), - elua::Value::Multi(_) => { - return Err(elua::Error::runtime("unable to get string representation of ValueVec")); - }, - }, - None => { - let got_args = arg_num;// - 1; - // continue searching for {} to get the number of format spots for the error message. - while let Some(start) = text.find("{}") { - text = text[start + 2..].to_string(); - arg_num += 1; + return Err(mlua::Error::BadArgument { + to: Some("printf".into()), + pos: 2, + name: Some("fmt...".into()), + cause: Arc::new(mlua::Error::runtime(format!( + "not enough args \ + given for the amount of format areas in the string. Expected {}, \ + got {}.", + arg_num, got_args + ))), + }); } + }; - return Err(elua::Error::BadArgument { - func: Some("printf".to_string()), - arg_index: 2, - arg_name: Some("fmt...".to_string()), - error: Arc::new(elua::Error::Runtime(format!( - "not enough args \ - given for the amount of format areas in the string. Expected {}, \ - got {}.", arg_num, got_args - ))) - }) - }, - }; + formatted = format!("{}{}{}", formatted, &text[0..start], val_str); - formatted = format!("{}{}{}", formatted, &text[0..start], val_str); + text = text[start + 2..].to_string(); - text = text[start + 2..].to_string(); + arg_num += 1; + } - arg_num += 1; - } + if arg_num < formats.len() { + return Err(mlua::Error::BadArgument { + to: Some("printf".into()), + pos: 2, + name: Some("fmt...".into()), + cause: Arc::new(mlua::Error::runtime(format!( + "got more args \ + than format areas in the string. Expected {}, got {}.", + formats.len(), + arg_num + ))), + }); + } - if arg_num < formats.len() { - return Err(elua::Error::BadArgument { - func: Some("printf".to_string()), - arg_index: 2, - arg_name: Some("fmt...".to_string()), - error: Arc::new(elua::Error::Runtime(format!( - "got more args \ - than format areas in the string. Expected {}, got {}.", formats.len(), arg_num - ))) - }) - } - - formatted = format!("{}{}", formatted, text); + formatted = format!("{}{}", formatted, text); - lua.globals()? - .get::<_, elua::Function>("print")? - .exec::<_, ()>(formatted)?; + lua.globals() + .get::("print")? + .call::<()>(formatted)?; - Ok(()) - }; - - let script_name_reg = ctx.registry_insert(data.name.clone())?; + Ok(()) + }; + + let script_name_reg = ctx.create_registry_value(data.name.clone())?; let printf_func = ctx.create_function(printf)?; let print_func = ctx.create_function(move |lua, text: String| { - let name = lua.registry_get::(script_name_reg)?; + let name = lua.registry_value::(&script_name_reg)?; let _span = debug_span!("lua", script = &name).entered(); debug!(target: "lyra_scripting::lua", "{}", text); @@ -117,18 +141,42 @@ impl ScriptApiProvider for UtilityApiProvider { Ok(()) })?; - let globals = ctx.globals()?; + // a custom implementation of `getmetatable` is required since mlua protects __metatable, + // making it impossible to get the metatable of userdata. + let getmetatable_func = ctx.create_function(|lua, ud: AnyUserData| { + // the userdata is left on the stack from `lua_getmetatable`, so that needs to be + // included in the returns + let (_ud, table): (mlua::AnyUserData, mlua::Table) = unsafe { + lua.exec_raw(ud, |state| { + mlua::ffi::lua_getmetatable(state, -1); + }) + }?; + + Ok(table) + })?; + + let globals = ctx.globals(); globals.set("printf", printf_func)?; globals.set("print", print_func)?; - + globals.set("getmetatable2", getmetatable_func)?; + Ok(()) } - fn setup_script(&mut self, _data: &ScriptData, _ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn setup_script( + &mut self, + _data: &ScriptData, + _ctx: &mut Self::ScriptContext, + ) -> Result<(), crate::ScriptError> { Ok(()) } - fn update_script_environment(&mut self, _world: crate::ScriptWorldPtr, _data: &ScriptData, _ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn update_script_environment( + &mut self, + _world: crate::ScriptWorldPtr, + _data: &ScriptData, + _ctx: &mut Self::ScriptContext, + ) -> Result<(), crate::ScriptError> { Ok(()) } -} \ No newline at end of file +} diff --git a/lyra-scripting/src/lua/proxy.rs b/lyra-scripting/src/lua/proxy.rs index f43faf2..7017da1 100644 --- a/lyra-scripting/src/lua/proxy.rs +++ b/lyra-scripting/src/lua/proxy.rs @@ -1,12 +1,12 @@ use std::{any::TypeId, collections::HashMap, ptr::NonNull}; -use elua::{FromLua, TableProxy, AsLua}; +use mlua::{ObjectLike, IntoLua}; use lyra_ecs::{ComponentInfo, DynamicBundle}; use lyra_reflect::Reflect; use crate::{ScriptBorrow, ScriptDynamicBundle}; -use super::FN_NAME_INTERNAL_REFLECT; +use super::{Error, FN_NAME_INTERNAL_REFLECT}; pub trait LuaWrapper { /// The type id of the wrapped type. @@ -15,40 +15,39 @@ pub trait LuaWrapper { /// A trait that used to convert something into lua, or to set something to a value from lua. pub trait LuaProxy { - fn as_lua_value<'lua>( - lua: &'lua elua::State, + fn as_lua_value( + lua: &mlua::Lua, this: &dyn Reflect, - ) -> elua::Result>; + ) -> mlua::Result; fn apply( - lua: &elua::State, + lua: &mlua::Lua, this: &mut dyn Reflect, - value: &elua::Value, - ) -> elua::Result<()>; + value: &mlua::Value, + ) -> mlua::Result<()>; } impl<'a, T> LuaProxy for T where - T: Reflect + Clone + elua::FromLua<'a> + elua::Userdata + T: Reflect + Clone + mlua::FromLua + mlua::UserData { - fn as_lua_value<'lua>( - lua: &'lua elua::State, + fn as_lua_value( + lua: &mlua::Lua, this: &dyn Reflect, - ) -> elua::Result> { + ) -> mlua::Result { let this = this.as_any().downcast_ref::().unwrap(); - lua.create_userdata(this.clone()) - .and_then(|ud| ud.as_lua(lua)) + this.clone().into_lua(lua) } fn apply( - _: &elua::State, + _: &mlua::Lua, this: &mut dyn Reflect, - apply: &elua::Value, - ) -> elua::Result<()> { + apply: &mlua::Value, + ) -> mlua::Result<()> { let this = this.as_any_mut().downcast_mut::().unwrap(); let apply = apply.as_userdata() .expect("Somehow a non-userdata Lua Value was provided to a LuaProxy") - .as_ref::()?; + .borrow::()?; *this = apply.clone(); @@ -67,12 +66,12 @@ pub struct LuaTableProxyLookup { #[derive(Clone)] pub struct ReflectLuaProxy { pub fn_as_lua: - for<'a> fn(lua: &'a elua::State, this_ptr: NonNull<()>) -> elua::Result>, + for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull<()>) -> mlua::Result, pub fn_apply: for<'a> fn( - lua: &'a elua::State, + lua: &'a mlua::Lua, this_ptr: NonNull<()>, - value: &'a elua::Value<'a>, - ) -> elua::Result<()>, + value: &'a mlua::Value, + ) -> mlua::Result<()>, } impl ReflectLuaProxy { @@ -82,7 +81,7 @@ impl ReflectLuaProxy { T: Reflect + LuaProxy { Self { - fn_as_lua: |lua, this| -> elua::Result { + fn_as_lua: |lua, this| -> mlua::Result { let this = unsafe { this.cast::().as_ref() }; ::as_lua_value(lua, this) }, @@ -93,42 +92,19 @@ impl ReflectLuaProxy { } } - pub fn from_table_proxy() -> Self - where - T: TableProxy - { - Self { - fn_as_lua: |lua, this| -> elua::Result { - let this = unsafe { this.cast::().as_ref() }; - this.as_table(lua) - .and_then(|t| t.as_lua(lua)) - }, - fn_apply: |lua, ptr, value| { - let this = unsafe { ptr.cast::().as_mut() }; - let table = value.as_table() - .expect("Somehow a non-Table Lua Value was provided to a TableProxy"); - let new_val = T::from_table(lua, table.clone())?; - - *this = new_val; - - Ok(()) - }, - } - } - /// Create from a type that implements FromLua and AsLua pub fn from_as_and_from_lua() -> Self where - T: for<'a> elua::FromLua<'a> + for<'a> elua::AsLua<'a> + Clone + T: mlua::FromLua + mlua::IntoLua + Clone { Self { - fn_as_lua: |lua, this| -> elua::Result { + fn_as_lua: |lua, this| -> mlua::Result { let this = unsafe { this.cast::().as_ref() }; - this.clone().as_lua(lua) + this.clone().into_lua(lua) }, fn_apply: |lua, ptr, value| { let this = unsafe { ptr.cast::().as_mut() }; - let new_val = T::from_lua(lua, value.clone())?; + let new_val = T::from_lua(value.clone(), lua)?; *this = new_val; @@ -138,42 +114,27 @@ impl ReflectLuaProxy { } } -impl<'lua> elua::FromLua<'lua> for ScriptDynamicBundle { - fn from_lua(_: &'lua elua::State, val: elua::Value<'lua>) -> elua::Result { +impl mlua::FromLua for ScriptDynamicBundle { + fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result { match val { - elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), - elua::Value::Nil => Err(elua::Error::Nil), + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), + mlua::Value::Nil => Err(Error::Nil.into()), _ => unreachable!(), } } } -impl<'lua> elua::FromLuaVec<'lua> for ScriptDynamicBundle { - fn from_lua_value_vec(state: &'lua elua::State, mut values: elua::ValueVec<'lua>) -> elua::Result { - if let Some(v) = values.pop_front() { - Ok(ScriptDynamicBundle::from_lua(state, v)?) - } else { - Err(elua::Error::Nil) - } - } -} +impl mlua::UserData for ScriptDynamicBundle { + fn add_methods>(methods: &mut M) { + methods.add_function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new()))); + methods.add_method_mut("push", |_, this, comp: mlua::AnyUserData| { + let script_brw = comp.call_method::(FN_NAME_INTERNAL_REFLECT, ())?; + let reflect = script_brw.reflect_branch.as_component_unchecked(); -impl elua::Userdata for ScriptDynamicBundle { - fn name() -> String { - "Bundle".to_string() - } + let refl_data = script_brw.data.unwrap(); + reflect.bundle_insert(&mut this.0, refl_data); - fn build<'a>(builder: &mut elua::UserdataBuilder<'a, Self>) { - builder - .function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new()))) - .method_mut("push", |_, this, comp: elua::AnyUserdata| { - let script_brw = comp.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?; - let reflect = script_brw.reflect_branch.as_component_unchecked(); - - let refl_data = script_brw.data.unwrap(); - reflect.bundle_insert(&mut this.0, refl_data); - - Ok(()) - }); + Ok(()) + }); } } \ No newline at end of file diff --git a/lyra-scripting/src/lua/script.rs b/lyra-scripting/src/lua/script.rs index 0a6e515..ed58c2f 100644 --- a/lyra-scripting/src/lua/script.rs +++ b/lyra-scripting/src/lua/script.rs @@ -1,31 +1,32 @@ use std::sync::Mutex; -use elua::{AsLua, StdLibraries}; +use mlua::{IntoLua, StdLib}; use crate::{ScriptHost, ScriptError, ScriptWorldPtr, ScriptEntity}; #[derive(Default)] pub struct LuaHost; -fn try_call_lua_function(lua: &elua::State, fn_name: &str) -> Result<(), ScriptError> { - let globals = lua.globals()?; +fn try_call_lua_function(lua: &mlua::Lua, fn_name: &str) -> Result<(), ScriptError> { + let globals = lua.globals(); - if globals.has_key(fn_name)? { - let lua_fn = globals.get::<_, elua::Function>(fn_name)?; - lua_fn.exec(()) - .map_err(ScriptError::MluaError)?; + if globals.contains_key(fn_name)? { + let lua_fn = globals.get::(fn_name)?; + lua_fn.call::<()>(()) + .map_err(ScriptError::from)?; } Ok(()) } impl ScriptHost for LuaHost { - type ScriptContext = Mutex; + type ScriptContext = Mutex; fn load_script(&mut self, script: &[u8], script_data: &crate::ScriptData, providers: &mut crate::ScriptApiProviders) -> Result { let mut ctx = Mutex::new({ - let s = elua::State::new(); - s.expose_libraries(StdLibraries::all()); + // unsafe is required to allow the debug module + let s = unsafe { mlua::Lua::unsafe_new() }; + s.load_std_libs(StdLib::ALL)?; s }); @@ -35,9 +36,9 @@ impl ScriptHost for LuaHost { } let lua = ctx.lock().unwrap(); - lua.load(&script_data.name, script)? - .execute(()) - .map_err(|e| ScriptError::MluaError(e))?; + lua.load(script) + .exec() + .map_err(|e| ScriptError::LuaError(super::Error::Mlua(e)))?; drop(lua); Ok(ctx) @@ -65,9 +66,9 @@ impl ScriptHost for LuaHost { let ctx = ctx.lock().expect("Failure to get Lua ScriptContext"); - let globals = ctx.globals()?; - globals.set("world", world.as_lua(&ctx)?)?; - globals.set("entity", ScriptEntity(script_data.entity).as_lua(&ctx)?)?; + let globals = ctx.globals(); + globals.set("world", world.into_lua(&ctx)?)?; + globals.set("entity", ScriptEntity(script_data.entity).into_lua(&ctx)?)?; try_call_lua_function(&ctx, function_name)?; diff --git a/lyra-scripting/src/lua/system.rs b/lyra-scripting/src/lua/system.rs index 1456e41..9d961b8 100644 --- a/lyra-scripting/src/lua/system.rs +++ b/lyra-scripting/src/lua/system.rs @@ -5,7 +5,7 @@ use lyra_reflect::TypeRegistry; use lyra_resource::ResourceManager; use tracing::{debug, debug_span, error, trace}; -use crate::{GameScriptExt, ScriptApiProviders, ScriptContexts, ScriptData, ScriptError, ScriptHost, ScriptList, ScriptWorldPtr}; +use crate::{GameScriptExt, ScriptApiProviders, ScriptContexts, ScriptData, ScriptError, ScriptHost, ScriptList, ScriptWorldPtrGuard}; use super::{providers::{LyraEcsApiProvider, LyraMathApiProvider, UtilityApiProvider}, LuaContext, LuaHost, LuaLoader, LuaScript}; @@ -40,7 +40,8 @@ pub fn lua_scripts_create_contexts( trace!("Finished setting up script"); // call on_init, handle the error - let world_ptr = ScriptWorldPtr::from_ref(&world); + let world_guard = unsafe { ScriptWorldPtrGuard::new(world) }; + let world_ptr = (*world_guard).clone(); match host.call_script( world_ptr, &script_data, @@ -50,7 +51,7 @@ pub fn lua_scripts_create_contexts( ) { Ok(()) => {} Err(e) => match e { - ScriptError::MluaError(m) => { + ScriptError::LuaError(m) => { error!("Script '{}' ran into an error: {}", script.name(), m); } ScriptError::Other(_) => return Err(e.into()), @@ -114,10 +115,11 @@ pub fn lua_scripts_reload_system( } fn lua_call_script_function(world: &mut World, stage_name: &str) -> anyhow::Result<()> { - let world_ptr = ScriptWorldPtr::from_ref(&world); - let mut host = world.get_resource_mut::(); - let mut contexts = world.get_resource_mut::>(); - let mut providers = world.get_resource_mut::>(); + let world_guard = unsafe { ScriptWorldPtrGuard::new(world) }; + let world_ptr = (*world_guard).clone(); + let mut host = world.get_resource_mut::().unwrap(); + let mut contexts = world.get_resource_mut::>().unwrap(); + let mut providers = world.get_resource_mut::>().unwrap(); for (en, scripts) in world.view_iter::<(Entities, &ScriptList)>() { for script in scripts.iter() { @@ -143,7 +145,7 @@ fn lua_call_script_function(world: &mut World, stage_name: &str) -> anyhow::Resu ) { Ok(()) => {} Err(e) => match e { - ScriptError::MluaError(m) => { + ScriptError::LuaError(m) => { error!("Script '{}' ran into an error: {}", script.name(), m); } ScriptError::Other(_) => return Err(e.into()), @@ -190,8 +192,8 @@ pub fn lua_script_last_stage_system(world: &mut World) -> anyhow::Result<()> { pub struct LuaScriptingPlugin; impl Plugin for LuaScriptingPlugin { - fn setup(&mut self, game: &mut lyra_game::game::Game) { - let world = game.world_mut(); + fn setup(&mut self, app: &mut lyra_game::game::App) { + let world = &mut app.world; world.add_resource_default::(); @@ -200,16 +202,16 @@ impl Plugin for LuaScriptingPlugin { world.add_resource_default::>(); let loader = world - .try_get_resource_mut::() + .get_resource_mut::() .expect("Add 'ResourceManager' to the world before trying to add this plugin"); loader.register_loader::(); drop(loader); - game.add_script_api_provider::(UtilityApiProvider); - game.add_script_api_provider::(LyraEcsApiProvider); - game.add_script_api_provider::(LyraMathApiProvider); + app.add_script_api_provider::(UtilityApiProvider); + app.add_script_api_provider::(LyraEcsApiProvider); + app.add_script_api_provider::(LyraMathApiProvider); - game.add_system_to_stage( + app.add_system_to_stage( GameStages::First, "lua_create_contexts", lua_scripts_create_contexts, diff --git a/lyra-scripting/src/lua/world.rs b/lyra-scripting/src/lua/world.rs index b2ae8ca..1414f5a 100644 --- a/lyra-scripting/src/lua/world.rs +++ b/lyra-scripting/src/lua/world.rs @@ -1,32 +1,31 @@ -use std::{ptr::NonNull, sync::Arc}; +use std::{ops::DerefMut, ptr::NonNull, sync::Arc}; use crate::{ScriptBorrow, ScriptEntity, ScriptWorldPtr}; -use elua::AsLua; -use lyra_ecs::{query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType}, CommandQueue, Commands, DynamicBundle, World}; +use lyra_ecs::{ + query::dynamic::{DynamicViewState, DynamicViewStateIter, QueryDynamicType}, + CommandQueue, Commands, DynamicBundle, World, +}; use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry}; use lyra_resource::ResourceManager; +use mlua::{IntoLua, ObjectLike}; use super::{ - reflect_user_data, wrappers::LuaResHandleToComponent, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE + reflect_user_data, wrappers::LuaResHandleToComponent, Error, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE }; -impl<'lua> elua::FromLua<'lua> for ScriptEntity { - fn from_lua(_: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result { +impl mlua::FromLua for ScriptEntity { + fn from_lua(value: mlua::Value, _: &mlua::Lua) -> mlua::Result { match value { - elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), - elua::Value::Nil => Err(elua::Error::type_mismatch("ScriptEntity", "Nil")), + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), + mlua::Value::Nil => Err(mlua::Error::external(Error::type_mismatch("ScriptEntity", "Nil"))), _ => panic!(), } } } -impl elua::Userdata for ScriptEntity { - fn name() -> String { - "Entity".to_string() - } - - fn build<'a>(builder: &mut elua::userdata::UserdataBuilder<'a, Self>) { - builder.meta_method(elua::MetaMethod::ToString, |_, this, ()| { +impl mlua::UserData for ScriptEntity { + fn add_methods>(methods: &mut M) { + methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, ()| { Ok(format!("{:?}", this.0)) }); } @@ -38,279 +37,278 @@ pub enum WorldError { LuaInvalidUsage(String), } -impl<'a> elua::FromLua<'a> for ScriptWorldPtr { - fn from_lua(_: &'a elua::State, val: elua::Value<'a>) -> elua::Result { +impl mlua::FromLua for ScriptWorldPtr { + fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result { match val { - elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), - elua::Value::Nil => Err(elua::Error::type_mismatch("ScriptWorldPtr", "Nil")), + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), + mlua::Value::Nil => Err(mlua::Error::external(Error::type_mismatch("ScriptWorldPtr", "Nil"))), _ => panic!(), } } } -impl elua::Userdata for ScriptWorldPtr { - fn name() -> String { - "World".to_string() - } +impl mlua::UserData for ScriptWorldPtr { + fn add_methods>(methods: &mut M) { + methods.add_method_mut("spawn", |_, this, vals: mlua::MultiValue| { + let mut world = this.write(); - fn build<'a>(builder: &mut elua::UserdataBuilder<'a, Self>) { - builder - .method_mut("spawn", |_, this, vals: elua::ValueVec| { - let world = this.as_mut(); + let mut bundle = DynamicBundle::new(); - let mut bundle = DynamicBundle::new(); + //while let Some(val) = vals.pop_front() { + for (i, val) in vals.into_iter().enumerate() { + let ud = val.as_userdata().ok_or(mlua::Error::BadArgument { + to: Some("World:spawn".into()), + pos: 2 + i, // i starts at 0 + name: Some("components...".into()), + cause: Arc::new(mlua::Error::runtime("provided component is not userdata")), + })?; - //while let Some(val) = vals.pop_front() { - for (i, val) in vals.into_iter().enumerate() { - let ud = val.as_userdata().ok_or( - elua::Error::bad_arg( - Some("World:spawn"), - 2 + i as i32, // i starts at 0 - Some("components..."), - Arc::new(elua::Error::runtime("provided component is not userdata")), - ))?; - - let comp_borrow = { - if let Ok(as_comp) = ud.get::<_, elua::Function>(FN_NAME_INTERNAL_AS_COMPONENT) { - let ud = match as_comp.exec(ud.clone())? { - elua::Value::Userdata(ud) => ud, - elua::Value::Nil => ud.clone(), - _ => todo!(), - }; + let comp_borrow = { + if let Ok(as_comp) = ud.get::(FN_NAME_INTERNAL_AS_COMPONENT) + { + let ud = match as_comp.call(ud.clone())? { + mlua::Value::UserData(ud) => ud, + mlua::Value::Nil => ud.clone(), + _ => todo!(), + }; - ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())? - } else { - ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())? - } - }; + ud.call_method::(FN_NAME_INTERNAL_REFLECT, ())? + } else { + ud.call_method::(FN_NAME_INTERNAL_REFLECT, ())? + } + }; - let reflect = comp_borrow.reflect_branch.as_component_unchecked(); - let refl_data = comp_borrow.data.unwrap(); - reflect.bundle_insert(&mut bundle, refl_data); + let reflect = comp_borrow.reflect_branch.as_component_unchecked(); + let refl_data = comp_borrow.data.unwrap(); + reflect.bundle_insert(&mut bundle, refl_data); + } + + // defer the entity spawn + // SAFETY: Commands borrows Entities from World, the resource borrows from the world resources, + // They are borrowing different parts of World. + let world_ptr: *mut World = world.deref_mut(); + let mut commands_queue = world.get_resource_mut::().unwrap(); + let mut commands = Commands::new(&mut commands_queue, unsafe { &mut *world_ptr }); + let entity = commands.spawn(bundle); + + Ok(ScriptEntity(entity)) + }); + methods.add_method_mut( + "view", + |lua, this, (system, queries): (mlua::Function, mlua::MultiValue)| { + if queries.is_empty() { + return Err(mlua::Error::BadArgument { + to: Some("World:view".into()), + pos: 2, + name: Some("query...".into()), + cause: Arc::new(mlua::Error::external(WorldError::LuaInvalidUsage( + "no component types provided".into(), + ))), + }); } - // defer the entity spawn - // safety: Commands borrows Entities from World, the resource borrows from the world resouces, - // they are borrowing different parts of World. - let world_ptr: *mut World = world; - let mut commands_queue = world.get_resource_mut::(); - let mut commands = Commands::new(&mut commands_queue, unsafe { &mut *world_ptr }); - let entity = commands.spawn(bundle); + let world = this.read(); + let mut view = DynamicViewState::new(); - Ok(ScriptEntity(entity)) - }) - .method_mut( - "view", - |lua, this, (system, queries): (elua::Function, elua::ValueVec)| { - if queries.is_empty() { - return Err(elua::Error::BadArgument { - func: Some("World:view".to_string()), - arg_index: 2, - arg_name: Some("query...".to_string()), - error: Arc::new(elua::Error::other(WorldError::LuaInvalidUsage( - "no component types provided".to_string(), - ))), - }); - } + for (idx, comp) in queries.into_iter().enumerate() { + match comp { + mlua::Value::Table(t) => { + let name: String = t.get(mlua::MetaMethod::Type.name())?; - let world = unsafe { this.inner.as_ref() }; - //let mut view = world.dynamic_view(); - let mut view = DynamicViewState::new(); - - for (idx, comp) in queries.into_iter().enumerate() { - match comp { - elua::Value::Table(t) => { - let name: String = t.get(elua::MetaMethod::Name)?; - - let lookup = world - .try_get_resource::() - .ok_or(elua::Error::runtime( - "Unable to lookup table proxy, none were ever registered!", - ))?; - let info = lookup.comp_info_from_name.get(&name).ok_or_else( - || elua::Error::BadArgument { - func: Some("World:view".to_string()), - arg_index: 2 + idx as i32, - arg_name: Some("query...".to_string()), - error: Arc::new(elua::Error::Runtime(format!( + let lookup = world.get_resource::().ok_or( + mlua::Error::runtime( + "Unable to lookup table proxy, none were ever registered!", + ), + )?; + let info = lookup.comp_info_from_name.get(&name).ok_or_else(|| { + mlua::Error::BadArgument { + to: Some("World:view".into()), + pos: 2 + idx, + name: Some("query...".into()), + cause: Arc::new(mlua::Error::external( + WorldError::LuaInvalidUsage(format!( "the 'Table' with name {} is unknown to the engine!", name - ))), - }, - )?; + )), + )), + } + })?; - let dyn_type = QueryDynamicType::from_info(info.clone()); - view.push(dyn_type); - } - elua::Value::Userdata(ud) => { - let reflect = ud - .execute_function::<_, ScriptBorrow>( - FN_NAME_INTERNAL_REFLECT_TYPE, - (), - ) - .expect("Type does not implement 'reflect_type' properly"); - let refl_comp = reflect.reflect_branch.as_component_unchecked(); - - let dyn_type = QueryDynamicType::from_info(refl_comp.info); - view.push(dyn_type); - } - _ => todo!(), + let dyn_type = QueryDynamicType::from_info(info.clone()); + view.push(dyn_type); } - } + mlua::Value::UserData(ud) => { + let reflect = ud + .call_function::( + FN_NAME_INTERNAL_REFLECT_TYPE, + (), + ) + .expect("Type does not implement 'reflect_type' properly"); + let refl_comp = reflect.reflect_branch.as_component_unchecked(); - let iter = view.into_iter(); - let mut reflected_iter = ReflectedIterator { - world: this.clone(), - dyn_view: DynamicViewStateIter::from(iter), - reflected_components: None, - }; - - let mut current = world.current_tick(); - let mut has_ticked = false; - - while let Some(row) = reflected_iter.next_lua(lua) { - let r = row - .row - .into_iter() - .map(|r| (r.comp_val, r.comp_ptr.cast::<()>())) - .collect::>(); - let (values, ptrs) = - itertools::multiunzip::<(Vec, Vec>), _>(r); - let mult_val = elua::ValueVec::from(values); - let res: elua::ValueVec = system.exec(mult_val)?; - - // if values were returned, find the type in the type registry, and apply the new values - if res.len() <= ptrs.len() { - // we only want to tick one time per system - if !has_ticked { - current = world.tick(); - has_ticked = true; - } - - for (comp, ptr) in res.into_iter().zip(ptrs) { - let lua_typeid = match &comp { - elua::Value::Userdata(ud) => { - let lua_comp = reflect_user_data(ud); - let refl_comp = - lua_comp.reflect_branch.as_component_unchecked(); - refl_comp.info.type_id().as_rust() - }, - elua::Value::Table(tbl) => { - let name: String = tbl.get(elua::MetaMethod::Name)?; - - let lookup = world.get_resource::(); - *lookup.typeid_from_name.get(&name).unwrap() - }, - _ => { - panic!("A userdata or table value was not returned!"); - // TODO: Handle properly - } - }; - - // update the component tick - let world = unsafe { this.inner.as_mut() }; - let arch = world.entity_archetype_mut(row.entity).unwrap(); - let idx = arch.entity_indexes().get(&row.entity).unwrap().clone(); - let c = arch.get_column_mut(lua_typeid).unwrap(); - c.entity_ticks[idx.0 as usize] = current; - - // apply the new component data - let reg = this.as_ref().get_resource::(); - let reg_type = reg.get_type(lua_typeid).unwrap(); - - let proxy = reg_type - .get_data::() - // this should actually be safe since the ReflectedIterator - // attempts to get the type data before it is tried here - .expect("Type does not have ReflectLuaProxy as a TypeData"); - (proxy.fn_apply)(lua, ptr, &comp)?; - } - } else { - let msg = format!( - "Too many arguments were returned from the World view! - At most, the expected number of results is {}.", - ptrs.len() - ); - return Err(elua::Error::Runtime(msg)); + let dyn_type = QueryDynamicType::from_info(refl_comp.info); + view.push(dyn_type); } + _ => todo!(), } - - Ok(()) - }, - ) - .method_mut("resource", |lua, this, (ty,): (elua::Value,)| { - let reflect = match ty { - elua::Value::Userdata(ud) => ud - .execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ()) - .expect("Type does not implement 'reflect_type' properly"), - elua::Value::Table(t) => { - let f: elua::Function = t.get(FN_NAME_INTERNAL_REFLECT_TYPE)?; - f.exec::<_, ScriptBorrow>(()) - .expect("Type does not implement 'reflect_type' properly") - } - _ => { - panic!("how"); - } - }; - /* let reflect = ty - .execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ()) - .expect("Type does not implement 'reflect_type' properly"); */ - - let res = reflect.reflect_branch.as_resource_unchecked(); - if let Some(res_ptr) = res.reflect_ptr(this.as_mut()) { - let reg_type = this - .as_ref() - .get_type::(reflect.reflect_branch.reflect_type_id()) - .expect("Resource is not type registered!"); - let proxy = reg_type - .get_data::() - .expect("Type does not have ReflectLuaProxy as a TypeData"); - - (proxy.fn_as_lua)(lua, res_ptr.cast()).and_then(|ud| ud.as_lua(lua)) - } else { - // if the resource is not found in the world, return nil - Ok(elua::Value::Nil) } - }) - .method_mut("add_resource", |_, this, res: elua::Value| { - let reflect = match res { - elua::Value::Userdata(ud) => ud - .execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ()) - .expect("Type does not implement 'reflect_type' properly"), - elua::Value::Table(t) => { - let f: elua::Function = t.get(FN_NAME_INTERNAL_REFLECT)?; - f.exec::<_, ScriptBorrow>(()) - .expect("Type does not implement 'reflect_type' properly") - } - _ => { - panic!("how"); - } + + let iter = view.into_iter(); + let mut reflected_iter = ReflectedIterator { + // SAFETY: bypassing the borrow checker here to get a pointer of the world + // is required since we mutably borrow below. Its safe to do so since + // only the entity ticks are updated. They are accessing different things + // from the world. + world: unsafe { NonNull::from(&*world).as_ref() }, + dyn_view: DynamicViewStateIter::from(iter), + reflected_components: None, }; - let data = reflect.data - .expect("Its expected that 'FN_NAME_INTERNAL_REFLECT' returns data in World:add_resource"); + let current = world.current_tick(); - let res = reflect.reflect_branch.as_resource() - .ok_or(elua::Error::runtime("Provided type is not a resource!"))?; + // drop read lock and acquire the write lock. + // dropping must be done to avoid mutex deadlock + drop(world); + let mut world = this.write(); - let world = this.as_mut(); - res.insert(world, data); + while let Some(row) = reflected_iter.next_lua(lua) { + let r = row.row.into_iter() + .into_iter() + .map(|r| (r.comp_val, r.comp_ptr.cast::<()>())) + .collect::>(); + let (values, ptrs) = + itertools::multiunzip::<(Vec, Vec>), _>(r); + let mult_val = mlua::MultiValue::from_iter(values.into_iter()); + let res: mlua::MultiValue = system.call(mult_val)?; + + // if values were returned, find the type in the type registry, and apply the new values + if res.len() <= ptrs.len() { + + for (comp, ptr) in res.into_iter().zip(ptrs) { + let lua_typeid = match &comp { + mlua::Value::UserData(ud) => { + let lua_comp = reflect_user_data(ud); + let refl_comp = + lua_comp.reflect_branch.as_component_unchecked(); + refl_comp.info.type_id().as_rust() + } + mlua::Value::Table(tbl) => { + let name: String = tbl.get(mlua::MetaMethod::Type.name())?; + + let lookup = world.get_resource::().unwrap(); + *lookup.typeid_from_name.get(&name).unwrap() + } + _ => { + panic!("A userdata or table value was not returned!"); + // TODO: Handle properly + } + }; + + // update the component tick + let arch = world.entity_archetype_mut(row.entity).unwrap(); + let idx = arch.entity_indexes().get(&row.entity).unwrap().clone(); + let c = arch.get_column_mut(lua_typeid).unwrap(); + c.entity_ticks[idx.0 as usize] = current; + + // apply the new component data + let reg = world.get_resource::().unwrap(); + let reg_type = reg.get_type(lua_typeid).unwrap(); + + let proxy = reg_type + .get_data::() + // this should actually be safe since the ReflectedIterator + // attempts to get the type data before it is tried here + .expect("Type does not have ReflectLuaProxy as a TypeData"); + (proxy.fn_apply)(lua, ptr, &comp)?; + } + } else { + let msg = format!( + "Too many arguments were returned from the World view! + At most, the expected number of results is {}.", + ptrs.len() + ); + return Err(mlua::Error::runtime(msg)); + } + } Ok(()) - }) - .method_mut("request_res", |lua, this, path: String| { - let world: &mut World = this.as_mut(); - let man = world.get_resource_mut::(); - let handle = man.request_raw(&path).unwrap(); + }, + ); + methods.add_method_mut("resource", |lua, this, (ty,): (mlua::Value,)| { + let reflect = match ty { + mlua::Value::UserData(ud) => ud + .call_function::(FN_NAME_INTERNAL_REFLECT_TYPE, ()) + .expect("Type does not implement 'reflect_type' properly"), + mlua::Value::Table(t) => { + let f: mlua::Function = t.get(FN_NAME_INTERNAL_REFLECT_TYPE)?; + f.call::(()) + .expect("Type does not implement 'reflect_type' properly") + } + _ => { + panic!("how"); + } + }; - // get the actual resource handle wrapper - let registry = world.get_resource::(); - let ty = registry.get_type(handle.resource_type_id()) - .expect("Could not find asset type in registry"); - let data = ty.get_data::() - .expect("Asset type does not have 'LuaResHandleToComponent' as TypeData"); + let mut world = this.write(); + let res = reflect.reflect_branch.as_resource_unchecked(); + if let Some(res_ptr) = res.reflect_ptr(&mut world) { + let reg_type = world + .get_type::(reflect.reflect_branch.reflect_type_id()) + .expect("Resource is not type registered!"); + let proxy = reg_type + .get_data::() + .expect("Type does not have ReflectLuaProxy as a TypeData"); - Ok((data.fn_to_lua)(lua, handle).unwrap()) - }); + (proxy.fn_as_lua)(lua, res_ptr.cast()).and_then(|ud| ud.into_lua(lua)) + } else { + // if the resource is not found in the world, return nil + Ok(mlua::Value::Nil) + } + }); + methods.add_method_mut("add_resource", |_, this, res: mlua::Value| { + let reflect = match res { + mlua::Value::UserData(ud) => ud + .call_method::(FN_NAME_INTERNAL_REFLECT, ()) + .expect("Type does not implement 'reflect_type' properly"), + mlua::Value::Table(t) => { + let f: mlua::Function = t.get(FN_NAME_INTERNAL_REFLECT)?; + f.call::(()) + .expect("Type does not implement 'reflect_type' properly") + } + _ => { + panic!("how"); + } + }; + + let data = reflect.data.expect( + "Its expected that 'FN_NAME_INTERNAL_REFLECT' returns data in World:add_resource", + ); + + let res = reflect + .reflect_branch + .as_resource() + .ok_or(mlua::Error::runtime("Provided type is not a resource!"))?; + + let mut world = this.write(); + res.insert(&mut world, data); + + Ok(()) + }); + methods.add_method_mut("request_res", |lua, this, path: String| { + let world = this.write(); + let man = world.get_resource_mut::().unwrap(); + let handle = man.request_raw(&path).unwrap(); + + // get the actual resource handle wrapper + let registry = world.get_resource::().unwrap(); + let ty = registry + .get_type(handle.resource_type_id()) + .expect("Could not find asset type in registry"); + let data = ty + .get_data::() + .expect("Asset type does not have 'LuaResHandleToComponent' as TypeData"); + + Ok((data.fn_to_lua)(lua, handle).unwrap()) + }); } } diff --git a/lyra-scripting/src/lua/wrappers/asset/mod.rs b/lyra-scripting/src/lua/wrappers/asset/mod.rs index 28075c5..b336c64 100644 --- a/lyra-scripting/src/lua/wrappers/asset/mod.rs +++ b/lyra-scripting/src/lua/wrappers/asset/mod.rs @@ -1,21 +1,23 @@ use std::{any::TypeId, ops::Deref}; -use elua::{AnyUserdata, AsLua, FromLua, State, Value}; +//use mlua::{AnyUserData, IntoLua, FromLua, Lua, Value}; use lyra_resource::{gltf::{Gltf, Material, Mesh}, Texture, ResHandle, UntypedResHandle}; use lyra_game::scene::SceneGraph; use lyra_reflect::{Reflect, TypeData}; use lyra_scripting_derive::{lua_wrap_handle, wrap_lua_struct}; -use crate::{lua::{LuaWrapper, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, lyra_engine, ScriptBorrow}; +use crate::{lua::{Error, LuaWrapper, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, lyra_engine, ScriptBorrow}; use crate as lyra_scripting; +use mlua::IntoLua; + pub struct LuaResHandleToComponent { /// Create the userdata component that - pub fn_to_lua: fn(&State, UntypedResHandle) -> Option, + pub fn_to_lua: fn(&mlua::Lua, UntypedResHandle) -> Option, } impl LuaResHandleToComponent { - pub fn new(f: fn(&State, UntypedResHandle) -> Option) -> Self { + pub fn new(f: fn(&mlua::Lua, UntypedResHandle) -> Option) -> Self { Self { fn_to_lua: f } @@ -53,16 +55,12 @@ impl From for LuaResHandle { } } -impl elua::Userdata for LuaResHandle { - fn name() -> String { - "Handle".to_string() - } - - fn build<'a>(builder: &mut elua::UserdataBuilder<'a, Self>) { - builder.field_getter("path", |_, this| Ok(this.path())); - builder.field_getter("version", |_, this| Ok(this.version())); - builder.field_getter("uuid", |_, this| Ok(this.uuid().to_string())); - builder.field_getter("state", |_, this| { +impl mlua::UserData for LuaResHandle { + fn add_fields>(fields: &mut F) { + fields.add_field_method_get("path", |_, this| Ok(this.path())); + fields.add_field_method_get("version", |_, this| Ok(this.version())); + fields.add_field_method_get("uuid", |_, this| Ok(this.uuid().to_string())); + fields.add_field_method_get("state", |_, this| { let name = if this.is_loaded() { "ready" } else if this.get_error().is_some() { @@ -71,41 +69,43 @@ impl elua::Userdata for LuaResHandle { Ok(name) }); + } - builder.method("is_watched", |_, this, ()| { + fn add_methods>(methods: &mut M) { + methods.add_method("is_watched", |_, this, ()| { Ok(this.is_watched()) }); - - builder.method("is_loaded", |_, this, ()| { + + methods.add_method("is_loaded", |_, this, ()| { Ok(this.is_loaded()) }); - - builder.method("wait_until_loaded", |_, this, ()| { + + methods.add_method("wait_until_loaded", |_, this, ()| { this.wait_recurse_dependencies_load(); Ok(()) }); - builder.method(FN_NAME_INTERNAL_AS_COMPONENT, |lua, this, ()| { + methods.add_method(FN_NAME_INTERNAL_AS_COMPONENT, |lua, this, ()| { let handle = &this.0; if let Some(handle) = handle.as_typed::() { - LuaSceneHandle(handle).as_lua(lua) + LuaSceneHandle(handle).into_lua(lua) } else if let Some(handle) = handle.as_typed::() { - LuaGltfHandle(handle).as_lua(lua) + LuaGltfHandle(handle).into_lua(lua) } else { - Ok(elua::Value::Nil) + Ok(mlua::Value::Nil) } }); } } -impl<'a> FromLua<'a> for LuaResHandle { - fn from_lua(_: &'a elua::State, val: elua::Value<'a>) -> elua::Result { +impl mlua::FromLua for LuaResHandle { + fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result { let tyname = val.type_name(); let ud = val.as_userdata() - .ok_or(elua::Error::type_mismatch("Handle", &tyname))?; - let handle = ud.as_ref::()?; + .ok_or(mlua::Error::external(Error::type_mismatch("Handle", &tyname)))?; + let handle = ud.borrow::()?; Ok(handle.clone()) } @@ -121,11 +121,11 @@ lua_wrap_handle!(Mesh, (material, { data.material.clone() .map(|v| LuaMaterialHandle(v.clone())) - .as_lua(lua) + .into_lua(lua) }) }, { - builder.method("indices", |lua, this, ()| { + methods.add_method("indices", |lua, this, ()| { if let Some(data) = this.0.data_ref() { let table = lua.create_table()?; @@ -133,21 +133,21 @@ lua_wrap_handle!(Mesh, Some(lyra_resource::gltf::MeshIndices::U16(v)) => { for (i, ind) in v.iter().enumerate() { let i = i as i64 + 1; // lua indexes start at 1 - table.raw_seti(i, *ind)?; + table.raw_set(i, *ind)?; } }, Some(lyra_resource::gltf::MeshIndices::U32(v)) => { for (i, ind) in v.iter().enumerate() { let i = i as i64 + 1; // lua indexes start at 1 - table.raw_seti(i, *ind)?; + table.raw_set(i, *ind)?; } }, None => {}, } - Ok(Value::Table(table)) + Ok(mlua::Value::Table(table)) } else { - Ok(Value::Nil) + Ok(mlua::Value::Nil) } }); @@ -167,17 +167,17 @@ lua_wrap_handle!(Material, (base_color_texture, { data.base_color_texture.clone() .map(|v| LuaTextureHandle(v.clone())) - .as_lua(lua) + .into_lua(lua) }), (metallic_roughness_texture, { data.metallic_roughness_texture.clone() .map(|v| LuaTextureHandle(v.clone())) - .as_lua(lua) + .into_lua(lua) }), (pbr_glossiness, { data.pbr_glossiness.clone() .map(|v| LuaPbrGlossiness(v.clone())) - .as_lua(lua) + .into_lua(lua) }), alpha_cutoff, (alpha_mode, { @@ -186,55 +186,57 @@ lua_wrap_handle!(Material, lyra_resource::gltf::AlphaMode::Opaque => "opaque", lyra_resource::gltf::AlphaMode::Mask => "mask", lyra_resource::gltf::AlphaMode::Blend => "blend", - }.as_lua(lua) + }.into_lua(lua) }), (specular, { data.specular.clone() .map(|v| LuaSpecular(v.clone())) - .as_lua(lua) + .into_lua(lua) }), } ); lua_wrap_handle!(Gltf, { - builder.method("scenes", |lua, this, ()| { + methods.add_method("scenes", |lua, this, ()| { if let Some(data) = this.0.data_ref() { let table = lua.create_table()?; for (i, scene) in data.scenes.iter().enumerate() { let i = i as i64 + 1; // lua indexes start at 1 - table.raw_seti(i, LuaSceneHandle(scene.clone()))?; + table.raw_set(i, LuaSceneHandle(scene.clone()))?; } - Ok(Value::Table(table)) + Ok(mlua::Value::Table(table)) } else { - Ok(Value::Nil) + Ok(mlua::Value::Nil) } - }).method("materials", |lua, this, ()| { + }); + methods.add_method("materials", |lua, this, ()| { if let Some(data) = this.0.data_ref() { let table = lua.create_table()?; for (i, mat) in data.materials.iter().enumerate() { let i = i as i64 + 1; // lua indexes start at 1 - table.raw_seti(i, LuaMaterialHandle(mat.clone()))?; + table.raw_set(i, LuaMaterialHandle(mat.clone()))?; } - Ok(Value::Table(table)) + Ok(mlua::Value::Table(table)) } else { - Ok(Value::Nil) + Ok(mlua::Value::Nil) } - }).method("meshes", |lua, this, ()| { + }); + methods.add_method("meshes", |lua, this, ()| { if let Some(data) = this.0.data_ref() { let table = lua.create_table()?; for (i, mesh) in data.meshes.iter().enumerate() { let i = i as i64 + 1; // lua indexes start at 1 - table.raw_seti(i, LuaMeshHandle(mesh.clone()))?; + table.raw_set(i, LuaMeshHandle(mesh.clone()))?; } - Ok(Value::Table(table)) + Ok(mlua::Value::Table(table)) } else { - Ok(Value::Nil) + Ok(mlua::Value::Nil) } }); }); \ No newline at end of file diff --git a/lyra-scripting/src/lua/wrappers/delta_time.rs b/lyra-scripting/src/lua/wrappers/delta_time.rs index d0bcf7b..36be0df 100644 --- a/lyra-scripting/src/lua/wrappers/delta_time.rs +++ b/lyra-scripting/src/lua/wrappers/delta_time.rs @@ -21,15 +21,15 @@ impl std::ops::DerefMut for LuaDeltaTime { } } -impl<'lua> elua::FromLua<'lua> for LuaDeltaTime { - fn from_lua(_: &'lua elua::State, _: elua::Value<'lua>) -> elua::Result { +impl mlua::FromLua for LuaDeltaTime { + fn from_lua(_: mlua::Value, _: &mlua::Lua) -> mlua::Result { todo!() } } -impl<'lua> elua::AsLua<'lua> for LuaDeltaTime { - fn as_lua(self, _: &'lua elua::State) -> elua::Result> { - Ok(elua::Value::Number(*self.0 as f64)) +impl mlua::IntoLua for LuaDeltaTime { + fn into_lua(self, _: &mlua::Lua) -> mlua::Result { + Ok(mlua::Value::Number(*self.0 as f64)) } } diff --git a/lyra-scripting/src/lua/wrappers/input_actions.rs b/lyra-scripting/src/lua/wrappers/input_actions.rs index 410b83c..7a07675 100644 --- a/lyra-scripting/src/lua/wrappers/input_actions.rs +++ b/lyra-scripting/src/lua/wrappers/input_actions.rs @@ -1,5 +1,6 @@ use lyra_game::input::{keycode_from_str, Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, ActionState, LayoutId, MouseAxis, MouseInput}; -use crate::lyra_engine; +use mlua::IntoLua; +use crate::{lua::Error, lyra_engine}; use lyra_reflect::Reflect; @@ -10,27 +11,23 @@ pub struct LuaActionHandler { handler: ActionHandler } -impl elua::Userdata for LuaActionHandler { - fn name() -> String { - "ActionHandler".to_string() - } - - fn build<'a>(builder: &mut elua::UserdataBuilder<'a, Self>) { - builder.function("new", |_, table: elua::Table| { +impl mlua::UserData for LuaActionHandler { + fn add_methods>(methods: &mut M) { + methods.add_function("new", |_, table: mlua::Table| { let mut handler = ActionHandler::new(); // create the layouts and add them to the handler - let layouts = table.get::<_, elua::Table>("layouts") - .map_err(|_| elua::Error::runtime("missing 'layouts' in ActionHandler table"))?; - for layout_id in layouts.sequence_iter::() { + let layouts = table.get::("layouts") + .map_err(|_| mlua::Error::runtime("missing 'layouts' in ActionHandler table"))?; + for layout_id in layouts.sequence_values::() { let layout_id = layout_id?; handler.add_layout(LayoutId(layout_id)); } // add the actions to the handler - let actions = table.get::<_, elua::Table>("actions") - .map_err(|_| elua::Error::runtime("missing 'actions' in ActionHandler table"))?; + let actions = table.get::("actions") + .map_err(|_| mlua::Error::runtime("missing 'actions' in ActionHandler table"))?; for pair in actions.pairs::() { let (action_lbl, action_type) = pair?; let action_type = action_type.to_lowercase(); @@ -45,26 +42,26 @@ impl elua::Userdata for LuaActionHandler { } // find the mappings and start processing them - let mappings= table.get::<_, elua::Table>("mappings") - .map_err(|_| elua::Error::runtime("missing 'mappings' in ActionHandler table"))?; - for (map_id, tbl) in mappings.sequence_iter::().enumerate() { + let mappings= table.get::("mappings") + .map_err(|_| mlua::Error::runtime("missing 'mappings' in ActionHandler table"))?; + for (map_id, tbl) in mappings.sequence_values::().enumerate() { let tbl = tbl?; - let layout_id = tbl.get::<_, u32>("layout")?; + let layout_id = tbl.get::("layout")?; let mut mapping = ActionMapping::new(LayoutId(layout_id), ActionMappingId(map_id as u32)); // find the binds and start processing them // the keys are used as the action names, and then the value is an array (lua table) - let binds_tbl = tbl.get::<_, elua::Table>("binds") - .map_err(|_| elua::Error::runtime("missing 'binds' in ActionHandler 'mappings' table"))?; - for pair in binds_tbl.pairs::() { + let binds_tbl = tbl.get::("binds") + .map_err(|_| mlua::Error::runtime("missing 'binds' in ActionHandler 'mappings' table"))?; + for pair in binds_tbl.pairs::() { let (action_lbl, input_binds) = pair?; - for input in input_binds.sequence_iter::() { + for input in input_binds.sequence_values::() { let input = input?.to_lowercase(); let action = handler.action(&action_lbl) - .ok_or(elua::Error::Runtime(format!("Unknown action specified in mapping binds: {}", action_lbl)))?; + .ok_or(mlua::Error::runtime(format!("Unknown action specified in mapping binds: {}", action_lbl)))?; let mut binds = Vec::new(); @@ -77,18 +74,18 @@ impl elua::Userdata for LuaActionHandler { let axis_name = input_split[2]; let src = process_axis_string(input_name, axis_name) - .ok_or(elua::Error::Runtime(format!("invalid bind '{input_name}', unable to find device or axis for device")))?; + .ok_or(mlua::Error::runtime(format!("invalid bind '{input_name}', unable to find device or axis for device")))?; binds.push(src.into_binding()); } else { // splits 'down=1' into 'down' and '1' let (button, val_str) = button.split_once("=") - .ok_or(elua::Error::Runtime(format!("invalid bind string for Axis Action: '{input}' (expected '=' with float)")))?; + .ok_or(mlua::Error::runtime(format!("invalid bind string for Axis Action: '{input}' (expected '=' with float)")))?; let val = val_str.parse::() - .map_err(|e| elua::Error::Runtime(format!("invalid bind string for Axis Action: '{input}' ({e})")))?; + .map_err(|e| mlua::Error::runtime(format!("invalid bind string for Axis Action: '{input}' ({e})")))?; let src = process_keyboard_string(button) - .ok_or(elua::Error::Runtime(format!("invalid key in bind: '{button}'")))?; + .ok_or(mlua::Error::runtime(format!("invalid key in bind: '{button}'")))?; binds.push(src.into_binding_modifier(val)); } } else { @@ -105,23 +102,29 @@ impl elua::Userdata for LuaActionHandler { Ok(LuaActionHandler { handler, }) - }) - .method("get_axis", |_, this, action: String| { + }); + + methods.add_method("get_axis", |_, this, action: String| { Ok(this.handler.get_axis_modifier(action)) - }) - .method("is_pressed", |_, this, action: String| { + }); + + methods.add_method("is_pressed", |_, this, action: String| { Ok(this.handler.is_action_pressed(action)) - }) - .method("was_just_pressed", |_, this, action: String| { + }); + + methods.add_method("was_just_pressed", |_, this, action: String| { Ok(this.handler.was_action_just_pressed(action)) - }) - .method("was_just_released", |_, this, action: String| { + }); + + methods.add_method("was_just_released", |_, this, action: String| { Ok(this.handler.was_action_just_released(action)) - }) - .method("get_just_pressed", |_, this, action: String| { + }); + + methods.add_method("get_just_pressed", |_, this, action: String| { Ok(this.handler.get_just_pressed_modifier(action)) - }) - .method("get_action_state", |lua, this, action: String| { + }); + + methods.add_method("get_action_state", |lua, this, action: String| { let state = this.handler.get_action_state(action); let (name, val) = match state { @@ -133,28 +136,29 @@ impl elua::Userdata for LuaActionHandler { ActionState::Other(v) => ("Other", Some(v)), }; - let mut multi = elua::ValueVec::new(); - multi.push_val(lua, name)?; - multi.push_val(lua, val)?; + let mut multi = Vec::new(); + multi.push(name.into_lua(lua)?); + multi.push(val.into_lua(lua)?); - Ok(elua::Value::Multi(multi)) - }) - .method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| { - Ok(ScriptBorrow::from_resource::(Some(this.handler.clone()))) - }) - .function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { - Ok(ScriptBorrow::from_resource::(None)) + Ok(mlua::MultiValue::from_iter(multi.into_iter())) }); + methods.add_method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| { + Ok(ScriptBorrow::from_resource::(Some(this.handler.clone()))) + }); + + methods.add_function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { + Ok(ScriptBorrow::from_resource::(None)) + }); } } -impl<'a> elua::FromLua<'a> for LuaActionHandler { - fn from_lua(_: &'a elua::State, val: elua::Value<'a>) -> elua::Result { +impl mlua::FromLua for LuaActionHandler { + fn from_lua(val: mlua::Value, _: &mlua::Lua) -> mlua::Result { let tyname = val.type_name(); let ud = val.as_userdata() - .ok_or(elua::Error::type_mismatch("ActionHandler", &tyname))?; - let handle = ud.as_ref::()?; + .ok_or(mlua::Error::external(Error::type_mismatch("ActionHandler", &tyname)))?; + let handle = ud.borrow::()?; Ok(handle.clone()) } diff --git a/lyra-scripting/src/lua/wrappers/math.rs b/lyra-scripting/src/lua/wrappers/math.rs index 6a4bf9e..0af2467 100644 --- a/lyra-scripting/src/lua/wrappers/math.rs +++ b/lyra-scripting/src/lua/wrappers/math.rs @@ -1,6 +1,7 @@ -use lyra_scripting_derive::{lua_vec_wrap_extension, wrap_lua_struct}; use crate::lyra_engine; use lyra_game::math; +use lyra_scripting_derive::{lua_vec_wrap_extension, wrap_lua_struct}; +use mlua::FromLuaMulti; use crate as lyra_scripting; @@ -20,13 +21,15 @@ wrap_lua_struct!( { lua_vec_wrap_extension!(math::Vec2, LuaVec2); - builder.method_mut("move_by", |lua, this, vals: elua::ValueVec| { + methods.add_method_mut("move_by", |lua, this, vals: mlua::MultiValue| { let vals_clone = vals.clone(); - if let Some((x, y)) = vals.try_into_vals::<(f32, f32)>(lua)? { + if let Ok((x, y)) = <(f32, f32) as FromLuaMulti>::from_lua_multi(vals, lua) { this.x += x; this.y += y; - } else if let Some(v) = vals_clone.try_into_vals::(lua)? { + } else if let Ok(v) = Self::from_lua_multi(vals_clone, lua) { this.0 += v.0; + } else { + todo!("handle invalid argument error"); } Ok(()) @@ -50,14 +53,16 @@ wrap_lua_struct!( { lua_vec_wrap_extension!(math::Vec3, LuaVec3); - builder.method_mut("move_by", |lua, this, vals: elua::ValueVec| { + methods.add_method_mut("move_by", |lua, this, vals: mlua::MultiValue| { let vals_clone = vals.clone(); - if let Some((x, y, z)) = vals.try_into_vals::<(f32, f32, f32)>(lua)? { + if let Ok((x, y, z)) = <(f32, f32, f32) as FromLuaMulti>::from_lua_multi(vals, lua) { this.x += x; this.y += y; this.z += z; - } else if let Some(v) = vals_clone.try_into_vals::(lua)? { + } else if let Ok(v) = Self::from_lua_multi(vals_clone, lua) { this.0 += v.0; + } else { + todo!("handle invalid argument error"); } Ok(()) @@ -98,70 +103,70 @@ wrap_lua_struct!( ), { // manually implemented since Quat doesn't have a `new` function - builder.function("new", |_, (x, y, z, w)| { + methods.add_function("new", |_, (x, y, z, w)| { Ok(Self(math::Quat::from_xyzw(x, y, z, w))) }); - builder.function("from_rotation_x", |_, (rad,)| { + methods.add_function("from_rotation_x", |_, (rad,)| { let q = math::Quat::from_rotation_x(rad); Ok(Self(q)) }); - builder.function("from_rotation_y", |_, (rad,)| { + methods.add_function("from_rotation_y", |_, (rad,)| { let q = math::Quat::from_rotation_y(rad); Ok(Self(q)) }); - builder.function("from_rotation_z", |_, (rad,)| { + methods.add_function("from_rotation_z", |_, (rad,)| { let q = math::Quat::from_rotation_z(rad); Ok(Self(q)) }); - builder.method("dot", |_, this, (rhs,): (Self,)| { + methods.add_method("dot", |_, this, (rhs,): (Self,)| { Ok(this.dot(rhs.0)) }); - builder.method("length", |_, this, ()| { + methods.add_method("length", |_, this, ()| { Ok(this.length()) }); - builder.method("length_squared", |_, this, ()| { + methods.add_method("length_squared", |_, this, ()| { Ok(this.length_squared()) }); - builder.method_mut("normalize", |_, this, ()| { + methods.add_method_mut("normalize", |_, this, ()| { this.0 = this.normalize(); Ok(()) }); - builder.method_mut("mult_quat", |_, this, (rhs,): (Self,)| { + methods.add_method_mut("mult_quat", |_, this, (rhs,): (Self,)| { this.0 *= rhs.0; Ok(()) }); - builder.method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| { + methods.add_method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| { Ok(LuaVec3(this.0 * rhs.0)) }); // manually implemented here since multiplying may not return `Self`. - builder.meta_method(elua::MetaMethod::Mul, |lua, this, (val,): (elua::Value,)| { - use elua::AsLua; + methods.add_meta_method(mlua::MetaMethod::Mul, |lua, this, (val,): (mlua::Value,)| { + use mlua::IntoLua; match val { - elua::Value::Userdata(ud) => { - if ud.is::()? { - let v3 = ud.as_ref::()?; + mlua::Value::UserData(ud) => { + if ud.is::() { + let v3 = ud.borrow::()?; LuaVec3(this.0 * v3.0) - .as_lua(lua) + .into_lua(lua) } else { - let quat = ud.as_ref::()?; + let quat = ud.borrow::()?; LuaQuat(this.0 * quat.0) - .as_lua(lua) + .into_lua(lua) } }, - elua::Value::Number(n) => { + mlua::Value::Number(n) => { LuaQuat(this.0 * (n as f32)) - .as_lua(lua) + .into_lua(lua) }, _ => { todo!() @@ -169,7 +174,7 @@ wrap_lua_struct!( } }); - builder.method("lerp", |_, this, (rhs, alpha): (Self, f32)| { + methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| { Ok(Self(this.lerp(*rhs, alpha))) }); } @@ -180,94 +185,94 @@ wrap_lua_struct!( derives(PartialEq, Copy), metamethods(ToString, Eq), { - builder.function("default", |_, ()| { + methods.add_function("default", |_, ()| { Ok(Self(math::Transform::default())) }); - builder.function("new", |_, (pos, rot, scale): (LuaVec3, LuaQuat, LuaVec3)| { + methods.add_function("new", |_, (pos, rot, scale): (LuaVec3, LuaQuat, LuaVec3)| { Ok(Self(math::Transform::new(*pos, *rot, *scale))) }); - - builder.function("from_translation", |_, (pos,): (LuaVec3,)| { + + methods.add_function("from_translation", |_, (pos,): (LuaVec3,)| { Ok(Self(math::Transform::from_translation(*pos))) }); - - builder.function("from_xyz", |_, (x, y, z)| { + + methods.add_function("from_xyz", |_, (x, y, z)| { Ok(Self(math::Transform::from_xyz(x, y, z))) }); - builder.method("clone", |_, this, ()| { + methods.add_method("clone", |_, this, ()| { Ok(this.clone()) }); - builder.method("forward", |_, this, ()| { + methods.add_method("forward", |_, this, ()| { Ok(LuaVec3(this.forward())) }); - builder.method("left", |_, this, ()| { + methods.add_method("left", |_, this, ()| { Ok(LuaVec3(this.left())) }); - builder.method("up", |_, this, ()| { + methods.add_method("up", |_, this, ()| { Ok(LuaVec3(this.up())) }); - builder.method_mut("rotate", |_, this, (quat,): (LuaQuat,)| { + methods.add_method_mut("rotate", |_, this, (quat,): (LuaQuat,)| { this.rotate(*quat); Ok(()) }); - builder.method_mut("rotate_x", |_, this, (deg,): (f32,)| { + methods.add_method_mut("rotate_x", |_, this, (deg,): (f32,)| { this.rotate_x(math::Angle::Degrees(deg)); Ok(()) }); - builder.method_mut("rotate_y", |_, this, (deg,): (f32,)| { + methods.add_method_mut("rotate_y", |_, this, (deg,): (f32,)| { this.rotate_y(math::Angle::Degrees(deg)); Ok(()) }); - builder.method_mut("rotate_z", |_, this, (deg,): (f32,)| { + methods.add_method_mut("rotate_z", |_, this, (deg,): (f32,)| { this.rotate_z(math::Angle::Degrees(deg)); Ok(()) }); - builder.method_mut("rotate_x_rad", |_, this, (rad,): (f32,)| { + methods.add_method_mut("rotate_x_rad", |_, this, (rad,): (f32,)| { this.rotate_x(math::Angle::Radians(rad)); Ok(()) }); - builder.method_mut("rotate_y_rad", |_, this, (rad,): (f32,)| { + methods.add_method_mut("rotate_y_rad", |_, this, (rad,): (f32,)| { this.rotate_y(math::Angle::Radians(rad)); Ok(()) }); - builder.method_mut("rotate_z_rad", |_, this, (rad,): (f32,)| { + methods.add_method_mut("rotate_z_rad", |_, this, (rad,): (f32,)| { this.rotate_z(math::Angle::Radians(rad)); Ok(()) }); - builder.method_mut("translate", |_, this, (x, y, z): (f32, f32, f32)| { + methods.add_method_mut("translate", |_, this, (x, y, z): (f32, f32, f32)| { this.translate(x, y, z); Ok(()) }); - builder.method("lerp", |_, this, (rhs, alpha): (Self, f32)| { + methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| { Ok(Self(this.lerp(*rhs, alpha))) }); // rotate a transform - builder.meta_method(elua::MetaMethod::Mul, |_, this, (quat,): (LuaQuat,)| { + methods.add_meta_method(mlua::MetaMethod::Mul, |_, this, (quat,): (LuaQuat,)| { let mut t = *this; t.rotation *= *quat; Ok(t) }); // move a transform - builder.meta_method(elua::MetaMethod::Add, |_, this, (pos,): (LuaVec3,)| { + methods.add_meta_method(mlua::MetaMethod::Add, |_, this, (pos,): (LuaVec3,)| { let mut t = *this; t.translation += *pos; Ok(t) }); } -); +); \ No newline at end of file diff --git a/lyra-scripting/src/world.rs b/lyra-scripting/src/world.rs index fd27bc8..1417b5b 100644 --- a/lyra-scripting/src/world.rs +++ b/lyra-scripting/src/world.rs @@ -1,6 +1,7 @@ -use std::ptr::NonNull; +use std::{ops::Deref, ptr::NonNull, sync::Arc}; use lyra_ecs::{World, Entity}; +use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; #[derive(Clone)] pub struct ScriptEntity(pub Entity); @@ -14,33 +15,41 @@ impl std::ops::Deref for ScriptEntity { } #[derive(Clone)] -pub struct ScriptWorldPtr { - pub inner: NonNull, -} +pub struct ScriptWorldPtr(Arc>>); impl ScriptWorldPtr { - /// Creates a world pointer from a world borrow. - pub fn from_ref(world: &World) -> Self { - Self { - inner: NonNull::from(world), - } + pub fn read(&self) -> MappedRwLockReadGuard { + RwLockReadGuard::map(self.0.read(), |p| unsafe { p.as_ref() }) } - /// Returns a borrow to the world from the ptr. - pub fn as_ref(&self) -> &World { - unsafe { self.inner.as_ref() } - } - - /// Returns a mutable borrow to the world from the ptr. - pub fn as_mut(&mut self) -> &mut World { - unsafe { self.inner.as_mut() } + pub fn write(&self) -> MappedRwLockWriteGuard { + RwLockWriteGuard::map(self.0.write(), |p| unsafe { p.as_mut() }) } } -impl std::ops::Deref for ScriptWorldPtr { - type Target = NonNull; +// SAFETY: The inner NonNull pointer is wrapped in an Arc> +unsafe impl Send for ScriptWorldPtr {} +unsafe impl Sync for ScriptWorldPtr {} + +#[derive(Clone)] +pub struct ScriptWorldPtrGuard(ScriptWorldPtr); + +impl Deref for ScriptWorldPtrGuard { + type Target = ScriptWorldPtr; fn deref(&self) -> &Self::Target { - &self.inner + &self.0 + } +} + +impl ScriptWorldPtrGuard { + /// Creates a new world pointer. + /// + /// # Safety + /// The original `&mut World` must not be used while this guard is created. + /// The [World] may only be accessed through this guard or one of its cloned [ScriptWorldPtr]s. + #[allow(clippy::arc_with_non_send_sync)] + pub unsafe fn new(world: &mut World) -> Self { + ScriptWorldPtrGuard(ScriptWorldPtr(Arc::new(RwLock::new(NonNull::from(world))))) } } \ No newline at end of file diff --git a/lyra-scripting/src/wrap.rs b/lyra-scripting/src/wrap.rs index d0c6c76..4bb6d79 100644 --- a/lyra-scripting/src/wrap.rs +++ b/lyra-scripting/src/wrap.rs @@ -9,4 +9,7 @@ impl std::ops::Deref for ScriptDynamicBundle { fn deref(&self) -> &Self::Target { &self.0 } -} \ No newline at end of file +} + +// SAFETY: todo!() +unsafe impl Send for ScriptDynamicBundle {} \ No newline at end of file