+359
-4
Cargo.lock
+359
-4
Cargo.lock
···
104
]
105
106
[[package]]
107
name = "alsa"
108
version = "0.9.1"
109
source = "registry+https://github.com/rust-lang/crates.io-index"
···
135
"bitflags 2.10.0",
136
"cc",
137
"cesu8",
138
-
"jni",
139
"jni-sys",
140
"libc",
141
"log",
···
181
dependencies = [
182
"num-traits",
183
]
184
185
[[package]]
186
name = "arrayref"
···
987
checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59"
988
989
[[package]]
990
name = "bevy_pbr"
991
version = "0.17.3"
992
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1535
]
1536
1537
[[package]]
1538
name = "bindgen"
1539
version = "0.72.1"
1540
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1553
]
1554
1555
[[package]]
1556
name = "bit-set"
1557
version = "0.8.0"
1558
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1631
"futures-io",
1632
"futures-lite",
1633
"piper",
1634
]
1635
1636
[[package]]
···
1976
"core-foundation-sys",
1977
"coreaudio-rs 0.11.3",
1978
"dasp_sample",
1979
-
"jni",
1980
"js-sys",
1981
"libc",
1982
"mach2",
···
1998
"alsa",
1999
"coreaudio-rs 0.13.0",
2000
"dasp_sample",
2001
-
"jni",
2002
"js-sys",
2003
"libc",
2004
"mach2",
···
2016
]
2017
2018
[[package]]
2019
name = "crc32fast"
2020
version = "1.5.0"
2021
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2304
]
2305
2306
[[package]]
2307
name = "felix-audio"
2308
version = "0.1.0"
2309
dependencies = [
···
2322
dependencies = [
2323
"anyhow",
2324
"bevy",
2325
"cpal 0.16.0",
2326
"dotenvy",
2327
"felix-audio",
2328
"felix-net",
2329
"tokio",
2330
]
2331
···
2882
2883
[[package]]
2884
name = "jni"
2885
version = "0.21.1"
2886
source = "registry+https://github.com/rust-lang/crates.io-index"
2887
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
···
3069
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
3070
3071
[[package]]
3072
name = "mach2"
3073
version = "0.4.3"
3074
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3342
]
3343
3344
[[package]]
3345
name = "num_enum"
3346
version = "0.7.5"
3347
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3657
source = "registry+https://github.com/rust-lang/crates.io-index"
3658
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
3659
dependencies = [
3660
-
"jni",
3661
"ndk 0.8.0",
3662
"ndk-context",
3663
"num-derive",
···
3700
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
3701
3702
[[package]]
3703
name = "opus"
3704
version = "0.3.0"
3705
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3735
dependencies = [
3736
"ttf-parser 0.25.1",
3737
]
3738
3739
[[package]]
3740
name = "parking"
···
4316
]
4317
4318
[[package]]
4319
name = "serde_core"
4320
version = "1.0.228"
4321
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4346
"ryu",
4347
"serde",
4348
"serde_core",
4349
]
4350
4351
[[package]]
···
5028
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
5029
5030
[[package]]
5031
name = "uuid"
5032
version = "1.19.0"
5033
source = "registry+https://github.com/rust-lang/crates.io-index"
···
5294
"js-sys",
5295
"log",
5296
"naga",
5297
"portable-atomic",
5298
"profiling",
5299
"raw-window-handle",
5300
"smallvec",
5301
"static_assertions",
5302
"wasm-bindgen",
5303
"web-sys",
5304
"wgpu-core",
5305
"wgpu-hal",
···
5331
"smallvec",
5332
"thiserror 2.0.17",
5333
"wgpu-core-deps-apple",
5334
"wgpu-core-deps-wasm",
5335
"wgpu-core-deps-windows-linux-android",
5336
"wgpu-hal",
···
5342
version = "26.0.0"
5343
source = "registry+https://github.com/rust-lang/crates.io-index"
5344
checksum = "18ae5fbde6a4cbebae38358aa73fcd6e0f15c6144b67ef5dc91ded0db125dbdf"
5345
dependencies = [
5346
"wgpu-hal",
5347
]
···
104
]
105
106
[[package]]
107
+
name = "alloc-no-stdlib"
108
+
version = "2.0.4"
109
+
source = "registry+https://github.com/rust-lang/crates.io-index"
110
+
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
111
+
112
+
[[package]]
113
+
name = "alloc-stdlib"
114
+
version = "0.2.2"
115
+
source = "registry+https://github.com/rust-lang/crates.io-index"
116
+
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
117
+
dependencies = [
118
+
"alloc-no-stdlib",
119
+
]
120
+
121
+
[[package]]
122
name = "alsa"
123
version = "0.9.1"
124
source = "registry+https://github.com/rust-lang/crates.io-index"
···
150
"bitflags 2.10.0",
151
"cc",
152
"cesu8",
153
+
"jni 0.21.1",
154
"jni-sys",
155
"libc",
156
"log",
···
196
dependencies = [
197
"num-traits",
198
]
199
+
200
+
[[package]]
201
+
name = "array-init"
202
+
version = "2.1.0"
203
+
source = "registry+https://github.com/rust-lang/crates.io-index"
204
+
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
205
206
[[package]]
207
name = "arrayref"
···
1008
checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59"
1009
1010
[[package]]
1011
+
name = "bevy_mod_openxr"
1012
+
version = "0.4.0"
1013
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1014
+
checksum = "1ead3d12dc1c364bc8f5d063c8cd82df23a3d6261807abecfbbca70ca3cb2c15"
1015
+
dependencies = [
1016
+
"android_system_properties",
1017
+
"ash",
1018
+
"bevy_app",
1019
+
"bevy_camera",
1020
+
"bevy_derive",
1021
+
"bevy_ecs",
1022
+
"bevy_log",
1023
+
"bevy_math",
1024
+
"bevy_mod_xr",
1025
+
"bevy_platform",
1026
+
"bevy_render",
1027
+
"bevy_transform",
1028
+
"jni 0.20.0",
1029
+
"ndk-context",
1030
+
"openxr",
1031
+
"thiserror 2.0.17",
1032
+
"wgpu",
1033
+
"wgpu-hal",
1034
+
]
1035
+
1036
+
[[package]]
1037
+
name = "bevy_mod_xr"
1038
+
version = "0.4.0"
1039
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1040
+
checksum = "4107b79e3e3b38bc57a7c3fceb465300070b4bc3d2ebd839a9e04468b06cc11c"
1041
+
dependencies = [
1042
+
"bevy_app",
1043
+
"bevy_camera",
1044
+
"bevy_color",
1045
+
"bevy_derive",
1046
+
"bevy_ecs",
1047
+
"bevy_gizmos",
1048
+
"bevy_log",
1049
+
"bevy_math",
1050
+
"bevy_render",
1051
+
"bevy_transform",
1052
+
]
1053
+
1054
+
[[package]]
1055
name = "bevy_pbr"
1056
version = "0.17.3"
1057
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1600
]
1601
1602
[[package]]
1603
+
name = "bevy_xr_utils"
1604
+
version = "0.4.0"
1605
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1606
+
checksum = "f82cd353262258aae6048ccad3544b8a978a301d9eb954d66efef6dccc91dfa9"
1607
+
dependencies = [
1608
+
"bevy_app",
1609
+
"bevy_color",
1610
+
"bevy_derive",
1611
+
"bevy_ecs",
1612
+
"bevy_gizmos",
1613
+
"bevy_log",
1614
+
"bevy_math",
1615
+
"bevy_mod_openxr",
1616
+
"bevy_mod_xr",
1617
+
"bevy_transform",
1618
+
"openxr",
1619
+
"openxr_mndx_xdev_space",
1620
+
]
1621
+
1622
+
[[package]]
1623
name = "bindgen"
1624
version = "0.72.1"
1625
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1638
]
1639
1640
[[package]]
1641
+
name = "binrw"
1642
+
version = "0.15.0"
1643
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1644
+
checksum = "81419ff39e6ed10a92a7f125290859776ced35d9a08a665ae40b23e7ca702f30"
1645
+
dependencies = [
1646
+
"array-init",
1647
+
"binrw_derive",
1648
+
"bytemuck",
1649
+
]
1650
+
1651
+
[[package]]
1652
+
name = "binrw_derive"
1653
+
version = "0.15.0"
1654
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1655
+
checksum = "376404e55ec40d0d6f8b4b7df3f87b87954bd987f0cf9a7207ea3b6ea5c9add4"
1656
+
dependencies = [
1657
+
"either",
1658
+
"owo-colors",
1659
+
"proc-macro2",
1660
+
"quote",
1661
+
"syn",
1662
+
]
1663
+
1664
+
[[package]]
1665
name = "bit-set"
1666
version = "0.8.0"
1667
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1740
"futures-io",
1741
"futures-lite",
1742
"piper",
1743
+
]
1744
+
1745
+
[[package]]
1746
+
name = "brotli"
1747
+
version = "3.5.0"
1748
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1749
+
checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
1750
+
dependencies = [
1751
+
"alloc-no-stdlib",
1752
+
"alloc-stdlib",
1753
+
"brotli-decompressor",
1754
+
]
1755
+
1756
+
[[package]]
1757
+
name = "brotli-decompressor"
1758
+
version = "2.5.1"
1759
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1760
+
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
1761
+
dependencies = [
1762
+
"alloc-no-stdlib",
1763
+
"alloc-stdlib",
1764
]
1765
1766
[[package]]
···
2106
"core-foundation-sys",
2107
"coreaudio-rs 0.11.3",
2108
"dasp_sample",
2109
+
"jni 0.21.1",
2110
"js-sys",
2111
"libc",
2112
"mach2",
···
2128
"alsa",
2129
"coreaudio-rs 0.13.0",
2130
"dasp_sample",
2131
+
"jni 0.21.1",
2132
"js-sys",
2133
"libc",
2134
"mach2",
···
2146
]
2147
2148
[[package]]
2149
+
name = "crc"
2150
+
version = "3.4.0"
2151
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2152
+
checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d"
2153
+
dependencies = [
2154
+
"crc-catalog",
2155
+
]
2156
+
2157
+
[[package]]
2158
+
name = "crc-catalog"
2159
+
version = "2.4.0"
2160
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2161
+
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
2162
+
2163
+
[[package]]
2164
name = "crc32fast"
2165
version = "1.5.0"
2166
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2449
]
2450
2451
[[package]]
2452
+
name = "felix-assets"
2453
+
version = "0.1.0"
2454
+
dependencies = [
2455
+
"anyhow",
2456
+
"bevy",
2457
+
"unity-asset",
2458
+
"unity-asset-binary",
2459
+
"unity-asset-decode",
2460
+
]
2461
+
2462
+
[[package]]
2463
name = "felix-audio"
2464
version = "0.1.0"
2465
dependencies = [
···
2478
dependencies = [
2479
"anyhow",
2480
"bevy",
2481
+
"bevy_mod_openxr",
2482
+
"bevy_mod_xr",
2483
+
"bevy_xr_utils",
2484
"cpal 0.16.0",
2485
"dotenvy",
2486
+
"felix-assets",
2487
"felix-audio",
2488
"felix-net",
2489
+
"openxr",
2490
"tokio",
2491
]
2492
···
3043
3044
[[package]]
3045
name = "jni"
3046
+
version = "0.20.0"
3047
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3048
+
checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c"
3049
+
dependencies = [
3050
+
"cesu8",
3051
+
"combine",
3052
+
"jni-sys",
3053
+
"log",
3054
+
"thiserror 1.0.69",
3055
+
"walkdir",
3056
+
]
3057
+
3058
+
[[package]]
3059
+
name = "jni"
3060
version = "0.21.1"
3061
source = "registry+https://github.com/rust-lang/crates.io-index"
3062
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
···
3244
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
3245
3246
[[package]]
3247
+
name = "lz4_flex"
3248
+
version = "0.12.0"
3249
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3250
+
checksum = "ab6473172471198271ff72e9379150e9dfd70d8e533e0752a27e515b48dd375e"
3251
+
dependencies = [
3252
+
"twox-hash",
3253
+
]
3254
+
3255
+
[[package]]
3256
+
name = "lzma-rs"
3257
+
version = "0.3.0"
3258
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3259
+
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
3260
+
dependencies = [
3261
+
"byteorder",
3262
+
"crc",
3263
+
]
3264
+
3265
+
[[package]]
3266
name = "mach2"
3267
version = "0.4.3"
3268
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3536
]
3537
3538
[[package]]
3539
+
name = "num_cpus"
3540
+
version = "1.17.0"
3541
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3542
+
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
3543
+
dependencies = [
3544
+
"hermit-abi",
3545
+
"libc",
3546
+
]
3547
+
3548
+
[[package]]
3549
name = "num_enum"
3550
version = "0.7.5"
3551
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3861
source = "registry+https://github.com/rust-lang/crates.io-index"
3862
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
3863
dependencies = [
3864
+
"jni 0.21.1",
3865
"ndk 0.8.0",
3866
"ndk-context",
3867
"num-derive",
···
3904
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
3905
3906
[[package]]
3907
+
name = "openxr"
3908
+
version = "0.19.0"
3909
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3910
+
checksum = "2a2d6934d2508f94fd4cbda6c2a326f111f60ce59fd9136df6d478564397dd40"
3911
+
dependencies = [
3912
+
"libc",
3913
+
"libloading",
3914
+
"ndk-context",
3915
+
"openxr-sys",
3916
+
]
3917
+
3918
+
[[package]]
3919
+
name = "openxr-sys"
3920
+
version = "0.11.0"
3921
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3922
+
checksum = "f10e7e38c47f2175fc39363713b656db899fa0b4a14341029702cbdfa6f44d05"
3923
+
dependencies = [
3924
+
"cmake",
3925
+
"libc",
3926
+
"mint",
3927
+
]
3928
+
3929
+
[[package]]
3930
+
name = "openxr_mndx_xdev_space"
3931
+
version = "0.1.1"
3932
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3933
+
checksum = "fc03c3948dceb287224eaa9079a5d4f690e91b43a2385da6c686edf0f850408a"
3934
+
dependencies = [
3935
+
"openxr",
3936
+
]
3937
+
3938
+
[[package]]
3939
name = "opus"
3940
version = "0.3.0"
3941
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3971
dependencies = [
3972
"ttf-parser 0.25.1",
3973
]
3974
+
3975
+
[[package]]
3976
+
name = "owo-colors"
3977
+
version = "4.2.3"
3978
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3979
+
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
3980
3981
[[package]]
3982
name = "parking"
···
4558
]
4559
4560
[[package]]
4561
+
name = "serde_bytes"
4562
+
version = "0.11.19"
4563
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4564
+
checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
4565
+
dependencies = [
4566
+
"serde",
4567
+
"serde_core",
4568
+
]
4569
+
4570
+
[[package]]
4571
name = "serde_core"
4572
version = "1.0.228"
4573
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4598
"ryu",
4599
"serde",
4600
"serde_core",
4601
+
]
4602
+
4603
+
[[package]]
4604
+
name = "serde_yaml"
4605
+
version = "0.9.34+deprecated"
4606
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4607
+
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
4608
+
dependencies = [
4609
+
"indexmap",
4610
+
"itoa",
4611
+
"ryu",
4612
+
"serde",
4613
+
"unsafe-libyaml",
4614
]
4615
4616
[[package]]
···
5293
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
5294
5295
[[package]]
5296
+
name = "unity-asset"
5297
+
version = "0.2.0"
5298
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5299
+
checksum = "6705b95fda449527055ff77fe5cff49f774dde7335ed92bc3d048fc74066ebaf"
5300
+
dependencies = [
5301
+
"unity-asset-binary",
5302
+
"unity-asset-core",
5303
+
"unity-asset-yaml",
5304
+
]
5305
+
5306
+
[[package]]
5307
+
name = "unity-asset-binary"
5308
+
version = "0.2.0"
5309
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5310
+
checksum = "d739d1414c1732be1035417f83b1e60f234c7d5eb8abda0ee70d178a58137cb7"
5311
+
dependencies = [
5312
+
"binrw",
5313
+
"brotli",
5314
+
"byteorder",
5315
+
"flate2",
5316
+
"indexmap",
5317
+
"lz4_flex",
5318
+
"lzma-rs",
5319
+
"memmap2",
5320
+
"num_cpus",
5321
+
"once_cell",
5322
+
"regex",
5323
+
"serde",
5324
+
"serde_json",
5325
+
"thiserror 2.0.17",
5326
+
"unity-asset-core",
5327
+
]
5328
+
5329
+
[[package]]
5330
+
name = "unity-asset-core"
5331
+
version = "0.2.0"
5332
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5333
+
checksum = "12903fd47e122b5e7e335fc9cb5540bb35ab0ffe5bb57a7741a8c7be8d361361"
5334
+
dependencies = [
5335
+
"indexmap",
5336
+
"lazy_static",
5337
+
"serde",
5338
+
"serde_bytes",
5339
+
"thiserror 2.0.17",
5340
+
]
5341
+
5342
+
[[package]]
5343
+
name = "unity-asset-decode"
5344
+
version = "0.2.0"
5345
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5346
+
checksum = "9ea6e630cdefde54a88ca4fbae54cf3d3e5ba527fac96b085562da3b3834b77b"
5347
+
dependencies = [
5348
+
"indexmap",
5349
+
"serde",
5350
+
"unity-asset-binary",
5351
+
"unity-asset-core",
5352
+
]
5353
+
5354
+
[[package]]
5355
+
name = "unity-asset-yaml"
5356
+
version = "0.2.0"
5357
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5358
+
checksum = "b991e340c27b1578e657defee9f57de867d853b8f40448fb079d0ee3a5ebc77e"
5359
+
dependencies = [
5360
+
"indexmap",
5361
+
"serde",
5362
+
"serde_yaml",
5363
+
"thiserror 2.0.17",
5364
+
"unity-asset-core",
5365
+
]
5366
+
5367
+
[[package]]
5368
+
name = "unsafe-libyaml"
5369
+
version = "0.2.11"
5370
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5371
+
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
5372
+
5373
+
[[package]]
5374
name = "uuid"
5375
version = "1.19.0"
5376
source = "registry+https://github.com/rust-lang/crates.io-index"
···
5637
"js-sys",
5638
"log",
5639
"naga",
5640
+
"parking_lot",
5641
"portable-atomic",
5642
"profiling",
5643
"raw-window-handle",
5644
"smallvec",
5645
"static_assertions",
5646
"wasm-bindgen",
5647
+
"wasm-bindgen-futures",
5648
"web-sys",
5649
"wgpu-core",
5650
"wgpu-hal",
···
5676
"smallvec",
5677
"thiserror 2.0.17",
5678
"wgpu-core-deps-apple",
5679
+
"wgpu-core-deps-emscripten",
5680
"wgpu-core-deps-wasm",
5681
"wgpu-core-deps-windows-linux-android",
5682
"wgpu-hal",
···
5688
version = "26.0.0"
5689
source = "registry+https://github.com/rust-lang/crates.io-index"
5690
checksum = "18ae5fbde6a4cbebae38358aa73fcd6e0f15c6144b67ef5dc91ded0db125dbdf"
5691
+
dependencies = [
5692
+
"wgpu-hal",
5693
+
]
5694
+
5695
+
[[package]]
5696
+
name = "wgpu-core-deps-emscripten"
5697
+
version = "26.0.0"
5698
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5699
+
checksum = "d7670e390f416006f746b4600fdd9136455e3627f5bd763abf9a65daa216dd2d"
5700
dependencies = [
5701
"wgpu-hal",
5702
]
+4
-1
Cargo.toml
+4
-1
Cargo.toml
+11
assets/Cargo.toml
+11
assets/Cargo.toml
+3
assets/examples/test.rs
+3
assets/examples/test.rs
+62
assets/src/buffer.rs
+62
assets/src/buffer.rs
···
···
1
+
use std::io::Read;
2
+
3
+
use bevy::math::{Quat, Vec3};
4
+
5
+
pub struct StreamedBuffer{
6
+
stream: Box<dyn Read>
7
+
}
8
+
9
+
impl StreamedBuffer{
10
+
pub fn new( stream: impl Read + 'static ) -> Self{
11
+
Self {
12
+
stream: Box::new(stream)
13
+
}
14
+
}
15
+
16
+
pub fn get_u8(&mut self) -> u8{
17
+
let mut b = [0u8; 1];
18
+
self.stream.read(&mut b).unwrap();
19
+
20
+
b[0]
21
+
}
22
+
23
+
pub fn get_u8s(&mut self, count: usize) -> Vec<u8>{
24
+
let mut b = vec![0u8; count];
25
+
self.stream.read(&mut b).unwrap();
26
+
27
+
b
28
+
}
29
+
30
+
pub fn get_i32(&mut self) -> i32{
31
+
let b = self.get_u8s(4);
32
+
i32::from_le_bytes([ b[0], b[1], b[2], b[3] ])
33
+
}
34
+
35
+
pub fn get_u32(&mut self) -> u32{
36
+
let b = self.get_u8s(4);
37
+
u32::from_le_bytes([ b[0], b[1], b[2], b[3] ])
38
+
}
39
+
40
+
pub fn get_str(&mut self) -> String{
41
+
let length = self.get_u32();
42
+
let b = self.get_u8s(length as usize);
43
+
44
+
let string = str::from_utf8(&b).unwrap();
45
+
string.to_owned()
46
+
}
47
+
48
+
49
+
pub fn get_vec3(&mut self) -> Vec3{
50
+
Vec3 { x: self.get_f32(), y: self.get_f32(), z: self.get_f32() }
51
+
}
52
+
53
+
pub fn get_quat(&mut self) -> Quat{
54
+
Quat::from_xyzw(self.get_f32(), self.get_f32(), self.get_f32(), self.get_f32())
55
+
}
56
+
57
+
58
+
pub fn get_f32(&mut self) -> f32{
59
+
let b = self.get_u8s(4);
60
+
f32::from_le_bytes([ b[0], b[1], b[2], b[3] ])
61
+
}
62
+
}
+84
assets/src/felix/mod.rs
+84
assets/src/felix/mod.rs
···
···
1
+
use std::fs::File;
2
+
3
+
use bevy::{asset::RenderAssetUsages, mesh::{Indices, PrimitiveTopology}, prelude::*, transform::components::Transform};
4
+
5
+
use crate::{BevyObject, BevyObjectData, BevyObjectLightData, BevyObjectLightDataType, buffer::StreamedBuffer};
6
+
7
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<BevyObject>>{
8
+
// TODO: Material loading
9
+
// TODO: UV Loading
10
+
// TODO: Flat normals
11
+
// TODO: Live updates directly from blender?
12
+
13
+
let mut objs = vec![];
14
+
15
+
let decoder = File::open(path).unwrap();
16
+
let mut buf = StreamedBuffer::new(decoder);
17
+
18
+
let obj_count = buf.get_u32();
19
+
20
+
for _ in 0..obj_count{
21
+
let name = buf.get_str();
22
+
let transform = Transform {
23
+
translation: buf.get_vec3(),
24
+
rotation: buf.get_quat(),
25
+
scale: buf.get_vec3()
26
+
};
27
+
28
+
match buf.get_u32(){
29
+
0 => { // 0 - Mesh
30
+
let mut vertices = vec![];
31
+
let mut normals = vec![];
32
+
let mut triangles = vec![];
33
+
34
+
let vertex_count = buf.get_u32();
35
+
for _ in 0..vertex_count{
36
+
vertices.push(buf.get_vec3());
37
+
normals.push(buf.get_vec3());
38
+
}
39
+
40
+
let triangle_count = buf.get_u32();
41
+
for _ in 0..triangle_count{
42
+
triangles.push(buf.get_u32());
43
+
triangles.push(buf.get_u32());
44
+
triangles.push(buf.get_u32());
45
+
}
46
+
47
+
objs.push(BevyObject {
48
+
name,
49
+
transform,
50
+
data: BevyObjectData::Mesh(Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
51
+
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
52
+
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
53
+
.with_inserted_indices(Indices::U32(triangles)))
54
+
});
55
+
}
56
+
57
+
1 => { // 1 - Light
58
+
let light_type = match buf.get_u32(){
59
+
0 => BevyObjectLightDataType::Point,
60
+
1 => BevyObjectLightDataType::Sun,
61
+
2 => BevyObjectLightDataType::Spot,
62
+
3 => BevyObjectLightDataType::Area,
63
+
_ => BevyObjectLightDataType::Unknown
64
+
};
65
+
66
+
let colour = buf.get_vec3();
67
+
68
+
objs.push(BevyObject {
69
+
name,
70
+
transform,
71
+
data: BevyObjectData::Light(BevyObjectLightData {
72
+
type_: light_type,
73
+
colour: Color::linear_rgb(colour.x, colour.y, colour.z),
74
+
power: buf.get_f32()
75
+
})
76
+
});
77
+
}
78
+
79
+
_ => {}
80
+
}
81
+
}
82
+
83
+
Ok(objs)
84
+
}
+38
assets/src/lib.rs
+38
assets/src/lib.rs
···
···
1
+
use bevy::{color::Color, mesh::Mesh, transform::components::Transform};
2
+
3
+
mod unity;
4
+
mod felix;
5
+
mod buffer;
6
+
7
+
#[derive(Debug)]
8
+
pub enum BevyObjectData{
9
+
Mesh(Mesh),
10
+
Light(BevyObjectLightData)
11
+
}
12
+
13
+
#[derive(Debug)]
14
+
pub struct BevyObject{
15
+
pub name: String,
16
+
pub transform: Transform,
17
+
pub data: BevyObjectData,
18
+
}
19
+
20
+
#[derive(Debug)]
21
+
pub struct BevyObjectLightData{
22
+
pub type_: BevyObjectLightDataType,
23
+
pub colour: Color,
24
+
pub power: f32
25
+
}
26
+
27
+
#[derive(Debug)]
28
+
pub enum BevyObjectLightDataType{
29
+
Point,
30
+
Sun,
31
+
Spot,
32
+
Area,
33
+
Unknown
34
+
}
35
+
36
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<BevyObject>>{
37
+
felix::load(path)
38
+
}
+22
assets/src/unity/component/mesh_renderer.rs
+22
assets/src/unity/component/mesh_renderer.rs
···
···
1
+
use unity_asset_binary::object::UnityObject;
2
+
3
+
use crate::unity::component::Component;
4
+
5
+
#[derive(Debug)]
6
+
pub struct MeshRenderer{
7
+
8
+
}
9
+
10
+
impl Component for MeshRenderer{
11
+
12
+
}
13
+
14
+
impl From<UnityObject> for MeshRenderer{
15
+
fn from(value: UnityObject) -> Self {
16
+
// dbg!(value.property_names());
17
+
18
+
Self {
19
+
20
+
}
21
+
}
22
+
}
+6
assets/src/unity/component/mod.rs
+6
assets/src/unity/component/mod.rs
+16
assets/src/unity/component/transform.rs
+16
assets/src/unity/component/transform.rs
···
···
1
+
use bevy::transform::components::Transform;
2
+
use unity_asset_binary::object::UnityObject;
3
+
4
+
use crate::unity::unity_value::{unity_value_to_quat, unity_value_to_vec3};
5
+
6
+
pub fn into_bevy_transform(value: UnityObject) -> Transform {
7
+
let position = value.get("m_LocalPosition").unwrap();
8
+
let rotation = value.get("m_LocalRotation").unwrap();
9
+
let scale = value.get("m_LocalScale").unwrap();
10
+
11
+
Transform {
12
+
translation: unity_value_to_vec3(position),
13
+
rotation: unity_value_to_quat(rotation),
14
+
scale: unity_value_to_vec3(scale)
15
+
}
16
+
}
+111
assets/src/unity/mod.rs
+111
assets/src/unity/mod.rs
···
···
1
+
// NOTE: Very WIP, Does not work!!
2
+
3
+
use anyhow::bail;
4
+
use bevy::{prelude::*, transform::components::Transform};
5
+
use unity_asset::environment::{Environment, EnvironmentObjectRef};
6
+
use unity_asset_binary::unity_version::UnityVersion;
7
+
use unity_asset_decode::mesh::MeshParser;
8
+
9
+
use crate::{BevyObject, BevyObjectData, unity::{component::{Component, mesh_renderer::MeshRenderer, transform::into_bevy_transform}, unity_value::try_unity_mesh_to_bevy}};
10
+
11
+
mod component;
12
+
mod unity_value;
13
+
14
+
#[derive(Debug)]
15
+
pub struct UnityGameObject{
16
+
pub name: String,
17
+
pub active: bool,
18
+
19
+
pub transform: Transform,
20
+
pub mesh_renderer: Option<MeshRenderer>,
21
+
pub mesh_filter: Option<Mesh>,
22
+
}
23
+
24
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<BevyObject>>{
25
+
let mesh_parser = MeshParser::new(UnityVersion::parse_version("2020.3.12f1").unwrap());
26
+
27
+
let mut env = Environment::new();
28
+
env.load(path)?;
29
+
30
+
let mut gameobjects = vec![];
31
+
32
+
for obj in env.objects(){
33
+
match obj{
34
+
EnvironmentObjectRef::Binary(v) => {
35
+
if v.object.class_id() == 1{
36
+
let obj = v.object.read()?;
37
+
let go = obj.as_gameobject().unwrap();
38
+
39
+
let mut components: Vec<Box<dyn Component>> = vec![];
40
+
41
+
let mut transform = None;
42
+
let mut mesh_renderer = None;
43
+
let mut mesh_filter = None;
44
+
45
+
let comps = obj.get("m_Component").unwrap().as_array().unwrap();
46
+
47
+
for comp in comps{
48
+
let obj = comp.as_object().unwrap().get("component").unwrap();
49
+
let path_id = obj.as_object().unwrap().get("m_PathID").unwrap().as_i64().unwrap();
50
+
51
+
let comp = env.find_binary_object(path_id).unwrap();
52
+
let comp = comp.read().unwrap();
53
+
54
+
match comp.class_id(){
55
+
4 => transform = Some(into_bevy_transform(comp)), // Normal Transform
56
+
224 => transform = Some(into_bevy_transform(comp)), // Rect Transform (gonna just treat it as normal)
57
+
58
+
23 => mesh_renderer = Some(MeshRenderer::from(comp)),
59
+
33 => {
60
+
let mesh = comp.get("m_Mesh").unwrap();
61
+
let path_id = mesh.as_object().unwrap().get("m_PathID").unwrap().as_i64().unwrap();
62
+
63
+
let mesh = env.find_binary_object(path_id).unwrap();
64
+
let mesh_obj = mesh.read().unwrap();
65
+
66
+
if let Some(mesh) = try_unity_mesh_to_bevy(mesh_obj, &mesh_parser){
67
+
mesh_filter = Some(mesh);
68
+
} else{
69
+
println!("[WARN] Failed to load mesh for: {}", go.name);
70
+
}
71
+
},
72
+
73
+
_ => {}
74
+
}
75
+
}
76
+
77
+
if transform.is_none(){ bail!("Cannot find transform for object {}", go.name); }
78
+
79
+
let gameobject = UnityGameObject {
80
+
name: go.name,
81
+
active: go.active,
82
+
83
+
transform: transform.unwrap(),
84
+
mesh_renderer,
85
+
mesh_filter
86
+
};
87
+
88
+
gameobjects.push(gameobject);
89
+
break;
90
+
}
91
+
},
92
+
_ => {}
93
+
}
94
+
}
95
+
96
+
let mut objs = vec![];
97
+
98
+
for go in gameobjects{
99
+
if go.active{
100
+
if let Some(mesh) = go.mesh_filter{
101
+
objs.push(BevyObject {
102
+
name: go.name,
103
+
transform: go.transform,
104
+
data: BevyObjectData::Mesh(mesh)
105
+
});
106
+
}
107
+
}
108
+
}
109
+
110
+
Ok(objs)
111
+
}
+467
assets/src/unity/unity_value.rs
+467
assets/src/unity/unity_value.rs
···
···
1
+
use std::{fs::File, io::Write, mem};
2
+
3
+
use bevy::{asset::RenderAssetUsages, math::{Quat, Vec3}, mesh::{Indices, PrimitiveTopology}, prelude::*};
4
+
use unity_asset::UnityValue;
5
+
use unity_asset_binary::object::UnityObject;
6
+
use unity_asset_decode::mesh::MeshParser;
7
+
8
+
pub fn unity_value_to_vec3( val: &UnityValue ) -> Vec3{
9
+
let obj = val.as_object().unwrap();
10
+
11
+
Vec3 {
12
+
x: obj.get("x").unwrap().as_f64().unwrap() as f32,
13
+
y: obj.get("y").unwrap().as_f64().unwrap() as f32,
14
+
z: obj.get("z").unwrap().as_f64().unwrap() as f32
15
+
}
16
+
}
17
+
18
+
pub fn unity_value_to_quat( val: &UnityValue ) -> Quat{
19
+
let obj = val.as_object().unwrap();
20
+
21
+
Quat::from_xyzw(
22
+
obj.get("x").unwrap().as_f64().unwrap() as f32,
23
+
obj.get("y").unwrap().as_f64().unwrap() as f32,
24
+
obj.get("z").unwrap().as_f64().unwrap() as f32,
25
+
obj.get("w").unwrap().as_f64().unwrap() as f32
26
+
)
27
+
}
28
+
29
+
fn get_channel_component_size( format: u8 ) -> usize{
30
+
match format{
31
+
0 => 4, // kVertexFormatFloat
32
+
1 => 2, // kVertexFormatFloat16
33
+
2 => 1, // kVertexFormatUNorm8
34
+
3 => 1, // kVertexFormatSNorm8
35
+
4 => 2, // kVertexFormatUNorm16
36
+
5 => 2, // kVertexFormatSNorm16
37
+
6 => 1, // kVertexFormatUInt8
38
+
7 => 1, // kVertexFormatSInt8
39
+
8 => 2, // kVertexFormatUInt16
40
+
9 => 2, // kVertexFormatSInt16
41
+
10 => 4, // kVertexFormatUInt32
42
+
11 => 4, // kVertexFormatSInt32
43
+
44
+
_ => 0
45
+
}
46
+
}
47
+
48
+
enum UnityDataTypeArray{
49
+
kVertexFormatFloat(Vec<Vec<f32>>),
50
+
kVertexFormatFloat16(Vec<Vec<f32>>),
51
+
kVertexFormatUNorm8(Vec<Vec<u8>>),
52
+
kVertexFormatSNorm8(Vec<Vec<i8>>),
53
+
kVertexFormatUNorm16(Vec<Vec<u16>>),
54
+
kVertexFormatSNorm16(Vec<Vec<i16>>),
55
+
kVertexFormatUInt8(Vec<Vec<u8>>),
56
+
kVertexFormatSInt8(Vec<Vec<i8>>),
57
+
kVertexFormatUInt16(Vec<Vec<u16>>),
58
+
kVertexFormatSInt16(Vec<Vec<i16>>),
59
+
kVertexFormatUInt32(Vec<Vec<u32>>),
60
+
kVertexFormatSInt32(Vec<Vec<i32>>),
61
+
Unknown
62
+
}
63
+
64
+
impl UnityDataTypeArray{
65
+
pub fn as_vec3_array( &self ) -> Vec<Vec3>{
66
+
if let Self::kVertexFormatFloat(array) = self{
67
+
let mut vecs = vec![];
68
+
69
+
for val in array{
70
+
vecs.push(Vec3 { x: val[0], y: val[1], z: val[2] });
71
+
}
72
+
73
+
vecs
74
+
} else{
75
+
panic!("Not a float array");
76
+
}
77
+
}
78
+
}
79
+
80
+
fn unpack_struct( dimension: usize, component_dtype: u8, bytes: Vec<u8> ) -> UnityDataTypeArray{
81
+
match component_dtype{
82
+
0 => {
83
+
let mut decoded: Vec<Vec<_>> = vec![];
84
+
let item_size = get_channel_component_size(component_dtype);
85
+
let vec_size = item_size * dimension;
86
+
87
+
for i in 0..( bytes.len() / vec_size ){
88
+
let indx = i * vec_size;
89
+
let mut vec = vec![0.0; dimension];
90
+
91
+
for j in 0..dimension{
92
+
vec[j] = f32::from_le_bytes([
93
+
bytes[indx + (j * item_size)],
94
+
bytes[indx + (j * item_size) + 1],
95
+
bytes[indx + (j * item_size) + 2],
96
+
bytes[indx + (j * item_size) + 3]
97
+
]);
98
+
}
99
+
decoded.push(vec);
100
+
}
101
+
102
+
UnityDataTypeArray::kVertexFormatFloat(decoded)
103
+
},
104
+
105
+
1 => {
106
+
let mut decoded: Vec<Vec<_>> = vec![];
107
+
let item_size = get_channel_component_size(component_dtype);
108
+
let vec_size = item_size * dimension;
109
+
110
+
for i in 0..( bytes.len() / vec_size ){
111
+
let indx = i * vec_size;
112
+
let mut vec = vec![0.0; dimension];
113
+
114
+
for j in 0..dimension{
115
+
vec[j] = f32::from_le_bytes([
116
+
bytes[indx + (j * item_size)],
117
+
bytes[indx + (j * item_size) + 1],
118
+
0, 0
119
+
]);
120
+
}
121
+
decoded.push(vec);
122
+
}
123
+
124
+
UnityDataTypeArray::kVertexFormatFloat16(decoded)
125
+
},
126
+
127
+
2 => {
128
+
let mut decoded: Vec<Vec<u8>> = vec![];
129
+
let item_size = get_channel_component_size(component_dtype);
130
+
let vec_size = item_size * dimension;
131
+
132
+
for i in 0..( bytes.len() / vec_size ){
133
+
let indx = i * vec_size;
134
+
let mut vec = vec![0; vec_size];
135
+
136
+
for j in 0..vec_size{ vec[j] = u8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
137
+
decoded.push(vec);
138
+
}
139
+
140
+
UnityDataTypeArray::kVertexFormatUNorm8(decoded)
141
+
},
142
+
143
+
3 => {
144
+
let mut decoded: Vec<Vec<_>> = vec![];
145
+
let item_size = get_channel_component_size(component_dtype);
146
+
let vec_size = item_size * dimension;
147
+
148
+
for i in 0..( bytes.len() / vec_size ){
149
+
let indx = i * vec_size;
150
+
let mut vec = vec![0; vec_size];
151
+
152
+
for j in 0..vec_size{ vec[j] = i8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
153
+
decoded.push(vec);
154
+
}
155
+
156
+
UnityDataTypeArray::kVertexFormatSNorm8(decoded)
157
+
},
158
+
159
+
4 => {
160
+
let mut decoded: Vec<Vec<_>> = vec![];
161
+
let item_size = get_channel_component_size(component_dtype);
162
+
let vec_size = item_size * dimension;
163
+
164
+
for i in 0..( bytes.len() / vec_size ){
165
+
let indx = i * vec_size;
166
+
let mut vec = vec![0; vec_size];
167
+
168
+
for j in 0..vec_size{
169
+
vec[j] = u16::from_le_bytes([
170
+
bytes[indx + (j * item_size)],
171
+
bytes[indx + (j * item_size) + 1]
172
+
]);
173
+
}
174
+
decoded.push(vec);
175
+
}
176
+
177
+
UnityDataTypeArray::kVertexFormatUNorm16(decoded)
178
+
},
179
+
180
+
5 => {
181
+
let mut decoded: Vec<Vec<_>> = vec![];
182
+
let item_size = get_channel_component_size(component_dtype);
183
+
let vec_size = item_size * dimension;
184
+
185
+
for i in 0..( bytes.len() / vec_size ){
186
+
let indx = i * vec_size;
187
+
let mut vec = vec![0; vec_size];
188
+
189
+
for j in 0..vec_size{
190
+
vec[j] = i16::from_le_bytes([
191
+
bytes[indx + (j * item_size)],
192
+
bytes[indx + (j * item_size) + 1]
193
+
]);
194
+
}
195
+
decoded.push(vec);
196
+
}
197
+
198
+
UnityDataTypeArray::kVertexFormatSNorm16(decoded)
199
+
},
200
+
201
+
6 => {
202
+
let mut decoded: Vec<Vec<u8>> = vec![];
203
+
let item_size = get_channel_component_size(component_dtype);
204
+
let vec_size = item_size * dimension;
205
+
206
+
for i in 0..( bytes.len() / vec_size ){
207
+
let indx = i * vec_size;
208
+
let mut vec = vec![0; vec_size];
209
+
210
+
for j in 0..vec_size{ vec[j] = u8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
211
+
decoded.push(vec);
212
+
}
213
+
214
+
UnityDataTypeArray::kVertexFormatUInt8(decoded)
215
+
},
216
+
217
+
7 => {
218
+
let mut decoded: Vec<Vec<_>> = vec![];
219
+
let item_size = get_channel_component_size(component_dtype);
220
+
let vec_size = item_size * dimension;
221
+
222
+
for i in 0..( bytes.len() / vec_size ){
223
+
let indx = i * vec_size;
224
+
let mut vec = vec![0; vec_size];
225
+
226
+
for j in 0..vec_size{ vec[j] = i8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
227
+
decoded.push(vec);
228
+
}
229
+
230
+
UnityDataTypeArray::kVertexFormatSInt8(decoded)
231
+
},
232
+
233
+
8 => {
234
+
let mut decoded: Vec<Vec<_>> = vec![];
235
+
let item_size = get_channel_component_size(component_dtype);
236
+
let vec_size = item_size * dimension;
237
+
238
+
for i in 0..( bytes.len() / vec_size ){
239
+
let indx = i * vec_size;
240
+
let mut vec = vec![0; vec_size];
241
+
242
+
for j in 0..vec_size{
243
+
vec[j] = u16::from_le_bytes([
244
+
bytes[indx + (j * item_size)],
245
+
bytes[indx + (j * item_size) + 1]
246
+
]);
247
+
}
248
+
decoded.push(vec);
249
+
}
250
+
251
+
UnityDataTypeArray::kVertexFormatUInt16(decoded)
252
+
},
253
+
254
+
9 => {
255
+
let mut decoded: Vec<Vec<_>> = vec![];
256
+
let item_size = get_channel_component_size(component_dtype);
257
+
let vec_size = item_size * dimension;
258
+
259
+
for i in 0..( bytes.len() / vec_size ){
260
+
let indx = i * vec_size;
261
+
let mut vec = vec![0; vec_size];
262
+
263
+
for j in 0..vec_size{
264
+
vec[j] = i16::from_le_bytes([
265
+
bytes[indx + (j * item_size)],
266
+
bytes[indx + (j * item_size) + 1]
267
+
]);
268
+
}
269
+
decoded.push(vec);
270
+
}
271
+
272
+
UnityDataTypeArray::kVertexFormatSInt16(decoded)
273
+
},
274
+
275
+
10 => {
276
+
let mut decoded: Vec<Vec<_>> = vec![];
277
+
let item_size = get_channel_component_size(component_dtype);
278
+
let vec_size = item_size * dimension;
279
+
280
+
for i in 0..( bytes.len() / vec_size ){
281
+
let indx = i * vec_size;
282
+
let mut vec = vec![0; vec_size];
283
+
284
+
for j in 0..vec_size{
285
+
vec[j] = u32::from_le_bytes([
286
+
bytes[indx + (j * item_size)],
287
+
bytes[indx + (j * item_size) + 1],
288
+
bytes[indx + (j * item_size) + 2],
289
+
bytes[indx + (j * item_size) + 3]
290
+
]);
291
+
}
292
+
decoded.push(vec);
293
+
}
294
+
295
+
UnityDataTypeArray::kVertexFormatUInt32(decoded)
296
+
},
297
+
298
+
11 => {
299
+
let mut decoded: Vec<Vec<_>> = vec![];
300
+
let item_size = get_channel_component_size(component_dtype);
301
+
let vec_size = item_size * dimension;
302
+
303
+
for i in 0..( bytes.len() / vec_size ){
304
+
let indx = i * vec_size;
305
+
let mut vec = vec![0; vec_size];
306
+
307
+
for j in 0..vec_size{
308
+
vec[j] = i32::from_le_bytes([
309
+
bytes[indx + (j * item_size)],
310
+
bytes[indx + (j * item_size) + 1],
311
+
bytes[indx + (j * item_size) + 2],
312
+
bytes[indx + (j * item_size) + 3]
313
+
]);
314
+
}
315
+
decoded.push(vec);
316
+
}
317
+
318
+
UnityDataTypeArray::kVertexFormatSInt32(decoded)
319
+
},
320
+
321
+
_ => { UnityDataTypeArray::Unknown }
322
+
}
323
+
}
324
+
325
+
struct StreamInfo{
326
+
channel_mask: usize,
327
+
offset: usize,
328
+
stride: usize
329
+
}
330
+
331
+
pub fn try_unity_mesh_to_bevy( mesh_obj: UnityObject, mesh_parser: &MeshParser ) -> Option<Mesh>{
332
+
let mut vertices = None;
333
+
let mut normals = None;
334
+
let mut tangents = None;
335
+
let mut uv0 = None;
336
+
337
+
let mesh = mesh_parser.parse_from_unity_object(&mesh_obj).unwrap().mesh;
338
+
let vertex_data = mesh.vertex_data;
339
+
340
+
dbg!(&vertex_data.channels);
341
+
342
+
let mut streams = vec![];
343
+
let stream_count = 1 + vertex_data.channels.iter().map(|x| x.stream).max()? as usize;
344
+
345
+
let mut offset = 0;
346
+
347
+
for s in 0..stream_count{
348
+
let mut chn_mask = 0;
349
+
let mut stride = 0;
350
+
351
+
let mut i = 0;
352
+
for channel in &vertex_data.channels{
353
+
if channel.stream == s as u8 && channel.dimension > 0{
354
+
chn_mask |= 1 << i;
355
+
356
+
let component_size = get_channel_component_size(channel.format);
357
+
stride += channel.dimension as usize * component_size;
358
+
}
359
+
360
+
i += 1;
361
+
}
362
+
363
+
streams.push(StreamInfo {
364
+
channel_mask: chn_mask,
365
+
offset,
366
+
stride
367
+
});
368
+
369
+
offset += vertex_data.vertex_count as usize * stride;
370
+
offset = ( offset + ( 16 - 1 ) ) & !(16 - 1);
371
+
}
372
+
373
+
let mut i = 0;
374
+
for channel in vertex_data.channels{
375
+
let stream = &streams[channel.stream as usize];
376
+
377
+
if stream.channel_mask >> i & 1 == 1{
378
+
let component_byte_size = get_channel_component_size(channel.format);
379
+
dbg!(&component_byte_size, &channel.format);
380
+
let channel_dimension = channel.dimension as usize;
381
+
382
+
let mut bytes =
383
+
vec![0; vertex_data.vertex_count as usize * channel_dimension * component_byte_size];
384
+
385
+
for v in 0..vertex_data.vertex_count{
386
+
let vertex_offset = stream.offset + channel.offset as usize + stream.stride * v as usize;
387
+
388
+
for d in 0..channel_dimension{
389
+
let component_offset = vertex_offset + component_byte_size * d as usize;
390
+
let dst_offset = component_byte_size * (v as usize * channel.dimension as usize + d as usize);
391
+
392
+
let slice = &vertex_data.data_size[component_offset..component_offset + component_byte_size];
393
+
bytes[dst_offset..dst_offset + component_byte_size].clone_from_slice(slice);
394
+
}
395
+
}
396
+
397
+
let component_data = unpack_struct(channel_dimension, channel.format, bytes);
398
+
399
+
match i{
400
+
0 => vertices = Some(component_data),
401
+
1 => normals = Some(component_data),
402
+
2 => tangents = Some(component_data),
403
+
4 => uv0 = Some(component_data),
404
+
405
+
_ => {}
406
+
}
407
+
}
408
+
409
+
i += 1;
410
+
}
411
+
412
+
let mut triangles = vec![];
413
+
if mesh.index_buffer.len() > 0{
414
+
for submesh in mesh.sub_meshes{
415
+
let first_index = submesh.first_byte / 2;
416
+
417
+
match submesh.topology{
418
+
0 => {
419
+
// for i in (0..submesh.index_count).step_by(3){
420
+
// triangles.push(mesh.index_buffer[(first_index + i) as usize] as u16);
421
+
// triangles.push(mesh.index_buffer[(first_index + i + 1) as usize] as u16);
422
+
// triangles.push(mesh.index_buffer[(first_index + i + 2) as usize] as u16);
423
+
// }
424
+
425
+
for i in (0..submesh.index_count).step_by(6){
426
+
triangles.push(u16::from_le_bytes([
427
+
mesh.index_buffer[(first_index + i) as usize],
428
+
mesh.index_buffer[(first_index + i + 1) as usize]
429
+
]));
430
+
431
+
triangles.push(u16::from_le_bytes([
432
+
mesh.index_buffer[(first_index + i + 2) as usize],
433
+
mesh.index_buffer[(first_index + i + 3) as usize]
434
+
]));
435
+
436
+
triangles.push(u16::from_le_bytes([
437
+
mesh.index_buffer[(first_index + i + 4) as usize],
438
+
mesh.index_buffer[(first_index + i + 5) as usize]
439
+
]));
440
+
}
441
+
},
442
+
// TODO: Implement other topologys
443
+
_ => {}
444
+
}
445
+
}
446
+
} else{
447
+
return None;
448
+
}
449
+
450
+
if vertices.is_none(){ panic!("Cannot parse vertices") }
451
+
let vertices = vertices.unwrap().as_vec3_array();
452
+
453
+
let mut file = File::create("test.obj").unwrap();
454
+
455
+
for vec in &vertices{
456
+
writeln!(file, "v {} {} {}", vec.x, vec.y, vec.z).unwrap();
457
+
}
458
+
459
+
for i in 0..(triangles.len() / 3){
460
+
let indx = i * 3;
461
+
writeln!(file, "f {} {} {}", triangles[indx] + 1, triangles[indx + 1] + 1, triangles[indx + 2] + 1).unwrap();
462
+
}
463
+
464
+
Some(Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
465
+
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
466
+
.with_inserted_indices(Indices::U16(triangles)))
467
+
}
+6
-13
audio/src/lib.rs
+6
-13
audio/src/lib.rs
···
1
use bevy::{app::{App, Plugin, Startup, Update}, ecs::{component::Component, system::{Commands, Query}}, math::{Quat, Vec3}, transform::components::Transform};
2
-
use cpal::{BufferSize, SampleRate, StreamConfig};
3
-
use kira::{AudioManager, AudioManagerSettings, DefaultBackend, Tween, backend::cpal::CpalBackendSettings, listener::ListenerHandle};
4
5
use crate::source::FelixAudioSource;
6
···
12
pub mod source;
13
pub mod utils;
14
pub mod voice;
15
16
fn update_audio_system(
17
mut audio_system: Query<&mut FelixAudioComponent>,
···
47
impl Plugin for FelixAudio{
48
fn build(&self, app: &mut App) {
49
app.add_systems(Startup, move | mut commands: Commands | {
50
-
let mut settings = AudioManagerSettings::default();
51
-
settings.backend_settings = CpalBackendSettings {
52
-
config: Some(StreamConfig {
53
-
channels: 2,
54
-
sample_rate: SampleRate(48_000),
55
-
buffer_size: BufferSize::Fixed(512)
56
-
}),
57
-
..Default::default()
58
-
};
59
-
60
-
let mut manager = AudioManager::<DefaultBackend>::new(settings).unwrap();
61
let main_listener = manager.add_listener(Vec3::default(), Quat::default()).unwrap();
62
63
let handle = FelixAudioComponent { manager, main_listener };
···
1
use bevy::{app::{App, Plugin, Startup, Update}, ecs::{component::Component, system::{Commands, Query}}, math::{Quat, Vec3}, transform::components::Transform};
2
+
use kira::{AudioManager, AudioManagerSettings, DefaultBackend, Tween, listener::ListenerHandle};
3
4
use crate::source::FelixAudioSource;
5
···
11
pub mod source;
12
pub mod utils;
13
pub mod voice;
14
+
15
+
// TODO: Make this use HRTF at some point
16
+
// Maybe revisit steam audio?
17
+
// Or just find some other library that does HRTFs.
18
19
fn update_audio_system(
20
mut audio_system: Query<&mut FelixAudioComponent>,
···
50
impl Plugin for FelixAudio{
51
fn build(&self, app: &mut App) {
52
app.add_systems(Startup, move | mut commands: Commands | {
53
+
let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default()).unwrap();
54
let main_listener = manager.add_listener(Vec3::default(), Quat::default()).unwrap();
55
56
let handle = FelixAudioComponent { manager, main_listener };
+1
-6
audio/src/source/static_source.rs
+1
-6
audio/src/source/static_source.rs
···
1
use std::{sync::{Arc, Mutex}, thread};
2
3
use bevy::transform::components::Transform;
4
-
use kira::{Decibels, Easing, Mapping, Mix, Tween, Value, effect::{filter::FilterBuilder, reverb::ReverbBuilder}, sound::static_sound::StaticSoundData, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
5
6
use crate::{FelixAudioComponent, source::AudioSource};
7
···
52
.with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
53
input_range: ( 0.0, 20.0 ),
54
output_range: ( 18000.0, 2000.0 ),
55
-
easing: Easing::Linear
56
-
})))
57
-
.with_effect(ReverbBuilder::new().mix(Value::FromListenerDistance(Mapping {
58
-
input_range: ( 0.0, 100.0 ),
59
-
output_range: ( Mix::DRY, Mix::WET ),
60
easing: Easing::Linear
61
})))
62
.with_send(&send_track, Value::FromListenerDistance(Mapping {
···
1
use std::{sync::{Arc, Mutex}, thread};
2
3
use bevy::transform::components::Transform;
4
+
use kira::{Decibels, Easing, Mapping, Tween, Value, effect::{filter::FilterBuilder}, sound::static_sound::StaticSoundData, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
5
6
use crate::{FelixAudioComponent, source::AudioSource};
7
···
52
.with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
53
input_range: ( 0.0, 20.0 ),
54
output_range: ( 18000.0, 2000.0 ),
55
easing: Easing::Linear
56
})))
57
.with_send(&send_track, Value::FromListenerDistance(Mapping {
+1
-6
audio/src/source/stream_source.rs
+1
-6
audio/src/source/stream_source.rs
···
1
use bevy::transform::components::Transform;
2
-
use kira::{Decibels, Easing, Mapping, Mix, Tween, Value, effect::{filter::FilterBuilder, reverb::ReverbBuilder}, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
3
4
use crate::{FelixAudioComponent, source::{AudioSource, stream_source::sound_data::StreamAudioSourceSoundData}};
5
···
44
.with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
45
input_range: ( 0.0, 20.0 ),
46
output_range: ( 18000.0, 2000.0 ),
47
-
easing: Easing::Linear
48
-
})))
49
-
.with_effect(ReverbBuilder::new().mix(Value::FromListenerDistance(Mapping {
50
-
input_range: ( 0.0, 100.0 ),
51
-
output_range: ( Mix::DRY, Mix::WET ),
52
easing: Easing::Linear
53
})))
54
.with_send(&send_track, Value::FromListenerDistance(Mapping {
···
1
use bevy::transform::components::Transform;
2
+
use kira::{Decibels, Easing, Mapping, Tween, Value, effect::{filter::FilterBuilder}, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
3
4
use crate::{FelixAudioComponent, source::{AudioSource, stream_source::sound_data::StreamAudioSourceSoundData}};
5
···
44
.with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
45
input_range: ( 0.0, 20.0 ),
46
output_range: ( 18000.0, 2000.0 ),
47
easing: Easing::Linear
48
})))
49
.with_send(&send_track, Value::FromListenerDistance(Mapping {
+18
-3
audio/src/voice/decoder.rs
+18
-3
audio/src/voice/decoder.rs
···
1
-
use std::{collections::VecDeque, sync::{Arc, Mutex, mpsc::{Sender, channel}}, thread};
2
3
use opus::{Channels, Decoder};
4
5
use crate::{MONO_20MS, SAMPLE_RATE};
6
7
pub struct VoiceChatDecoder{
8
-
stream_in: Sender<Vec<u8>>
9
}
10
11
impl VoiceChatDecoder{
···
13
let mut decoder = Decoder::new(SAMPLE_RATE as u32, Channels::Mono).unwrap();
14
let ( stream_in, stream_out ) = channel();
15
16
thread::spawn(move || {
17
let mut buffer = [0.0; MONO_20MS];
18
···
20
let packet: Vec<u8> = stream_out.recv().unwrap();
21
decoder.decode_float(&packet, &mut buffer, false).unwrap();
22
23
let mut voice = queue.lock().unwrap();
24
for sample in buffer{ voice.push_back(sample); }
25
}
26
});
27
28
-
Self { stream_in }
29
}
30
31
pub fn decode( &self, packet: Vec<u8> ){
32
self.stream_in.send(packet).unwrap();
33
}
34
}
···
1
+
use std::{collections::VecDeque, sync::{Arc, Mutex, RwLock, mpsc::{Sender, channel}}, thread};
2
3
use opus::{Channels, Decoder};
4
5
use crate::{MONO_20MS, SAMPLE_RATE};
6
7
pub struct VoiceChatDecoder{
8
+
stream_in: Sender<Vec<u8>>,
9
+
last_rms: Arc<RwLock<f32>>
10
}
11
12
impl VoiceChatDecoder{
···
14
let mut decoder = Decoder::new(SAMPLE_RATE as u32, Channels::Mono).unwrap();
15
let ( stream_in, stream_out ) = channel();
16
17
+
let set_rms = Arc::new(RwLock::new(0.0));
18
+
let set_rms_1 = set_rms.clone();
19
+
20
thread::spawn(move || {
21
let mut buffer = [0.0; MONO_20MS];
22
···
24
let packet: Vec<u8> = stream_out.recv().unwrap();
25
decoder.decode_float(&packet, &mut buffer, false).unwrap();
26
27
+
let mut total = 0.0;
28
+
for sample in buffer{ total += sample.powi(2) }
29
+
*set_rms.write().unwrap() = 20.0 * ( total / buffer.len() as f32 ).sqrt().log10();
30
+
31
let mut voice = queue.lock().unwrap();
32
for sample in buffer{ voice.push_back(sample); }
33
}
34
});
35
36
+
Self {
37
+
stream_in,
38
+
last_rms: set_rms_1
39
+
}
40
}
41
42
pub fn decode( &self, packet: Vec<u8> ){
43
self.stream_in.send(packet).unwrap();
44
+
}
45
+
46
+
pub fn get_last_rms( &self ) -> f32{
47
+
*self.last_rms.read().unwrap()
48
}
49
}
+63
-18
audio/src/voice/microphone.rs
+63
-18
audio/src/voice/microphone.rs
···
1
-
use std::{env, net::{ToSocketAddrs, UdpSocket}, sync::{Arc, Mutex}};
2
3
use bevy::ecs::component::Component;
4
use cpal::{BufferSize, SampleRate, Stream, StreamConfig, traits::{DeviceTrait, HostTrait, StreamTrait}};
···
10
#[derive(Component)]
11
pub struct VoiceChatMicrophone{
12
stream: Option<Stream>,
13
-
udp: Option<UdpSocket>,
14
-
muted: Arc<Mutex<bool>>
15
}
16
17
impl VoiceChatMicrophone{
18
-
pub fn new( socket: UdpSocket ) -> Self{
19
Self {
20
stream: None,
21
-
udp: Some(socket),
22
-
muted: Arc::new(Mutex::new(false))
23
}
24
}
25
···
33
let mut encoder = Encoder::new(SAMPLE_RATE as u32, Channels::Mono, Application::Voip)?;
34
35
let host = cpal::default_host();
36
-
let mic = host.default_input_device().unwrap();
37
38
let mut output = [0; 512];
39
···
41
let mut buffer = [0; MONO_20MS];
42
43
let muted = self.muted.clone();
44
-
let udp = self.udp.take().unwrap();
45
46
-
let addr = env::var("HOST")?.to_socket_addrs()?.nth(0).unwrap();
47
48
let stream = mic.build_input_stream(
49
&StreamConfig {
50
-
channels: 1,
51
buffer_size: BufferSize::Fixed(BUFFER_SIZE as u32),
52
sample_rate: SampleRate(SAMPLE_RATE as u32)
53
},
···
58
buffer_indx = 0;
59
} else{
60
for i in 0..data.len(){
61
buffer[buffer_indx] = data[i];
62
buffer_indx += 1;
63
64
if buffer_indx >= MONO_20MS{
65
buffer_indx = 0;
66
67
-
let len = encoder.encode(&buffer, &mut output).unwrap();
68
-
let buf_to_send = output[0..len].to_vec();
69
70
-
let packet = PlayerVoicePacket {
71
-
id: "".into(), // NOTE: I know this kinda seems stupid but it's easier for me to get the player id on the server so imma just make the server fill this in.
72
-
packet: buf_to_send
73
-
};
74
75
-
let packet: Vec<u8> = packet.to_buf().into();
76
-
udp.send_to(&packet, addr).unwrap();
77
}
78
}
79
}
···
86
self.stream = Some(stream);
87
88
Ok(())
89
}
90
}
···
1
+
use std::{env, net::{SocketAddr, UdpSocket}, sync::{Arc, Mutex, RwLock}};
2
3
use bevy::ecs::component::Component;
4
use cpal::{BufferSize, SampleRate, Stream, StreamConfig, traits::{DeviceTrait, HostTrait, StreamTrait}};
···
10
#[derive(Component)]
11
pub struct VoiceChatMicrophone{
12
stream: Option<Stream>,
13
+
addr: SocketAddr,
14
+
udp: UdpSocket,
15
+
muted: Arc<Mutex<bool>>,
16
+
last_rms: Arc<RwLock<f32>>,
17
+
gate_level: Arc<RwLock<f32>>
18
}
19
20
impl VoiceChatMicrophone{
21
+
pub fn new( addr: SocketAddr, socket: UdpSocket ) -> Self{
22
Self {
23
stream: None,
24
+
addr,
25
+
udp: socket,
26
+
muted: Arc::new(Mutex::new(false)), // TODO: Default to muted
27
+
last_rms: Arc::new(RwLock::new(0.0)),
28
+
gate_level: Arc::new(RwLock::new(-65.0))
29
}
30
}
31
···
39
let mut encoder = Encoder::new(SAMPLE_RATE as u32, Channels::Mono, Application::Voip)?;
40
41
let host = cpal::default_host();
42
+
43
+
let mut i = 0;
44
+
let devices = host.input_devices().unwrap();
45
+
for device in devices{
46
+
println!("{}) {:?}", i, device.name());
47
+
i += 1;
48
+
}
49
+
50
+
let mut devices = host.input_devices().unwrap();
51
+
let mic = if let Ok(device_index) = env::var("MIC_INDEX"){
52
+
devices.nth(device_index.parse()?).unwrap()
53
+
} else{
54
+
host.default_input_device().unwrap()
55
+
};
56
+
57
+
println!("Using Device: {:?}", mic.name());
58
59
let mut output = [0; 512];
60
···
62
let mut buffer = [0; MONO_20MS];
63
64
let muted = self.muted.clone();
65
+
66
+
let udp = self.udp.try_clone().unwrap();
67
+
let addr = self.addr.clone();
68
+
69
+
for conf in mic.supported_input_configs().unwrap(){
70
+
println!("{} {:?} {} {:?}", conf.channels(), conf.buffer_size(), conf.sample_format(), conf.with_max_sample_rate());
71
+
}
72
73
+
let set_rms = self.last_rms.clone();
74
+
let gate_level = self.gate_level.clone();
75
76
let stream = mic.build_input_stream(
77
&StreamConfig {
78
+
channels: 2,
79
buffer_size: BufferSize::Fixed(BUFFER_SIZE as u32),
80
sample_rate: SampleRate(SAMPLE_RATE as u32)
81
},
···
86
buffer_indx = 0;
87
} else{
88
for i in 0..data.len(){
89
+
if i % 2 == 1{ continue; }
90
+
91
buffer[buffer_indx] = data[i];
92
buffer_indx += 1;
93
94
if buffer_indx >= MONO_20MS{
95
buffer_indx = 0;
96
97
+
let mut total = 0.0;
98
+
for sample in buffer{ total += (sample as f32).powi(2) }
99
100
+
let rms = 20.0 * ( ( total / buffer.len() as f32 ).sqrt() / i16::MAX as f32 ).log10();
101
+
*set_rms.write().unwrap() = rms;
102
103
+
if rms > *gate_level.read().unwrap(){
104
+
let len = encoder.encode(&buffer, &mut output).unwrap();
105
+
let buf_to_send = output[0..len].to_vec();
106
+
107
+
let packet = PlayerVoicePacket {
108
+
id: "".into(), // NOTE: I know this kinda seems stupid but it's easier for me to get the player id on the server so imma just make the server fill this in.
109
+
packet: buf_to_send
110
+
};
111
+
112
+
let packet: Vec<u8> = packet.to_buf().into();
113
+
udp.send_to(&packet, addr).unwrap();
114
+
}
115
}
116
}
117
}
···
124
self.stream = Some(stream);
125
126
Ok(())
127
+
}
128
+
129
+
pub fn get_rms_of_last_packet( &self ) -> ( f32, bool ){
130
+
let rms = *self.last_rms.read().unwrap();
131
+
let gate = *self.gate_level.read().unwrap();
132
+
133
+
( rms, rms > gate )
134
}
135
}
+3
-3
audio/src/voice/mod.rs
+3
-3
audio/src/voice/mod.rs
···
1
-
use std::net::UdpSocket;
2
3
use crate::voice::microphone::VoiceChatMicrophone;
4
5
pub mod decoder;
6
pub mod microphone;
7
8
-
pub fn init_microphone( socket: UdpSocket ) -> anyhow::Result<VoiceChatMicrophone>{
9
-
let mut handle = VoiceChatMicrophone::new(socket);
10
handle.start_stream()?;
11
12
Ok(handle)
···
1
+
use std::net::{SocketAddr, UdpSocket};
2
3
use crate::voice::microphone::VoiceChatMicrophone;
4
5
pub mod decoder;
6
pub mod microphone;
7
8
+
pub fn init_microphone( addr: SocketAddr, socket: UdpSocket ) -> anyhow::Result<VoiceChatMicrophone>{
9
+
let mut handle = VoiceChatMicrophone::new(addr, socket);
10
handle.start_stream()?;
11
12
Ok(handle)
+5
client/Cargo.toml
+5
client/Cargo.toml
···
10
dotenvy = "0.15.7"
11
felix-net = { path = '../net' }
12
felix-audio = { path = '../audio' }
13
+
felix-assets = { path = '../assets' }
14
tokio = { version = "1.48.0", features = ["full"] }
15
+
bevy_mod_openxr = "0.4.0"
16
+
openxr = "0.19.0"
17
+
bevy_mod_xr = "0.4.0"
18
+
bevy_xr_utils = "0.4.0"
+143
-28
client/src/components/debug_camera.rs
+143
-28
client/src/components/debug_camera.rs
···
1
use std::f32::consts::PI;
2
3
use bevy::{ input::mouse::MouseMotion, prelude::* };
4
5
#[derive(Component)]
6
pub struct DebugCamera{
···
17
}
18
}
19
20
pub fn update(
21
mut query: Query<(&mut DebugCamera, &mut Transform)>,
22
-
23
time: Res<Time>,
24
25
keys: Res<ButtonInput<KeyCode>>,
26
mouse_buttons: Res<ButtonInput<MouseButton>>,
27
mut mouse_motion: MessageReader<MouseMotion>,
28
){
29
-
let mut delta_time = time.delta_secs();
30
-
if keys.pressed(KeyCode::ShiftLeft){ delta_time *= 2.0; }
31
32
let ( mut debug, mut transform ) = query.single_mut().unwrap();
33
34
-
for ev in mouse_motion.read(){
35
-
if mouse_buttons.pressed(MouseButton::Right){
36
-
debug.pitch -= ev.delta.y * delta_time * 0.1;
37
-
debug.yaw -= ev.delta.x * delta_time * 0.1;
38
}
39
-
}
40
41
-
transform.rotation = Quat::from_euler(EulerRot::YXZ, debug.yaw, debug.pitch, 0.0);
42
43
-
if keys.pressed(KeyCode::KeyW){
44
-
let dir = transform.forward();
45
-
transform.translation += dir * delta_time;
46
-
} else if keys.pressed(KeyCode::KeyS){
47
-
let dir = -transform.forward();
48
-
transform.translation += dir * delta_time;
49
}
50
51
-
if keys.pressed(KeyCode::KeyA){
52
-
let dir = transform.left();
53
-
transform.translation += dir * delta_time;
54
-
} else if keys.pressed(KeyCode::KeyD){
55
-
let dir = -transform.left();
56
-
transform.translation += dir * delta_time;
57
}
58
59
-
if keys.pressed(KeyCode::KeyE){
60
-
let dir = transform.up();
61
-
transform.translation += dir * delta_time;
62
-
} else if keys.pressed(KeyCode::KeyQ){
63
-
let dir = -transform.up();
64
-
transform.translation += dir * delta_time;
65
-
}
66
}
···
1
use std::f32::consts::PI;
2
3
use bevy::{ input::mouse::MouseMotion, prelude::* };
4
+
use bevy_mod_openxr::{helper_traits::ToQuat, resources::OxrViews};
5
+
use bevy_mod_xr::session::{XrState, XrTrackingRoot};
6
+
use felix_audio::voice::microphone::VoiceChatMicrophone;
7
+
8
+
use crate::net::connection::Connection;
9
10
#[derive(Component)]
11
pub struct DebugCamera{
···
22
}
23
}
24
25
+
pub fn vr_locomotion( // TODO: Move locomotion to controllers instead of keyboard
26
+
views: ResMut<OxrViews>,
27
+
mut position_query: Query<&mut Transform, With<XrTrackingRoot>>,
28
+
keys: Res<ButtonInput<KeyCode>>,
29
+
xr_state: Res<XrState>,
30
+
time: Res<Time>
31
+
){
32
+
if *xr_state == XrState::Running{
33
+
let mut delta_time = time.delta_secs();
34
+
if keys.pressed(KeyCode::ShiftLeft){ delta_time *= 2.0; }
35
+
36
+
let mut transform = position_query.single_mut().unwrap();
37
+
let view = views.first().unwrap();
38
+
39
+
let cam = view.pose.orientation.to_quat();
40
+
41
+
if keys.pressed(KeyCode::KeyW){
42
+
let mut dir = cam * -Vec3::Z * delta_time;
43
+
dir.y = 0.0;
44
+
45
+
transform.translation += dir;
46
+
} else if keys.pressed(KeyCode::KeyS){
47
+
let mut dir = cam * Vec3::Z * delta_time;
48
+
dir.y = 0.0;
49
+
50
+
transform.translation += dir;
51
+
}
52
+
53
+
if keys.pressed(KeyCode::KeyA){
54
+
let mut dir = cam * -Vec3::X * delta_time;
55
+
dir.y = 0.0;
56
+
57
+
transform.translation += dir;
58
+
} else if keys.pressed(KeyCode::KeyD){
59
+
let mut dir = cam * Vec3::X * delta_time;
60
+
dir.y = 0.0;
61
+
62
+
transform.translation += dir;
63
+
}
64
+
}
65
+
}
66
+
67
pub fn update(
68
mut query: Query<(&mut DebugCamera, &mut Transform)>,
69
time: Res<Time>,
70
71
keys: Res<ButtonInput<KeyCode>>,
72
mouse_buttons: Res<ButtonInput<MouseButton>>,
73
mut mouse_motion: MessageReader<MouseMotion>,
74
+
75
+
// Debug Text
76
+
mut debug_text: Query<(&mut Text, &DebugText)>,
77
+
voice: Query<&VoiceChatMicrophone>,
78
+
networking: Query<&Connection>,
79
+
xr_state: Res<XrState>
80
){
81
+
let net_manager = networking.single().unwrap();
82
+
let xr_state = xr_state.into_inner();
83
84
let ( mut debug, mut transform ) = query.single_mut().unwrap();
85
86
+
if *xr_state != XrState::Running{
87
+
let mut delta_time = time.delta_secs();
88
+
if keys.pressed(KeyCode::ShiftLeft){ delta_time *= 2.0; }
89
+
90
+
for ev in mouse_motion.read(){
91
+
if mouse_buttons.pressed(MouseButton::Right){
92
+
debug.pitch -= ev.delta.y * delta_time * 0.1;
93
+
debug.yaw -= ev.delta.x * delta_time * 0.1;
94
+
}
95
+
}
96
+
97
+
transform.rotation = Quat::from_euler(EulerRot::YXZ, debug.yaw, debug.pitch, 0.0);
98
+
99
+
if keys.pressed(KeyCode::KeyW){
100
+
let dir = transform.forward();
101
+
transform.translation += dir * delta_time;
102
+
} else if keys.pressed(KeyCode::KeyS){
103
+
let dir = -transform.forward();
104
+
transform.translation += dir * delta_time;
105
}
106
107
+
if keys.pressed(KeyCode::KeyA){
108
+
let dir = transform.left();
109
+
transform.translation += dir * delta_time;
110
+
} else if keys.pressed(KeyCode::KeyD){
111
+
let dir = -transform.left();
112
+
transform.translation += dir * delta_time;
113
+
}
114
115
+
if keys.pressed(KeyCode::KeyE){
116
+
let dir = transform.up();
117
+
transform.translation += dir * delta_time;
118
+
} else if keys.pressed(KeyCode::KeyQ){
119
+
let dir = -transform.up();
120
+
transform.translation += dir * delta_time;
121
+
}
122
}
123
124
+
let mut remote_rms = "".to_owned();
125
+
for id in net_manager.get_remote_player_voice_ids(){
126
+
remote_rms += format!(
127
+
"{}: {:.4}db\n",
128
+
id,
129
+
net_manager.get_remote_player_voice_rms(&id)
130
+
).as_str();
131
}
132
133
+
let ( rms, mic_open ) = if let Ok(mic) = voice.single(){
134
+
mic.get_rms_of_last_packet()
135
+
} else{
136
+
( -1.0, false )
137
+
};
138
+
139
+
let ( mut text, _ ) = debug_text.single_mut().unwrap();
140
+
text.0 = format!(
141
+
"Microphone RMS: {:.4}db Open: {}
142
+
{}Position: X: {:.2} Y: {:.2} Z: {:.2}
143
+
Rotation: X: {:.2} Y: {:.2} Z: {:.2} W: {:.2}
144
+
XR State: {:#?}",
145
+
rms,
146
+
mic_open,
147
+
148
+
remote_rms,
149
+
150
+
transform.translation.x,
151
+
transform.translation.y,
152
+
transform.translation.z,
153
+
154
+
transform.rotation.x,
155
+
transform.rotation.y,
156
+
transform.rotation.z,
157
+
transform.rotation.w,
158
+
159
+
xr_state
160
+
);
161
+
}
162
+
163
+
#[derive(Component)]
164
+
pub struct DebugText;
165
+
166
+
pub fn setup(
167
+
mut commands: Commands
168
+
){
169
+
commands.spawn((
170
+
Node {
171
+
position_type: PositionType::Absolute,
172
+
bottom: px(5.0),
173
+
right: px(5.0),
174
+
..default()
175
+
},
176
+
Text::new("Here is some text"),
177
+
TextColor(Color::WHITE),
178
+
TextLayout::new_with_justify(Justify::Right),
179
+
DebugText
180
+
));
181
}
+1
-1
client/src/components/network_interface.rs
+1
-1
client/src/components/network_interface.rs
+48
-17
client/src/main.rs
+48
-17
client/src/main.rs
···
1
-
use bevy::{DefaultPlugins, app::{App, FixedUpdate, Startup, Update}, ecs::system::Commands};
2
use felix_audio::{FelixAudio, voice};
3
4
use crate::{components::{debug_camera, network_interface, remote_player}, setup::setup};
···
8
mod net;
9
10
fn main() {
11
-
dotenvy::dotenv().unwrap();
12
13
-
App::new()
14
-
.add_plugins((
15
-
DefaultPlugins,
16
-
FelixAudio
17
))
18
-
.add_systems(Startup, setup)
19
-
.add_systems(Startup, move | mut commands: Commands |{
20
-
let ( comp, voice ) = net::handle_net().expect("Network Module Failed.");
21
22
-
commands.spawn(comp);
23
-
commands.spawn(voice::init_microphone(voice).expect("Failed to start microphone."));
24
-
})
25
-
.add_systems(Update, debug_camera::update)
26
-
.add_systems(Update, remote_player::update)
27
-
.add_systems(FixedUpdate, network_interface::fixed_update)
28
-
.run();
29
-
}
···
1
+
use std::{env, net::ToSocketAddrs};
2
+
3
+
use bevy::{app::{App, FixedUpdate, Startup, Update}, ecs::system::Commands, prelude::*, render::pipelined_rendering::PipelinedRenderingPlugin};
4
+
use bevy_mod_openxr::{add_xr_plugins, resources::OxrSessionConfig};
5
+
use bevy_mod_xr::session::{XrSessionCreated, XrSessionPlugin, XrState};
6
+
use bevy_xr_utils::tracking_utils::TrackingUtilitiesPlugin;
7
use felix_audio::{FelixAudio, voice};
8
9
use crate::{components::{debug_camera, network_interface, remote_player}, setup::setup};
···
13
mod net;
14
15
fn main() {
16
+
if let Err(err) = dotenvy::dotenv(){ println!("[WARN] .ENV failed loading {:#?}", err); }
17
+
let try_use_vr = env::var("DONT_USE_VR").is_err();
18
19
+
let mut app = App::new();
20
+
21
+
if try_use_vr{
22
+
app.add_plugins((
23
+
add_xr_plugins(
24
+
DefaultPlugins
25
+
.build()
26
+
.disable::<PipelinedRenderingPlugin>(),
27
+
).set(XrSessionPlugin { auto_handle: true }),
28
+
TrackingUtilitiesPlugin
29
))
30
+
.insert_resource(OxrSessionConfig {
31
+
..Default::default()
32
+
})
33
+
.add_systems(XrSessionCreated, || { println!("[INFO] Started VR") });
34
+
} else{
35
+
app
36
+
.add_plugins(DefaultPlugins)
37
+
.insert_resource(XrState::Unavailable);
38
+
}
39
40
+
app.add_plugins(FelixAudio)
41
+
.add_systems(Startup, setup)
42
+
.add_systems(Startup, move | mut commands: Commands |{
43
+
let addr = env::var("HOST").unwrap().to_socket_addrs().unwrap().nth(0).unwrap();
44
+
45
+
let ( comp, voice ) = net::handle_net(addr.clone()).expect("Network Module Failed");
46
+
commands.spawn(comp);
47
+
48
+
match voice::init_microphone(addr, voice){
49
+
Ok(voice) => { commands.spawn(voice); },
50
+
Err(err) => println!("[WARN] Failed to start microphone: {}", err)
51
+
}
52
+
})
53
+
.add_systems(Update, debug_camera::update)
54
+
.add_systems(Update, debug_camera::vr_locomotion)
55
+
.add_systems(Startup, debug_camera::setup)
56
+
.add_systems(Update, remote_player::update)
57
+
.add_systems(FixedUpdate, network_interface::fixed_update);
58
+
59
+
app.run();
60
+
}
+52
-14
client/src/net/connection.rs
+52
-14
client/src/net/connection.rs
···
1
-
use std::{collections::{HashMap, VecDeque}, io::{Read, Write}, net::{SocketAddr, TcpStream, UdpSocket}, sync::{Arc, Mutex, RwLock}, thread};
2
use bevy::ecs::component::Component;
3
use felix_audio::voice::decoder::VoiceChatDecoder;
4
use tokio::sync::broadcast::{self, Receiver, Sender};
···
14
udp: UdpSocket,
15
udp_server_address: SocketAddr,
16
17
net_recv: Receiver<NetClientCommand>,
18
19
voice_queues: Arc<RwLock<HashMap<String, VoiceChatDecoder>>>,
20
-
pub id: String
21
}
22
23
impl Connection{
24
pub fn new( stream: TcpStream, udp: UdpSocket, udp_server_address: SocketAddr ) -> Self{
25
let ( event_sender, event_recv ) = broadcast::channel(32);
26
27
let mut conn = Self {
28
tcp: stream,
···
30
udp,
31
udp_server_address,
32
33
net_recv: event_recv,
34
35
voice_queues: Arc::new(RwLock::new(HashMap::new())),
36
-
id: "".to_owned()
37
};
38
39
-
conn.start_listener_thread(event_sender).unwrap();
40
41
let packet = NotifyConnectionInfo { id: conn.id.clone() };
42
conn.send_reliable(packet).unwrap();
···
44
conn
45
}
46
47
-
fn start_listener_thread(&self, cmd: Sender<NetClientCommand>) -> anyhow::Result<()>{
48
let mut tcp = self.tcp.try_clone()?;
49
let udp = self.udp.try_clone()?;
50
···
54
let srv_addr = self.udp_server_address.clone();
55
let voice_queues = self.voice_queues.clone();
56
57
thread::spawn(move || { // UDP RECV THREAD
58
let mut buf = [0; 1024];
59
60
while let Ok((length, addr)) = udp_1.recv_from(&mut buf){
61
if addr != srv_addr{ continue; }
62
63
let mut msg: Buffer = (&buf[0..length]).into();
64
65
while msg.left() > 0{
66
let packet = packet::parse(&mut msg);
67
-
cmd_1.send(NetClientCommand::RecvPacket(packet)).unwrap();
68
}
69
}
70
});
···
74
75
while let Ok(length) = tcp.read(&mut buf){
76
if length == 0 { break; }
77
78
let mut msg: Buffer = (&buf[0..length]).into();
79
···
87
let packet = LinkUDP { id: info.id };
88
let packet: Vec<_> = packet.to_buf().into();
89
90
-
udp.send_to(&packet, "127.0.0.1:2603").unwrap();
91
-
},
92
-
PacketTypes::PlayerVoicePacket(packet) => {
93
-
let voices = voice_queues.read().unwrap();
94
-
if let Some(decoder) = voices.get(&packet.id){
95
-
decoder.decode(packet.packet); }
96
},
97
_ => {
98
cmd.send(NetClientCommand::RecvPacket(packet)).unwrap();
···
107
Ok(())
108
}
109
110
-
pub fn start_listening_for_player_voice( &mut self, id: &String ) -> Arc<Mutex<VecDeque<f32>>>{
111
let voice_queue = Arc::new(Mutex::new(VecDeque::new()));
112
let decoder = VoiceChatDecoder::new(voice_queue.clone());
113
···
117
voice_queue
118
}
119
120
-
pub fn stop_listening_for_player_voice( &mut self, id: &String ){
121
let mut voices = self.voice_queues.write().unwrap();
122
voices.remove(id);
123
}
···
138
self.udp.send_to(&buf, self.udp_server_address)?;
139
140
Ok(())
141
}
142
}
···
1
+
use std::{collections::{HashMap, VecDeque}, io::{Read, Write}, net::{Shutdown, SocketAddr, TcpStream, UdpSocket}, sync::{Arc, Mutex, RwLock}, thread};
2
use bevy::ecs::component::Component;
3
use felix_audio::voice::decoder::VoiceChatDecoder;
4
use tokio::sync::broadcast::{self, Receiver, Sender};
···
14
udp: UdpSocket,
15
udp_server_address: SocketAddr,
16
17
+
net_send: Sender<NetClientCommand>,
18
net_recv: Receiver<NetClientCommand>,
19
20
voice_queues: Arc<RwLock<HashMap<String, VoiceChatDecoder>>>,
21
+
pub id: String,
22
+
23
+
killed_signal: broadcast::Sender<()>
24
}
25
26
impl Connection{
27
pub fn new( stream: TcpStream, udp: UdpSocket, udp_server_address: SocketAddr ) -> Self{
28
let ( event_sender, event_recv ) = broadcast::channel(32);
29
+
let ( killed_signal_send, killed_signal ) = broadcast::channel(32);
30
31
let mut conn = Self {
32
tcp: stream,
···
34
udp,
35
udp_server_address,
36
37
+
net_send: event_sender.clone(),
38
net_recv: event_recv,
39
40
voice_queues: Arc::new(RwLock::new(HashMap::new())),
41
+
id: "".to_owned(),
42
+
43
+
killed_signal: killed_signal_send
44
};
45
46
+
conn.start_listener_thread(event_sender, killed_signal).unwrap();
47
48
let packet = NotifyConnectionInfo { id: conn.id.clone() };
49
conn.send_reliable(packet).unwrap();
···
51
conn
52
}
53
54
+
fn start_listener_thread(&self, cmd: Sender<NetClientCommand>, mut signal: Receiver<()>) -> anyhow::Result<()>{
55
let mut tcp = self.tcp.try_clone()?;
56
let udp = self.udp.try_clone()?;
57
···
61
let srv_addr = self.udp_server_address.clone();
62
let voice_queues = self.voice_queues.clone();
63
64
+
let mut signal_1 = signal.resubscribe();
65
+
66
thread::spawn(move || { // UDP RECV THREAD
67
let mut buf = [0; 1024];
68
69
while let Ok((length, addr)) = udp_1.recv_from(&mut buf){
70
if addr != srv_addr{ continue; }
71
+
if signal_1.try_recv().is_ok(){ break; }
72
73
let mut msg: Buffer = (&buf[0..length]).into();
74
75
while msg.left() > 0{
76
let packet = packet::parse(&mut msg);
77
+
78
+
match packet{
79
+
PacketTypes::PlayerVoicePacket(packet) => {
80
+
let voices = voice_queues.try_read().unwrap();
81
+
if let Some(decoder) = voices.get(&packet.id){
82
+
decoder.decode(packet.packet); }
83
+
},
84
+
_ => {
85
+
cmd_1.send(NetClientCommand::RecvPacket(packet)).unwrap();
86
+
}
87
+
}
88
}
89
}
90
});
···
94
95
while let Ok(length) = tcp.read(&mut buf){
96
if length == 0 { break; }
97
+
if signal.try_recv().is_ok(){ break; }
98
99
let mut msg: Buffer = (&buf[0..length]).into();
100
···
108
let packet = LinkUDP { id: info.id };
109
let packet: Vec<_> = packet.to_buf().into();
110
111
+
udp.send_to(&packet, srv_addr).unwrap();
112
},
113
_ => {
114
cmd.send(NetClientCommand::RecvPacket(packet)).unwrap();
···
123
Ok(())
124
}
125
126
+
pub fn get_remote_player_voice_ids( &self ) -> Vec<String>{
127
+
let voices = self.voice_queues.read().unwrap();
128
+
voices.iter().map(| x | x.0.clone()).collect()
129
+
}
130
+
131
+
pub fn get_remote_player_voice_rms( &self, id: &String ) -> f32{
132
+
let voices = self.voice_queues.read().unwrap();
133
+
let decoder = voices.get(id).unwrap();
134
+
135
+
decoder.get_last_rms()
136
+
}
137
+
138
+
pub fn start_listening_for_player_voice( &self, id: &String ) -> Arc<Mutex<VecDeque<f32>>>{
139
let voice_queue = Arc::new(Mutex::new(VecDeque::new()));
140
let decoder = VoiceChatDecoder::new(voice_queue.clone());
141
···
145
voice_queue
146
}
147
148
+
pub fn stop_listening_for_player_voice( &self, id: &String ){
149
let mut voices = self.voice_queues.write().unwrap();
150
voices.remove(id);
151
}
···
166
self.udp.send_to(&buf, self.udp_server_address)?;
167
168
Ok(())
169
+
}
170
+
}
171
+
172
+
impl Drop for Connection{
173
+
fn drop(&mut self) {
174
+
println!("Killing connection to: {}", self.udp_server_address);
175
+
self.net_send.send(NetClientCommand::Disconnected).unwrap();
176
+
177
+
self.killed_signal.send(()).unwrap();
178
+
self.tcp.shutdown(Shutdown::Both).unwrap();
179
}
180
}
+2
-4
client/src/net/mod.rs
+2
-4
client/src/net/mod.rs
···
1
-
use std::{env, net::{TcpStream, ToSocketAddrs, UdpSocket}};
2
3
use bevy::prelude::*;
4
use felix_net::packet::PacketTypes;
···
14
RecvPacket(PacketTypes)
15
}
16
17
-
pub fn handle_net() -> anyhow::Result<( Connection, UdpSocket )>{
18
-
let addr = env::var("HOST")?.to_socket_addrs()?.nth(0).unwrap();
19
-
20
let tcp = TcpStream::connect(addr)?;
21
let udp = UdpSocket::bind("0.0.0.0:0")?;
22
···
1
+
use std::net::{SocketAddr, TcpStream, UdpSocket};
2
3
use bevy::prelude::*;
4
use felix_net::packet::PacketTypes;
···
14
RecvPacket(PacketTypes)
15
}
16
17
+
pub fn handle_net( addr: SocketAddr ) -> anyhow::Result<( Connection, UdpSocket )>{
18
let tcp = TcpStream::connect(addr)?;
19
let udp = UdpSocket::bind("0.0.0.0:0")?;
20
+74
-21
client/src/setup.rs
+74
-21
client/src/setup.rs
···
1
use bevy::prelude::*;
2
use felix_audio::FelixAudioListener;
3
4
-
use crate::debug_camera;
5
6
pub fn setup(
7
mut commands: Commands,
8
mut meshes: ResMut<Assets<Mesh>>,
9
mut materials: ResMut<Assets<StandardMaterial>>
10
){
11
-
commands.spawn((
12
-
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
13
-
MeshMaterial3d(materials.add(Color::WHITE)),
14
-
Transform::from_xyz(5.0, 0.0, 0.0),
15
-
));
16
17
commands.spawn((
18
-
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
19
-
MeshMaterial3d(materials.add(Color::WHITE)),
20
-
Transform::from_xyz(-5.0, 0.0, 0.0)
21
));
22
23
commands.spawn((
24
-
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
25
-
MeshMaterial3d(materials.add(Color::WHITE)),
26
-
Transform::from_xyz(0.0, 0.0, 5.0)
27
));
28
29
commands.spawn((
30
-
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
31
-
MeshMaterial3d(materials.add(Color::WHITE)),
32
-
Transform::from_xyz(0.0, 0.0, -5.0)
33
));
34
35
-
commands.spawn((
36
-
debug_camera::DebugCamera::default(),
37
-
Camera3d::default(),
38
-
Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
39
-
FelixAudioListener
40
-
));
41
}
···
1
use bevy::prelude::*;
2
+
use bevy_mod_xr::session::XrTracker;
3
+
use bevy_xr_utils::tracking_utils::{XrTrackedLocalFloor, XrTrackedStage, XrTrackedView};
4
+
use felix_assets::{BevyObjectData, BevyObjectLightDataType};
5
use felix_audio::FelixAudioListener;
6
7
+
use crate::components::debug_camera::DebugCamera;
8
9
pub fn setup(
10
mut commands: Commands,
11
mut meshes: ResMut<Assets<Mesh>>,
12
mut materials: ResMut<Assets<StandardMaterial>>
13
){
14
+
// TODO: World loading from server
15
+
// TODO: UI and Menus
16
+
17
+
// commands.spawn((
18
+
// Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
19
+
// MeshMaterial3d(materials.add(Color::WHITE)),
20
+
// Transform::from_xyz(5.0, 0.0, 0.0),
21
+
// ));
22
+
23
+
// commands.spawn((
24
+
// Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
25
+
// MeshMaterial3d(materials.add(Color::WHITE)),
26
+
// Transform::from_xyz(-5.0, 0.0, 0.0)
27
+
// ));
28
+
29
+
// commands.spawn((
30
+
// Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
31
+
// MeshMaterial3d(materials.add(Color::WHITE)),
32
+
// Transform::from_xyz(0.0, 0.0, 5.0)
33
+
// ));
34
+
35
+
// commands.spawn((
36
+
// Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
37
+
// MeshMaterial3d(materials.add(Color::WHITE)),
38
+
// Transform::from_xyz(0.0, 0.0, -5.0)
39
+
// ));
40
41
commands.spawn((
42
+
DebugCamera::default(), // TODO: Build a proper player controller
43
+
Camera3d::default(),
44
+
Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
45
+
FelixAudioListener,
46
+
XrTracker,
47
+
XrTrackedView
48
));
49
50
commands.spawn((
51
+
Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))),
52
+
MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 144))),
53
+
Transform::from_xyz(0.0, 0.0, 0.0),
54
+
XrTrackedLocalFloor,
55
+
XrTracker,
56
));
57
58
commands.spawn((
59
+
Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))),
60
+
MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 255))),
61
+
Transform::from_xyz(0.0, 0.0, 0.0),
62
+
XrTrackedStage,
63
+
XrTracker,
64
));
65
66
+
let gos = felix_assets::load("/home/phaze/Documents/rindo.flx").unwrap();
67
+
for go in gos{
68
+
match go.data{
69
+
BevyObjectData::Mesh(mesh) => {
70
+
commands.spawn((
71
+
Mesh3d(meshes.add(mesh)),
72
+
MeshMaterial3d(materials.add(Color::WHITE)),
73
+
go.transform
74
+
));
75
+
},
76
+
BevyObjectData::Light(light) => {
77
+
match light.type_{
78
+
BevyObjectLightDataType::Point => {
79
+
commands.spawn((
80
+
PointLight {
81
+
color: light.colour,
82
+
intensity: light.power,
83
+
shadows_enabled: true,
84
+
..Default::default()
85
+
},
86
+
go.transform
87
+
));
88
+
},
89
+
_ => {}
90
+
}
91
+
}
92
+
}
93
+
}
94
}
-4
server/src/net/connection.rs
-4
server/src/net/connection.rs
···
74
self.position = packet.position;
75
self.rotation = packet.rotation;
76
},
77
-
PacketTypes::PlayerVoicePacket(mut voice) => {
78
-
voice.id = self.id.clone(); // NOTE: See "audio/src/voice/microphone.rs:71"
79
-
self.main_thread_sender.send(NetServerCommand::BroadcastVoice(voice)).unwrap();
80
-
},
81
_ => {}
82
}
83
+19
-10
server/src/net/mod.rs
+19
-10
server/src/net/mod.rs
···
1
use std::{collections::HashMap, env, net::{SocketAddr, TcpListener, TcpStream, UdpSocket}, thread, time::Duration};
2
3
-
use felix_net::{buffer::Buffer, packet::{self, PacketTypes}, packets::{player_join_packet::PlayerJoinPacket, player_leave_packet::PlayerLeavePacket, player_list_packet::PlayerListPacket, player_voice_packet::PlayerVoicePacket, update_clients_positions::UpdateClientsPositions}};
4
5
use crate::net::connection::Connection;
6
···
13
SendOverUDP(Vec<u8>, SocketAddr),
14
RecvOverUDP(SocketAddr, PacketTypes),
15
RecvOverTCP(String, PacketTypes),
16
-
BroadcastVoice(PlayerVoicePacket),
17
BroadcastPlayerPositions
18
}
19
20
pub fn handle_net() -> anyhow::Result<()>{
21
let port = env::var("HOST_PORT")?;
22
23
let tcp_listener = TcpListener::bind(format!("0.0.0.0:{}", port))?;
···
113
},
114
NetServerCommand::RecvOverUDP(addr, packet) => {
115
if let Some(conn_id) = connections_by_address.get(&addr){
116
-
let conn = connections.get_mut(conn_id).unwrap();
117
-
conn.recv_packet(packet)?;
118
}
119
},
120
NetServerCommand::RecvOverTCP(conn_id, packet) => {
···
130
131
for (_, conn) in &mut connections{
132
conn.try_send_unreliable(packet.clone())?; }
133
-
},
134
-
NetServerCommand::BroadcastVoice(packet) => {
135
-
for ( remote_id, conn ) in &mut connections{
136
-
if remote_id == &packet.id { continue; }
137
-
conn.try_send_unreliable(packet.clone())?;
138
-
}
139
}
140
}
141
}
···
1
use std::{collections::HashMap, env, net::{SocketAddr, TcpListener, TcpStream, UdpSocket}, thread, time::Duration};
2
3
+
use felix_net::{buffer::Buffer, packet::{self, PacketTypes}, packets::{player_join_packet::PlayerJoinPacket, player_leave_packet::PlayerLeavePacket, player_list_packet::PlayerListPacket, update_clients_positions::UpdateClientsPositions}};
4
5
use crate::net::connection::Connection;
6
···
13
SendOverUDP(Vec<u8>, SocketAddr),
14
RecvOverUDP(SocketAddr, PacketTypes),
15
RecvOverTCP(String, PacketTypes),
16
BroadcastPlayerPositions
17
}
18
19
pub fn handle_net() -> anyhow::Result<()>{
20
+
// TODO: Multiple instances
21
+
// Need to decide if i want to run each instance on a seperate thread
22
+
23
let port = env::var("HOST_PORT")?;
24
25
let tcp_listener = TcpListener::bind(format!("0.0.0.0:{}", port))?;
···
115
},
116
NetServerCommand::RecvOverUDP(addr, packet) => {
117
if let Some(conn_id) = connections_by_address.get(&addr){
118
+
match packet {
119
+
PacketTypes::PlayerVoicePacket(mut voice) => { // Keep voice stuff in one thread to avoid copying a lot of data all over the place
120
+
voice.id = conn_id.clone(); // NOTE: See "audio/src/voice/microphone.rs:71"
121
+
122
+
for ( remote_id, conn ) in &mut connections{
123
+
if remote_id == &voice.id { continue; }
124
+
conn.try_send_unreliable(voice.clone())?;
125
+
}
126
+
},
127
+
_ => {
128
+
let conn = connections.get_mut(conn_id).unwrap();
129
+
conn.recv_packet(packet)?;
130
+
}
131
+
}
132
+
133
}
134
},
135
NetServerCommand::RecvOverTCP(conn_id, packet) => {
···
145
146
for (_, conn) in &mut connections{
147
conn.try_send_unreliable(packet.clone())?; }
148
}
149
}
150
}