summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock287
-rw-r--r--Cargo.toml42
-rw-r--r--nix/flake.lock27
-rw-r--r--nix/flake.nix32
-rw-r--r--src/audio.rs66
-rw-r--r--src/context.rs36
-rw-r--r--src/lib.rs284
-rw-r--r--src/module.rs45
-rw-r--r--src/request.rs20
-rw-r--r--src/state.rs28
10 files changed, 638 insertions, 229 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4fff158..a7ec47c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -47,13 +47,22 @@ dependencies = [
]
[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "android-activity"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289"
dependencies = [
"android-properties",
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"cc",
"cesu8",
"jni",
@@ -74,6 +83,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
[[package]]
+name = "anstream"
+version = "0.6.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
name = "arrayref"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -144,9 +202,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.2"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-sys"
@@ -197,7 +255,7 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"log",
"polling",
"rustix",
@@ -247,12 +305,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
+name = "cgl"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
name = "combine"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -434,6 +507,29 @@ dependencies = [
]
[[package]]
+name = "env_filter"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "humantime",
+ "log",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -635,6 +731,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
+name = "gl_generator"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
+dependencies = [
+ "khronos_api",
+ "log",
+ "xml-rs",
+]
+
+[[package]]
name = "glam"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -653,6 +760,71 @@ dependencies = [
]
[[package]]
+name = "glutin"
+version = "0.31.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746"
+dependencies = [
+ "bitflags 2.6.0",
+ "cfg_aliases",
+ "cgl",
+ "core-foundation",
+ "dispatch",
+ "glutin_egl_sys",
+ "glutin_glx_sys",
+ "glutin_wgl_sys",
+ "icrate",
+ "libloading",
+ "objc2",
+ "once_cell",
+ "raw-window-handle 0.5.2",
+ "wayland-sys",
+ "windows-sys 0.48.0",
+ "x11-dl",
+]
+
+[[package]]
+name = "glutin-winit"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735"
+dependencies = [
+ "cfg_aliases",
+ "glutin",
+ "raw-window-handle 0.5.2",
+ "winit",
+]
+
+[[package]]
+name = "glutin_egl_sys"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd"
+dependencies = [
+ "gl_generator",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "glutin_glx_sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f"
+dependencies = [
+ "gl_generator",
+ "x11-dl",
+]
+
+[[package]]
+name = "glutin_wgl_sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead"
+dependencies = [
+ "gl_generator",
+]
+
+[[package]]
name = "h2"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -734,6 +906,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
name = "hyper"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -861,6 +1039,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -916,6 +1100,12 @@ dependencies = [
]
[[package]]
+name = "khronos_api"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
+
+[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -940,7 +1130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164"
dependencies = [
"cfg-if",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -949,7 +1139,7 @@ version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"libc",
"redox_syscall 0.4.1",
]
@@ -1042,12 +1232,13 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"jni-sys",
"log",
"ndk-sys",
"num_enum",
- "raw-window-handle",
+ "raw-window-handle 0.5.2",
+ "raw-window-handle 0.6.0",
"thiserror",
]
@@ -1139,7 +1330,7 @@ version = "0.10.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
@@ -1329,6 +1520,12 @@ dependencies = [
[[package]]
name = "raw-window-handle"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
+
+[[package]]
+name = "raw-window-handle"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544"
@@ -1372,6 +1569,35 @@ dependencies = [
]
[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
name = "reqwest"
version = "0.12.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1441,7 +1667,7 @@ version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"errno",
"libc",
"linux-raw-sys",
@@ -1654,7 +1880,7 @@ version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"calloop",
"calloop-wayland-source",
"cursor-icon",
@@ -1739,7 +1965,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"core-foundation",
"system-configuration-sys",
]
@@ -1763,13 +1989,17 @@ dependencies = [
"console_error_panic_hook",
"console_log",
"enum-map",
+ "env_logger",
"getrandom",
"glam",
"glow",
+ "glutin",
+ "glutin-winit",
"image",
"js-sys",
"log",
"rand",
+ "raw-window-handle 0.5.2",
"reqwest",
"serde",
"tobj",
@@ -2065,6 +2295,12 @@ dependencies = [
]
[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2187,7 +2423,7 @@ version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"rustix",
"wayland-backend",
"wayland-scanner",
@@ -2199,7 +2435,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"cursor-icon",
"wayland-backend",
]
@@ -2221,7 +2457,7 @@ version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"wayland-backend",
"wayland-client",
"wayland-scanner",
@@ -2233,7 +2469,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"wayland-backend",
"wayland-client",
"wayland-protocols",
@@ -2246,7 +2482,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"wayland-backend",
"wayland-client",
"wayland-protocols",
@@ -2579,14 +2815,14 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winit"
-version = "0.29.13"
+version = "0.29.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b9d7047a2a569d5a81e3be098dcd8153759909b127477f4397e03cf1006d90a"
+checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca"
dependencies = [
"ahash",
"android-activity",
"atomic-waker",
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"bytemuck",
"calloop",
"cfg_aliases",
@@ -2604,7 +2840,8 @@ dependencies = [
"once_cell",
"orbclient",
"percent-encoding",
- "raw-window-handle",
+ "raw-window-handle 0.5.2",
+ "raw-window-handle 0.6.0",
"redox_syscall 0.3.5",
"rustix",
"sctk-adwaita",
@@ -2678,7 +2915,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
"dlib",
"log",
"once_cell",
@@ -2692,6 +2929,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621"
[[package]]
+name = "xml-rs"
+version = "0.8.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26"
+
+[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 67ea1f8..3ea5ef3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,7 +15,6 @@ codegen-units = 1
opt-level = 2
[dependencies]
-winit = "*" # windowing and events
glow = {version = "*", features = []} # rendering
tobj = "*" # model loader
# gltf = {version = "*", features = ["extras", "names"]} # model loader
@@ -23,37 +22,26 @@ image = "*" # texture loader
glam = "*" # linear algebra
log = "*" # logging
rand = {version = "*", features = ["small_rng"]} # rng
-getrandom = {version = "*", features = ["js"]} # rng in the browser
serde = {version = "*", features = ["derive"]} # serialization
+enum-map = "*" # fast maps with enums as keys
+bimap = "*" # bijective maps
+reqwest = "*" # http requests
+bytes = "*" # bytes for http responses
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+winit = "*" # windowing and events
+getrandom = {version = "*", features = ["js"]} # rng in the browser
console_log = "*" # log to browser console
console_error_panic_hook = "*" # log to browser console on panic
tracing-wasm = "*" # trace performance in browser
wasm-bindgen = "*" # interface with javascript
wasm-bindgen-futures = "*" # interface with async javascript
js-sys = "*" # browser APIs to interact with JS runtime (e.g. run WASM)
-enum-map = "*" # fast maps with enums as keys
-bimap = "*" # bijective maps
-reqwest = "*" # http requests
-bytes = "*" # bytes for http responses
+web-sys = { version = "*", features = ["Document", "Window", "Element", "HtmlCanvasElement", "WebGl2RenderingContext", "Headers", "Request", "RequestInit", "RequestMode", "Response", "Performance", "PerformanceTiming", "AudioContext", "AudioNode", "AudioDestinationNode", "AudioBuffer", "AudioBufferSourceNode"] }
-[dependencies.web-sys] # common browser APIs
-version = "*"
-features = [
- "Document",
- "Window",
- "Element",
- "HtmlCanvasElement",
- "WebGl2RenderingContext",
- "Headers",
- "Request",
- "RequestInit",
- "RequestMode",
- "Response",
- "Performance",
- "PerformanceTiming",
- "AudioContext",
- "AudioNode",
- "AudioDestinationNode",
- "AudioBuffer",
- "AudioBufferSourceNode",
-] \ No newline at end of file
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+env_logger = "*"
+winit = { version = "0.29", features = ["x11", "rwh_05"], default-features = false } # windowing and events
+raw-window-handle = { version = "0.5" } # get window handle
+glutin = { version = "0.31" } # obtain opengl context
+glutin-winit = { version = "0.4" } # obtain opengl context \ No newline at end of file
diff --git a/nix/flake.lock b/nix/flake.lock
new file mode 100644
index 0000000..780a8b9
--- /dev/null
+++ b/nix/flake.lock
@@ -0,0 +1,27 @@
+{
+ "nodes": {
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1729788628,
+ "narHash": "sha256-3suayUinicnvE/4shMZwp9FHT5izUM8gMpdEO/NHBTo=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "63487b2f26fa065cfeeaa47dddb08e2856ba53e8",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/nix/flake.nix b/nix/flake.nix
new file mode 100644
index 0000000..3f5071a
--- /dev/null
+++ b/nix/flake.nix
@@ -0,0 +1,32 @@
+{
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ };
+
+ outputs = { self, nixpkgs, ... }@inputs:
+ let
+ system = "x86_64-linux";
+ pkgs = nixpkgs.legacyPackages.${system};
+ in {
+ devShells.x86_64-linux.default = pkgs.mkShell {
+ buildInputs = [
+ pkgs.pkg-config
+ pkgs.llvm
+ pkgs.clang
+ pkgs.llvmPackages.libclang
+ pkgs.openssl
+ ];
+ LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:${
+ with pkgs;
+ pkgs.lib.makeLibraryPath [
+ libGL
+ xorg.libX11
+ xorg.libXcursor
+ xorg.libXi
+ libxkbcommon
+ xorg.libxcb
+ ]
+ }";
+ };
+ };
+}
diff --git a/src/audio.rs b/src/audio.rs
index 2b190de..5cbce90 100644
--- a/src/audio.rs
+++ b/src/audio.rs
@@ -1,9 +1,11 @@
use std::{cell::RefCell, collections::HashMap};
+#[cfg(target_arch = "wasm32")]
pub struct Context {
pub audio: web_sys::AudioContext,
}
+#[cfg(target_arch = "wasm32")]
impl Context {
pub fn new() -> Self {
let audio = web_sys::AudioContext::new()
@@ -14,11 +16,13 @@ impl Context {
}
}
+#[cfg(target_arch = "wasm32")]
pub struct Audio {
pub buffer: &'static RefCell<Option<web_sys::AudioBuffer>>,
//pub source: &'static web_sys::AudioBufferSourceNode,
}
+#[cfg(target_arch = "wasm32")]
impl Audio {
pub fn new(ctx: &Context, bytes: &[u8]) -> Self {
let sbuffer: &_ = Box::leak(Box::new(RefCell::new(None)));
@@ -52,6 +56,7 @@ impl Audio {
}
}
+#[cfg(target_arch = "wasm32")]
pub struct Assets {
pub ctx: Context,
@@ -60,6 +65,7 @@ pub struct Assets {
pub music_node: Option<web_sys::AudioBufferSourceNode>,
}
+#[cfg(target_arch = "wasm32")]
impl Assets {
pub fn new<F>(f : F) -> Self where F: Fn(&Context) -> HashMap<String, Audio> {
let ctx = Context::new();
@@ -94,3 +100,63 @@ impl Assets {
}
}
}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub struct Context {
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+impl Context {
+ pub fn new() -> Self {
+ Self {
+ }
+ }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub struct Audio {
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+impl Audio {
+ pub fn new(ctx: &Context, _bytes: &[u8]) -> Self {
+ Self {
+ }
+ }
+
+ pub fn play(&self, ctx: &Context, looping: Option<(Option<f64>, Option<f64>)>) {
+ }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub struct Assets {
+ pub ctx: Context,
+ pub audio: HashMap<String, Audio>,
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+impl Assets {
+ pub fn new<F>(f : F) -> Self where F: Fn(&Context) -> HashMap<String, Audio> {
+ let ctx = Context::new();
+
+ let audio = f(&ctx);
+
+ Self {
+ ctx,
+ audio,
+ }
+ }
+
+ pub fn play_sfx(&mut self, name: &str) {
+ if let Some(a) = self.audio.get(name) {
+ a.play(&self.ctx, None);
+ }
+ }
+
+ pub fn is_music_playing(&self) -> bool {
+ false
+ }
+
+ pub fn play_music(&mut self, name: &str, start: Option<f64>, end: Option<f64>) {
+ }
+}
diff --git a/src/context.rs b/src/context.rs
index dc1d3a2..c6c68bc 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -1,17 +1,15 @@
-use wasm_bindgen::JsCast;
-use winit::platform::web::WindowExtWebSys;
use glow::HasContext;
+#[cfg(target_arch = "wasm32")]
+use winit::platform::web::WindowExtWebSys;
+
+#[cfg(target_arch = "wasm32")]
#[link(wasm_import_module = "./helpers.js")]
extern {
fn js_track_resized_setup();
fn js_poll_resized() -> bool;
}
-// pub const RENDER_WIDTH: f32 = 640.0;
-// pub const RENDER_HEIGHT: f32 = 360.0;
-// pub const RENDER_WIDTH: f32 = 320.0;
-// pub const RENDER_HEIGHT: f32 = 180.0;
pub const RENDER_WIDTH: f32 = 240.0;
pub const RENDER_HEIGHT: f32 = 160.0;
@@ -32,23 +30,13 @@ pub struct Context {
pub window: winit::window::Window,
pub gl: glow::Context,
pub emptyvao: glow::VertexArray,
+
+ #[cfg(target_arch = "wasm32")]
pub performance: web_sys::Performance,
}
impl Context {
- pub fn new(window: winit::window::Window) -> Self {
- let gl = web_sys::window()
- .and_then(|win| win.document())
- .and_then(|doc| {
- let dst = doc.get_element_by_id("teleia-parent")?;
- let canvas = web_sys::Element::from(window.canvas().expect("failed to find canvas"));
- dst.append_child(&canvas).ok()?;
- let c = canvas.dyn_into::<web_sys::HtmlCanvasElement>().ok()?;
- let webgl2_context = c.get_context("webgl2").ok()??
- .dyn_into::<web_sys::WebGl2RenderingContext>().ok()?;
- Some(glow::Context::from_webgl2_context(webgl2_context))
- })
- .expect("couldn't add canvas to document");
+ pub fn new(window: winit::window::Window, gl: glow::Context) -> Self {
unsafe {
gl.clear_color(0.1, 0.1, 0.1, 1.0);
gl.clear_depth_f32(1.0);
@@ -68,17 +56,21 @@ impl Context {
gl.create_vertex_array().expect("failed to initialize vao")
};
+ #[cfg(target_arch = "wasm32")]
unsafe { js_track_resized_setup(); }
Self {
window,
gl,
emptyvao,
+
+ #[cfg(target_arch = "wasm32")]
performance: web_sys::window().expect("failed to find window")
.performance().expect("failed to get performance"),
}
}
+ #[cfg(target_arch = "wasm32")]
pub fn maximize_canvas(&self) {
web_sys::window()
.and_then(|win| win.document())
@@ -100,12 +92,18 @@ impl Context {
.expect("failed to resize canvas");
}
+ #[cfg(target_arch = "wasm32")]
pub fn resize_necessary(&self) -> bool {
unsafe {
js_poll_resized()
}
}
+ #[cfg(not(target_arch = "wasm32"))]
+ pub fn resize_necessary(&self) -> bool {
+ false
+ }
+
pub fn clear_color(&self, color: glam::Vec4) {
unsafe {
self.gl.clear_color(color.x, color.y, color.z, color.w);
diff --git a/src/lib.rs b/src/lib.rs
index 41bfee8..b89b27e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,5 @@
-use winit::platform::web::EventLoopExtWebSys;
-
pub mod utils;
pub mod ui;
-pub mod request;
pub mod context;
pub mod state;
pub mod framebuffer;
@@ -10,9 +7,17 @@ pub mod shader;
pub mod mesh;
pub mod texture;
pub mod font;
-pub mod audio;
pub mod shadow;
-pub mod module;
+pub mod audio;
+
+#[cfg(target_arch = "wasm32")]
+use winit::platform::web::EventLoopExtWebSys;
+
+#[cfg(target_arch = "wasm32")]
+use winit::platform::web::WindowExtWebSys;
+
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen::JsCast;
static mut CTX: Option<*const context::Context> = None;
static mut ST: Option<*mut state::State> = None;
@@ -30,28 +35,186 @@ where
}
}
+pub fn event_loop_body<G>(event: winit::event::Event<()>, elwt: &winit::event_loop::EventLoopWindowTarget<()>)
+ where G: state::Game + 'static,
+{
+ contextualize(|ctx, st, game: &mut G| {
+ match &event {
+ winit::event::Event::WindowEvent {
+ event: wev,
+ window_id,
+ ..
+ } => match wev {
+ winit::event::WindowEvent::CloseRequested
+ if *window_id == ctx.window.id() => elwt.exit(),
+ winit::event::WindowEvent::Resized{..} => {
+ #[cfg(target_arch = "wasm32")]
+ ctx.maximize_canvas();
+ st.handle_resize(&ctx);
+ },
+ winit::event::WindowEvent::Focused(false) => {
+ st.keys = state::Keys::new();
+ },
+ winit::event::WindowEvent::CursorMoved { position, ..} => {
+ st.mouse_moved(&ctx, position.x as f32, position.y as f32, game);
+ },
+ winit::event::WindowEvent::MouseInput {
+ button,
+ state,
+ ..
+ } => match state {
+ winit::event::ElementState::Pressed => {
+ st.mouse_pressed(&ctx, *button, game)
+ },
+ winit::event::ElementState::Released => {
+ st.mouse_released(&ctx, *button)
+ },
+ }
+ winit::event::WindowEvent::KeyboardInput {
+ event: winit::event::KeyEvent {
+ physical_key: winit::keyboard::PhysicalKey::Code(key),
+ state,
+ repeat: false,
+ ..
+ },
+ ..
+ } => match state {
+ winit::event::ElementState::Pressed => {
+ st.key_pressed(&ctx, *key)
+ },
+ winit::event::ElementState::Released => {
+ st.key_released(&ctx, *key)
+ },
+ }
+ _ => {},
+ },
+
+ winit::event::Event::AboutToWait => {
+ if ctx.resize_necessary() {
+ #[cfg(target_arch = "wasm32")]
+ ctx.maximize_canvas();
+ st.handle_resize(&ctx);
+ }
+ if let Some(f) = &mut st.request {
+ match std::future::Future::poll(f.as_mut(), &mut st.waker_ctx) {
+ std::task::Poll::Pending => {},
+ std::task::Poll::Ready(res) => {
+ st.request = None;
+ match res {
+ Ok(r) => st.request_returned(&ctx, game, r),
+ Err(e) => log::warn!("error during HTTP request: {}", e),
+ }
+ },
+ }
+ // f.poll();
+ }
+ st.run_update(&ctx, game);
+ st.run_render(&ctx, game);
+ ctx.window.request_redraw();
+ },
+
+ _ => {},
+ }
+ });
+}
+
pub async fn run<'a, F, G, Fut>(gnew: F)
where
Fut: std::future::Future<Output = G>,
G: state::Game + 'static,
F: (Fn(&'a context::Context) -> Fut),
{
- console_log::init_with_level(log::Level::Debug).unwrap();
- console_error_panic_hook::set_once();
- tracing_wasm::set_as_global_default();
+ #[cfg(target_arch = "wasm32")]
+ {
+ console_log::init_with_level(log::Level::Debug).unwrap();
+ console_error_panic_hook::set_once();
+ tracing_wasm::set_as_global_default();
+ }
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ env_logger::Builder::new()
+ .filter(None, log::LevelFilter::Info)
+ .init();
+ }
log::info!("hello computer, starting up...");
let event_loop = winit::event_loop::EventLoop::new()
.expect("failed to initialize event loop");
- let window = winit::window::WindowBuilder::new()
- .with_maximized(true)
- .with_decorations(false)
- .build(&event_loop)
- .expect("failed to initialize window");
+ #[cfg(target_arch = "wasm32")]
+ let (window, gl) = {
+ let window = winit::window::WindowBuilder::new()
+ .with_maximized(true)
+ .with_decorations(false)
+ .build(&event_loop)
+ .expect("failed to initialize window");
+ let gl = web_sys::window()
+ .and_then(|win| win.document())
+ .and_then(|doc| {
+ let dst = doc.get_element_by_id("teleia-parent")?;
+ let canvas = web_sys::Element::from(window.canvas().expect("failed to find canvas"));
+ dst.append_child(&canvas).ok()?;
+ let c = canvas.dyn_into::<web_sys::HtmlCanvasElement>().ok()?;
+ let webgl2_context = c.get_context("webgl2").ok()??
+ .dyn_into::<web_sys::WebGl2RenderingContext>().ok()?;
+ Some(glow::Context::from_webgl2_context(webgl2_context))
+ })
+ .expect("couldn't add canvas to document");
+ (window, gl)
+ };
+
+ #[cfg(not(target_arch = "wasm32"))]
+ let (window, gl) = {
+ use glutin::config::GlConfig;
+ use glutin::context::NotCurrentGlContext;
+ use glutin::display::{GlDisplay, GetGlDisplay};
+ use glutin::surface::GlSurface;
+ use raw_window_handle::HasRawWindowHandle;
+ use glutin_winit::GlWindow;
+ let window_builder = winit::window::WindowBuilder::new()
+ .with_title("teleia")
+ .with_maximized(true)
+ .with_decorations(false);
+ let template = glutin::config::ConfigTemplateBuilder::new();
+ let display_builder = glutin_winit::DisplayBuilder::new().with_window_builder(Some(window_builder));
+ let (window, gl_config) = display_builder
+ .build(&event_loop, template, |configs| {
+ configs.reduce(|a, c| {
+ if c.num_samples() > a.num_samples() { c } else { a }
+ }).expect("failed to obtain select configuration")
+ }).expect("failed to obtain opengl display");
+ let window = window.expect("failed to create window");
+ let raw_window_handle = window.raw_window_handle();
+ let gl_display = gl_config.display();
+ let context_attributes = glutin::context::ContextAttributesBuilder::new()
+ // .with_context_api(glutin::context::ContextApi::OpenGl(Some(glutin::context::Version {
+ // major: 3,
+ // minor: 3,
+ // })))
+ .build(Some(raw_window_handle));
+ unsafe {
+ let not_current_gl_context = gl_display.create_context(&gl_config, &context_attributes)
+ .expect("failed to obtain opengl context");
+ let attrs = window.build_surface_attributes(Default::default());
+ let gl_surface = gl_display.create_window_surface(&gl_config, &attrs)
+ .expect("failed to create opengl surface");
+ let gl_context = not_current_gl_context.make_current(&gl_surface)
+ .expect("failed to set openglt context");
+ let gl = glow::Context::from_loader_function_cstr(|s| gl_display.get_proc_address(s));
+ gl_surface
+ .set_swap_interval(&gl_context, glutin::surface::SwapInterval::Wait(std::num::NonZeroU32::new(1).unwrap()))
+ .expect("failed to set swap interval");
+ (window, gl)
+ }
+ };
+
+ let ctx = Box::leak(Box::new(context::Context::new(window, gl)));
+
+ #[cfg(target_arch = "wasm32")]
+ {
+ ctx.maximize_canvas();
+ }
- let ctx = Box::leak(Box::new(context::Context::new(window)));
- ctx.maximize_canvas();
let game = Box::leak(Box::new(gnew(ctx).await));
let st = Box::leak(Box::new(state::State::new(&ctx)));
// request = Some(Box::new(async {
@@ -64,83 +227,20 @@ where
G = Some(game as *mut G as *mut std::ffi::c_void);
}
- event_loop.set_control_flow(winit::event_loop::ControlFlow::Wait);
- event_loop.spawn(|event, elwt| {
- contextualize(|ctx, st, game: &mut G| {
- match &event {
- winit::event::Event::WindowEvent {
- event: wev,
- window_id,
- ..
- } => match wev {
- winit::event::WindowEvent::CloseRequested
- if *window_id == ctx.window.id() => elwt.exit(),
- winit::event::WindowEvent::Resized{..} => {
- ctx.maximize_canvas();
- st.handle_resize(&ctx);
- },
- winit::event::WindowEvent::Focused(false) => {
- st.keys = state::Keys::new();
- },
- winit::event::WindowEvent::CursorMoved { position, ..} => {
- st.mouse_moved(&ctx, position.x as f32, position.y as f32, game);
- },
- winit::event::WindowEvent::MouseInput {
- button,
- state,
- ..
- } => match state {
- winit::event::ElementState::Pressed => {
- st.mouse_pressed(&ctx, *button, game)
- },
- winit::event::ElementState::Released => {
- st.mouse_released(&ctx, *button)
- },
- }
- winit::event::WindowEvent::KeyboardInput {
- event: winit::event::KeyEvent {
- physical_key: winit::keyboard::PhysicalKey::Code(key),
- state,
- repeat: false,
- ..
- },
- ..
- } => match state {
- winit::event::ElementState::Pressed => {
- st.key_pressed(&ctx, *key)
- },
- winit::event::ElementState::Released => {
- st.key_released(&ctx, *key)
- },
- }
- _ => {},
- },
-
- winit::event::Event::AboutToWait => {
- if ctx.resize_necessary() {
- ctx.maximize_canvas();
- st.handle_resize(&ctx);
- }
- if let Some(f) = &mut st.request {
- match std::future::Future::poll(f.as_mut(), &mut st.waker_ctx) {
- std::task::Poll::Pending => {},
- std::task::Poll::Ready(res) => {
- st.request = None;
- match res {
- Ok(r) => st.request_returned(&ctx, game, r),
- Err(e) => log::warn!("error during HTTP request: {}", e),
- }
- },
- }
- // f.poll();
- }
- st.run_update(&ctx, game);
- st.run_render(&ctx, game);
- ctx.window.request_redraw();
- },
- _ => {},
- }
+ #[cfg(target_arch = "wasm32")]
+ {
+ event_loop.set_control_flow(winit::event_loop::ControlFlow::Wait);
+ event_loop.spawn(|event, elwt| {
+ event_loop_body::<G>(event, elwt);
});
- });
+ }
+
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll);
+ event_loop.run(|event, elwt| {
+ event_loop_body::<G>(event, elwt);
+ }).expect("window closed");
+ }
}
diff --git a/src/module.rs b/src/module.rs
deleted file mode 100644
index 1fc4100..0000000
--- a/src/module.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use wasm_bindgen::prelude::*;
-
-#[wasm_bindgen]
-pub fn log_info(msg: i8) {
- log::info!("{:?}", msg);
-}
-
-#[wasm_bindgen(module="/src/js/module.js")]
-extern "C" {
- fn js_build_interface() -> js_sys::Object;
-}
-
-pub struct Module {
- pub wasm: js_sys::WebAssembly::Instance,
-}
-
-impl Module {
- pub async fn new(bytes: &[u8]) -> Option<Self> {
- let imp = js_build_interface();
- let o = wasm_bindgen_futures::JsFuture::from(
- js_sys::WebAssembly::instantiate_buffer(bytes, &imp)
- ).await.unwrap();
- let i = js_sys::Reflect::get(&o, &"instance".into()).unwrap();
- if let Ok(wasm) = i.dyn_into::<js_sys::WebAssembly::Instance>() {
- Some(Self {
- wasm,
- })
- } else {
- log::info!("failed 3");
- None
- }
- }
- pub fn call(&self, nm: &str) {
- let exp = self.wasm.exports();
- if let Ok(fo) = js_sys::Reflect::get(&exp, &nm.into()) {
- if let Ok(func) = fo.dyn_into::<js_sys::Function>() {
- let _ = func.call0(&JsValue::undefined());
- } else {
- log::warn!("couldn't cast module function: {}", nm);
- }
- } else {
- log::warn!("couldn't find module function: {}", nm);
- }
- }
-}
diff --git a/src/request.rs b/src/request.rs
deleted file mode 100644
index 7f66f57..0000000
--- a/src/request.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use wasm_bindgen::JsCast;
-
-pub async fn get_store(key: &str) -> Option<String> {
- let mut opts = web_sys::RequestInit::new();
- opts.method("GET");
- opts.mode(web_sys::RequestMode::Cors);
-
- let url = format!("https://colonq.computer/bullfrog/api/get/{}", key);
-
- let request = web_sys::Request::new_with_str_and_init(&url, &opts).ok()?;
-
- let window = web_sys::window().unwrap();
- let resp_value = wasm_bindgen_futures::JsFuture::from(window.fetch_with_request(&request)).await.ok()?;
-
- assert!(resp_value.is_instance_of::<web_sys::Response>());
- let resp: web_sys::Response = resp_value.dyn_into().unwrap();
-
- let text = wasm_bindgen_futures::JsFuture::from(resp.text().ok()?).await.ok()?;
- text.as_string()
-}
diff --git a/src/state.rs b/src/state.rs
index 8c70c51..c5478a9 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -93,9 +93,15 @@ pub struct PointLight {
pub attenuation: glam::Vec2,
}
+#[cfg(target_arch = "wasm32")]
+type Timestamp = f64;
+
+#[cfg(not(target_arch = "wasm32"))]
+type Timestamp = std::time::Instant;
+
pub struct State {
pub acc: f64,
- pub last: f64,
+ pub last: Timestamp,
pub tick: u64,
pub rebinding: Option<Key>,
@@ -119,10 +125,16 @@ pub struct State {
pub log: Vec<(u64, String)>,
}
-pub fn now(ctx: &context::Context) -> f64 {
+#[cfg(target_arch = "wasm32")]
+pub fn now(ctx: &context::Context) -> Timestamp {
ctx.performance.now() / 1000.0
}
+#[cfg(not(target_arch = "wasm32"))]
+pub fn now(_ctx: &context::Context) -> Timestamp {
+ std::time::Instant::now()
+}
+
pub fn default_keybindings() -> BiHashMap<winit::keyboard::KeyCode, Key> {
BiHashMap::from_iter(vec![
(winit::keyboard::KeyCode::KeyW, Key::Up),
@@ -156,9 +168,12 @@ impl State {
let cwaker = Box::leak(Box::new(waker.into()));
let waker_ctx = std::task::Context::from_waker(cwaker);
+ let acc = 0.0;
+ let last = now(ctx);
+
Self {
- acc: 0.0,
- last: now(ctx),
+ acc,
+ last,
// we initialize the tick to 1000, which allows us to use "0" as the default time for
// various animation starts on entities without having them all play at game start
tick: 1000,
@@ -421,7 +436,12 @@ impl State {
pub fn run_update<G>(&mut self, ctx: &context::Context, game: &mut G) where G: Game {
let now = now(ctx);
+
+ #[cfg(target_arch = "wasm32")]
let diff = now - self.last;
+ #[cfg(not(target_arch = "wasm32"))]
+ let diff = now.duration_since(self.last).as_secs_f64();
+
self.acc += diff;
self.last = now;