@bornengine/engine 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +231 -0
- package/native/android/Cargo.lock +1848 -0
- package/native/android/Cargo.toml +24 -0
- package/native/android/src/lib.rs +702 -0
- package/native/ios/Cargo.lock +1690 -0
- package/native/ios/Cargo.toml +32 -0
- package/native/ios/src/lib.rs +1267 -0
- package/native/linux/Cargo.lock +3279 -0
- package/native/linux/Cargo.toml +29 -0
- package/native/linux/src/lib.rs +1331 -0
- package/native/macos/Cargo.lock +3310 -0
- package/native/macos/Cargo.toml +46 -0
- package/native/macos/src/lib.rs +1302 -0
- package/native/shared/Cargo.lock +1899 -0
- package/native/shared/Cargo.toml +62 -0
- package/native/shared/assets/default_font.ttf +0 -0
- package/native/shared/build.rs +270 -0
- package/native/shared/shaders/common/clouds.wgsl +122 -0
- package/native/shared/shaders/common/fog.wgsl +16 -0
- package/native/shared/shaders/common/foliage_wind.wgsl +98 -0
- package/native/shared/shaders/common/imposter.wgsl +112 -0
- package/native/shared/shaders/common/pbr.wgsl +186 -0
- package/native/shared/shaders/common/shadows.wgsl +186 -0
- package/native/shared/shaders/common/sky.wgsl +8 -0
- package/native/shared/shaders/common/tonemap.wgsl +25 -0
- package/native/shared/shaders/impulse_field.wgsl +57 -0
- package/native/shared/shaders/material_abi.wgsl +383 -0
- package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
- package/native/shared/src/anim_mixer.rs +61 -0
- package/native/shared/src/attach.rs +263 -0
- package/native/shared/src/audio/decode.rs +123 -0
- package/native/shared/src/audio/mod.rs +863 -0
- package/native/shared/src/audio/render.rs +892 -0
- package/native/shared/src/audio/spsc.rs +156 -0
- package/native/shared/src/audio/stream.rs +226 -0
- package/native/shared/src/custom_shaders.rs +104 -0
- package/native/shared/src/decals.rs +245 -0
- package/native/shared/src/drs.rs +211 -0
- package/native/shared/src/engine.rs +261 -0
- package/native/shared/src/ffi.rs +116 -0
- package/native/shared/src/ffi_core/assets.rs +388 -0
- package/native/shared/src/ffi_core/audio_ffi.rs +184 -0
- package/native/shared/src/ffi_core/draw.rs +334 -0
- package/native/shared/src/ffi_core/game_loop.rs +577 -0
- package/native/shared/src/ffi_core/input.rs +234 -0
- package/native/shared/src/ffi_core/mod.rs +127 -0
- package/native/shared/src/ffi_core/models.rs +1154 -0
- package/native/shared/src/ffi_core/ragdoll_ffi.rs +261 -0
- package/native/shared/src/ffi_core/scene.rs +626 -0
- package/native/shared/src/ffi_core/vfx.rs +212 -0
- package/native/shared/src/ffi_core/visual.rs +691 -0
- package/native/shared/src/frame_callbacks.rs +122 -0
- package/native/shared/src/geometry.rs +236 -0
- package/native/shared/src/handles.rs +182 -0
- package/native/shared/src/input.rs +448 -0
- package/native/shared/src/jolt_sys.rs +822 -0
- package/native/shared/src/lib.rs +55 -0
- package/native/shared/src/models.rs +1093 -0
- package/native/shared/src/models_gltf.rs +1280 -0
- package/native/shared/src/particles.rs +391 -0
- package/native/shared/src/physics_jolt.rs +1908 -0
- package/native/shared/src/picking.rs +298 -0
- package/native/shared/src/postfx.rs +345 -0
- package/native/shared/src/profiler.rs +492 -0
- package/native/shared/src/ragdoll.rs +474 -0
- package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
- package/native/shared/src/renderer/brdf_lut.rs +154 -0
- package/native/shared/src/renderer/draw2d.rs +143 -0
- package/native/shared/src/renderer/formats.rs +822 -0
- package/native/shared/src/renderer/froxel.rs +421 -0
- package/native/shared/src/renderer/gi_bake.rs +653 -0
- package/native/shared/src/renderer/graph.rs +462 -0
- package/native/shared/src/renderer/hiz.rs +269 -0
- package/native/shared/src/renderer/hot_reload.rs +390 -0
- package/native/shared/src/renderer/impulse_field.rs +456 -0
- package/native/shared/src/renderer/lighting.rs +154 -0
- package/native/shared/src/renderer/material_instancing.rs +171 -0
- package/native/shared/src/renderer/material_pipeline.rs +700 -0
- package/native/shared/src/renderer/material_system.rs +1996 -0
- package/native/shared/src/renderer/material_system_tests.rs +601 -0
- package/native/shared/src/renderer/material_system_wasm.rs +41 -0
- package/native/shared/src/renderer/mod.rs +12556 -0
- package/native/shared/src/renderer/model_draw.rs +641 -0
- package/native/shared/src/renderer/occlusion.rs +429 -0
- package/native/shared/src/renderer/planar_pass.rs +593 -0
- package/native/shared/src/renderer/planar_reflection.rs +499 -0
- package/native/shared/src/renderer/post_pass.rs +249 -0
- package/native/shared/src/renderer/postfx_chain.rs +728 -0
- package/native/shared/src/renderer/pt_pass.rs +577 -0
- package/native/shared/src/renderer/scene_pass.rs +607 -0
- package/native/shared/src/renderer/shader_include.rs +205 -0
- package/native/shared/src/renderer/shader_library.rs +135 -0
- package/native/shared/src/renderer/shaders/ao.rs +570 -0
- package/native/shared/src/renderer/shaders/core.rs +1243 -0
- package/native/shared/src/renderer/shaders/env.rs +907 -0
- package/native/shared/src/renderer/shaders/gi.rs +810 -0
- package/native/shared/src/renderer/shaders/mod.rs +19 -0
- package/native/shared/src/renderer/shaders/post.rs +1558 -0
- package/native/shared/src/renderer/shaders/pt.rs +1859 -0
- package/native/shared/src/renderer/shaders/ssgi.rs +1586 -0
- package/native/shared/src/renderer/shadow_pass.rs +731 -0
- package/native/shared/src/renderer/ssgi_pass.rs +392 -0
- package/native/shared/src/renderer/ssr_pass.rs +188 -0
- package/native/shared/src/renderer/texture_store.rs +473 -0
- package/native/shared/src/renderer/transient.rs +591 -0
- package/native/shared/src/renderer/types.rs +941 -0
- package/native/shared/src/renderer/util.rs +152 -0
- package/native/shared/src/scene.rs +1362 -0
- package/native/shared/src/sdf_cache.rs +274 -0
- package/native/shared/src/shadows.rs +1036 -0
- package/native/shared/src/staging.rs +102 -0
- package/native/shared/src/string_header.rs +266 -0
- package/native/shared/src/text_renderer.rs +502 -0
- package/native/shared/src/textures.rs +197 -0
- package/native/tvos/Cargo.lock +1693 -0
- package/native/tvos/Cargo.toml +36 -0
- package/native/tvos/metal-patched/Cargo.toml +178 -0
- package/native/tvos/metal-patched/LICENSE-APACHE +201 -0
- package/native/tvos/metal-patched/LICENSE-MIT +25 -0
- package/native/tvos/metal-patched/src/acceleration_structure.rs +667 -0
- package/native/tvos/metal-patched/src/acceleration_structure_pass.rs +108 -0
- package/native/tvos/metal-patched/src/argument.rs +366 -0
- package/native/tvos/metal-patched/src/blitpass.rs +102 -0
- package/native/tvos/metal-patched/src/buffer.rs +71 -0
- package/native/tvos/metal-patched/src/capturedescriptor.rs +76 -0
- package/native/tvos/metal-patched/src/capturemanager.rs +113 -0
- package/native/tvos/metal-patched/src/commandbuffer.rs +192 -0
- package/native/tvos/metal-patched/src/commandqueue.rs +44 -0
- package/native/tvos/metal-patched/src/computepass.rs +107 -0
- package/native/tvos/metal-patched/src/constants.rs +152 -0
- package/native/tvos/metal-patched/src/counters.rs +119 -0
- package/native/tvos/metal-patched/src/depthstencil.rs +190 -0
- package/native/tvos/metal-patched/src/device.rs +2134 -0
- package/native/tvos/metal-patched/src/drawable.rs +39 -0
- package/native/tvos/metal-patched/src/encoder.rs +2041 -0
- package/native/tvos/metal-patched/src/heap.rs +281 -0
- package/native/tvos/metal-patched/src/indirect_encoder.rs +344 -0
- package/native/tvos/metal-patched/src/lib.rs +657 -0
- package/native/tvos/metal-patched/src/library.rs +902 -0
- package/native/tvos/metal-patched/src/mps.rs +575 -0
- package/native/tvos/metal-patched/src/pipeline/compute.rs +475 -0
- package/native/tvos/metal-patched/src/pipeline/mod.rs +71 -0
- package/native/tvos/metal-patched/src/pipeline/render.rs +762 -0
- package/native/tvos/metal-patched/src/renderpass.rs +443 -0
- package/native/tvos/metal-patched/src/resource.rs +182 -0
- package/native/tvos/metal-patched/src/sampler.rs +165 -0
- package/native/tvos/metal-patched/src/sync.rs +178 -0
- package/native/tvos/metal-patched/src/texture.rs +352 -0
- package/native/tvos/metal-patched/src/types.rs +90 -0
- package/native/tvos/metal-patched/src/vertexdescriptor.rs +250 -0
- package/native/tvos/src/audio_backend.rs +197 -0
- package/native/tvos/src/lib.rs +1891 -0
- package/native/visionos/Cargo.lock +1693 -0
- package/native/visionos/Cargo.toml +40 -0
- package/native/visionos/src/audio_backend.rs +197 -0
- package/native/visionos/src/lib.rs +1887 -0
- package/native/watchos/Cargo.lock +16 -0
- package/native/watchos/Cargo.toml +19 -0
- package/native/watchos/shaders/bloom_postfx.metal +99 -0
- package/native/watchos/src/BloomWatchApp.swift +1267 -0
- package/native/watchos/src/BloomWatchAudio.swift +179 -0
- package/native/watchos/src/audio.rs +55 -0
- package/native/watchos/src/draw_list.rs +229 -0
- package/native/watchos/src/ffi_stubs.rs +915 -0
- package/native/watchos/src/ffi_stubs_manual.rs +35 -0
- package/native/watchos/src/lib.rs +1124 -0
- package/native/watchos/src/models.rs +746 -0
- package/native/watchos/src/postfx.rs +95 -0
- package/native/watchos/src/scene.rs +534 -0
- package/native/watchos/src/textures.rs +184 -0
- package/native/web/Cargo.lock +1657 -0
- package/native/web/Cargo.toml +43 -0
- package/native/web/bloom_glue.js +695 -0
- package/native/web/build.sh +131 -0
- package/native/web/index.html +35 -0
- package/native/web/jolt_bridge.js +1519 -0
- package/native/web/src/input_ffi.rs +286 -0
- package/native/web/src/lib.rs +1796 -0
- package/native/web/src/material_ffi.rs +710 -0
- package/native/web/src/parity_ffi.rs +343 -0
- package/native/web/src/physics_ffi.rs +643 -0
- package/native/web/src/ragdoll_ffi.rs +250 -0
- package/native/web/src/render_settings.rs +98 -0
- package/native/windows/Cargo.lock +1815 -0
- package/native/windows/Cargo.toml +68 -0
- package/native/windows/src/lib.rs +1486 -0
- package/package.json +4279 -0
- package/src/audio/index.ts +315 -0
- package/src/core/colors.ts +63 -0
- package/src/core/index.ts +1206 -0
- package/src/core/keys.ts +63 -0
- package/src/core/types.ts +104 -0
- package/src/index.ts +171 -0
- package/src/math/index.ts +516 -0
- package/src/mobile/index.ts +294 -0
- package/src/models/index.ts +1258 -0
- package/src/physics/index.ts +1134 -0
- package/src/scene/index.ts +698 -0
- package/src/shapes/index.ts +120 -0
- package/src/text/index.ts +48 -0
- package/src/textures/index.ts +187 -0
- package/src/vfx/index.ts +191 -0
- package/src/world/index.ts +24 -0
- package/src/world/loader.ts +423 -0
- package/src/world/prefab.ts +217 -0
- package/src/world/render.ts +172 -0
- package/src/world/saver.ts +108 -0
- package/src/world/serialize.ts +301 -0
- package/src/world/terrain.ts +355 -0
- package/src/world/types.ts +160 -0
- package/src/world/validate.ts +319 -0
- package/src/world/version.ts +114 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
//! Texture/image/font/file loading, staging, screenshots.
|
|
2
|
+
//!
|
|
3
|
+
//! Section of [`define_core_ffi!`](crate::define_core_ffi) — see
|
|
4
|
+
//! `ffi_core/mod.rs` for the architecture and the invoking-crate contract.
|
|
5
|
+
//! Internal: platform crates must invoke `define_core_ffi!()`, never the
|
|
6
|
+
//! section macros directly.
|
|
7
|
+
|
|
8
|
+
#[doc(hidden)]
|
|
9
|
+
#[macro_export]
|
|
10
|
+
macro_rules! __bloom_ffi_assets {
|
|
11
|
+
() => {
|
|
12
|
+
|
|
13
|
+
// bloom_take_screenshot [source: macos]
|
|
14
|
+
#[no_mangle]
|
|
15
|
+
pub extern "C" fn bloom_take_screenshot(path_ptr: *const u8) {
|
|
16
|
+
$crate::ffi::guard("bloom_take_screenshot", move || {
|
|
17
|
+
let path = $crate::string_header::str_from_header(path_ptr).to_string();
|
|
18
|
+
eprintln!("bloom: screenshot requested -> '{}'", path);
|
|
19
|
+
let mut eng = engine();
|
|
20
|
+
eng.renderer.screenshot_requested = true;
|
|
21
|
+
eng.renderer.pending_screenshot_path = Some(path);
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// bloom_load_font [source: macos]
|
|
26
|
+
#[no_mangle]
|
|
27
|
+
pub extern "C" fn bloom_load_font(path_ptr: *const u8, _size: f64) -> f64 {
|
|
28
|
+
$crate::ffi::guard("bloom_load_font", move || {
|
|
29
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
30
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
31
|
+
match std::fs::read(path) {
|
|
32
|
+
Ok(data) => engine().text.load_font(&data) as f64,
|
|
33
|
+
Err(_) => 0.0,
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// bloom_unload_font [source: macos]
|
|
39
|
+
#[no_mangle]
|
|
40
|
+
pub extern "C" fn bloom_unload_font(font_handle: f64) {
|
|
41
|
+
$crate::ffi::guard("bloom_unload_font", move || {
|
|
42
|
+
engine().text.unload_font(font_handle as usize);
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// bloom_load_sound [source: curated]
|
|
47
|
+
#[no_mangle]
|
|
48
|
+
pub extern "C" fn bloom_load_sound(path_ptr: *const u8) -> f64 {
|
|
49
|
+
$crate::ffi::guard("bloom_load_sound", move || {
|
|
50
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
51
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
52
|
+
match std::fs::read(path) {
|
|
53
|
+
Ok(data) => match $crate::audio::decode_audio(path, &data) {
|
|
54
|
+
Some(s) => engine().audio.load_sound(s),
|
|
55
|
+
None => 0.0,
|
|
56
|
+
},
|
|
57
|
+
Err(_) => 0.0,
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// bloom_load_texture [source: curated]
|
|
63
|
+
#[no_mangle]
|
|
64
|
+
pub extern "C" fn bloom_load_texture(path_ptr: *const u8) -> f64 {
|
|
65
|
+
$crate::ffi::guard("bloom_load_texture", move || {
|
|
66
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
67
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
68
|
+
match std::fs::read(path) {
|
|
69
|
+
Ok(data) => {
|
|
70
|
+
let mut eng = engine();
|
|
71
|
+
let $crate::engine::EngineState { ref mut textures, ref mut renderer, .. } = *eng;
|
|
72
|
+
textures.load_texture(renderer, &data)
|
|
73
|
+
}
|
|
74
|
+
Err(_) => 0.0,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// bloom_unload_texture [source: curated]
|
|
80
|
+
#[no_mangle]
|
|
81
|
+
pub extern "C" fn bloom_unload_texture(handle: f64) {
|
|
82
|
+
$crate::ffi::guard("bloom_unload_texture", move || {
|
|
83
|
+
let mut eng = engine();
|
|
84
|
+
let $crate::engine::EngineState { ref mut textures, ref mut renderer, .. } = *eng;
|
|
85
|
+
textures.unload_texture(handle, renderer);
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// bloom_get_texture_width [source: macos]
|
|
90
|
+
#[no_mangle]
|
|
91
|
+
pub extern "C" fn bloom_get_texture_width(handle: f64) -> f64 {
|
|
92
|
+
$crate::ffi::guard("bloom_get_texture_width", move || {
|
|
93
|
+
let eng = engine();
|
|
94
|
+
eng.textures.get(handle).map(|t| t.width as f64).unwrap_or(0.0)
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// bloom_get_texture_height [source: macos]
|
|
99
|
+
#[no_mangle]
|
|
100
|
+
pub extern "C" fn bloom_get_texture_height(handle: f64) -> f64 {
|
|
101
|
+
$crate::ffi::guard("bloom_get_texture_height", move || {
|
|
102
|
+
let eng = engine();
|
|
103
|
+
eng.textures.get(handle).map(|t| t.height as f64).unwrap_or(0.0)
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// bloom_load_image [source: macos]
|
|
108
|
+
#[no_mangle]
|
|
109
|
+
pub extern "C" fn bloom_load_image(path_ptr: *const u8) -> f64 {
|
|
110
|
+
$crate::ffi::guard("bloom_load_image", move || {
|
|
111
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
112
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
113
|
+
match std::fs::read(path) {
|
|
114
|
+
Ok(data) => engine().textures.load_image(&data),
|
|
115
|
+
Err(_) => 0.0,
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// bloom_image_resize [source: macos]
|
|
121
|
+
#[no_mangle]
|
|
122
|
+
pub extern "C" fn bloom_image_resize(handle: f64, w: f64, h: f64) {
|
|
123
|
+
$crate::ffi::guard("bloom_image_resize", move || {
|
|
124
|
+
engine().textures.image_resize(handle, w as u32, h as u32);
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// bloom_image_crop [source: macos]
|
|
129
|
+
#[no_mangle]
|
|
130
|
+
pub extern "C" fn bloom_image_crop(handle: f64, x: f64, y: f64, w: f64, h: f64) {
|
|
131
|
+
$crate::ffi::guard("bloom_image_crop", move || {
|
|
132
|
+
engine().textures.image_crop(handle, x as u32, y as u32, w as u32, h as u32);
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// bloom_image_flip_h [source: macos]
|
|
137
|
+
#[no_mangle]
|
|
138
|
+
pub extern "C" fn bloom_image_flip_h(handle: f64) {
|
|
139
|
+
$crate::ffi::guard("bloom_image_flip_h", move || {
|
|
140
|
+
engine().textures.image_flip_h(handle);
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// bloom_image_flip_v [source: macos]
|
|
145
|
+
#[no_mangle]
|
|
146
|
+
pub extern "C" fn bloom_image_flip_v(handle: f64) {
|
|
147
|
+
$crate::ffi::guard("bloom_image_flip_v", move || {
|
|
148
|
+
engine().textures.image_flip_v(handle);
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// bloom_load_texture_from_image [source: curated]
|
|
153
|
+
#[no_mangle]
|
|
154
|
+
pub extern "C" fn bloom_load_texture_from_image(handle: f64) -> f64 {
|
|
155
|
+
$crate::ffi::guard("bloom_load_texture_from_image", move || {
|
|
156
|
+
let mut eng = engine();
|
|
157
|
+
let $crate::engine::EngineState { ref mut textures, ref mut renderer, .. } = *eng;
|
|
158
|
+
textures.load_texture_from_image(handle, renderer)
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// bloom_gen_texture_mipmaps [source: macos]
|
|
163
|
+
#[no_mangle]
|
|
164
|
+
pub extern "C" fn bloom_gen_texture_mipmaps(_handle: f64) {
|
|
165
|
+
$crate::ffi::guard("bloom_gen_texture_mipmaps", move || {
|
|
166
|
+
// Mipmap generation is handled by the GPU texture creation pipeline
|
|
167
|
+
// This is a no-op for now as wgpu handles mipmaps internally
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// bloom_load_shader [source: macos]
|
|
172
|
+
#[no_mangle]
|
|
173
|
+
pub extern "C" fn bloom_load_shader(source_ptr: *const u8) -> f64 {
|
|
174
|
+
$crate::ffi::guard("bloom_load_shader", move || {
|
|
175
|
+
let source = $crate::string_header::str_from_header(source_ptr);
|
|
176
|
+
engine().renderer.load_custom_shader(source) as f64
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// bloom_load_music [source: curated]
|
|
181
|
+
#[no_mangle]
|
|
182
|
+
pub extern "C" fn bloom_load_music(path_ptr: *const u8) -> f64 {
|
|
183
|
+
$crate::ffi::guard("bloom_load_music", move || {
|
|
184
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
185
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
186
|
+
match std::fs::read(path) {
|
|
187
|
+
// Streams OGG/MP3 from the compressed bytes (background
|
|
188
|
+
// decode worker); WAV and wasm32 fully decode.
|
|
189
|
+
Ok(data) => engine().audio.load_music_bytes(path, data),
|
|
190
|
+
Err(_) => 0.0,
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// bloom_write_file [source: macos]
|
|
196
|
+
#[no_mangle]
|
|
197
|
+
pub extern "C" fn bloom_write_file(path_ptr: *const u8, data_ptr: *const u8) -> f64 {
|
|
198
|
+
$crate::ffi::guard("bloom_write_file", move || {
|
|
199
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
200
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
201
|
+
// A string that failed ABI validation must NOT be written as "" and
|
|
202
|
+
// reported as a success. That is not a save, it is a deletion with a
|
|
203
|
+
// thumbs-up, and it is exactly what happened to every world the
|
|
204
|
+
// editor ever saved.
|
|
205
|
+
let data = match $crate::string_header::try_str_from_header(data_ptr) {
|
|
206
|
+
Some(d) => d,
|
|
207
|
+
None => return 0.0,
|
|
208
|
+
};
|
|
209
|
+
match std::fs::write(path, data.as_bytes()) {
|
|
210
|
+
Ok(_) => 1.0,
|
|
211
|
+
Err(_) => 0.0,
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// bloom_launch_process [EN-048]
|
|
217
|
+
//
|
|
218
|
+
// Perry's `child_process.spawn` COMPILES and then does nothing — it returns a
|
|
219
|
+
// child with an undefined pid and no process is started. So a tool that wants
|
|
220
|
+
// to launch another program (the editor's play-in-editor: save the level, run
|
|
221
|
+
// the game on it) has nowhere to go.
|
|
222
|
+
//
|
|
223
|
+
// Fire-and-forget by design. The caller is a GUI that must not block on, or
|
|
224
|
+
// die with, the thing it launched: close the game, and you are back in the
|
|
225
|
+
// editor with your undo history intact.
|
|
226
|
+
//
|
|
227
|
+
// `args` is newline-separated. Not shell-escaped and not shell-interpreted —
|
|
228
|
+
// there is no shell here, which is also why there is nothing to inject into.
|
|
229
|
+
#[no_mangle]
|
|
230
|
+
pub extern "C" fn bloom_launch_process(
|
|
231
|
+
cmd_ptr: *const u8, args_ptr: *const u8, cwd_ptr: *const u8,
|
|
232
|
+
) -> f64 {
|
|
233
|
+
$crate::ffi::guard("bloom_launch_process", move || {
|
|
234
|
+
let cmd = $crate::string_header::str_from_header(cmd_ptr);
|
|
235
|
+
if cmd.is_empty() { return 0.0; }
|
|
236
|
+
let args = $crate::string_header::str_from_header(args_ptr);
|
|
237
|
+
let cwd = $crate::string_header::str_from_header(cwd_ptr);
|
|
238
|
+
|
|
239
|
+
// Resolve the program against `cwd` when it is a bare name.
|
|
240
|
+
//
|
|
241
|
+
// Rust's `Command::current_dir` sets the CHILD's working directory --
|
|
242
|
+
// it does NOT affect how the program is FOUND, which happens in the
|
|
243
|
+
// parent's context. So launching "main.exe" with cwd "<project>"
|
|
244
|
+
// fails with "program not found" even though main.exe is sitting
|
|
245
|
+
// right there in <project>. Which is exactly what it did.
|
|
246
|
+
let bare = !cmd.chars().any(|ch| ch == '/' || ch == std::path::MAIN_SEPARATOR);
|
|
247
|
+
let resolved: std::path::PathBuf = if !cwd.is_empty() && bare {
|
|
248
|
+
std::path::Path::new(cwd).join(cmd)
|
|
249
|
+
} else {
|
|
250
|
+
std::path::PathBuf::from(cmd)
|
|
251
|
+
};
|
|
252
|
+
let mut c = std::process::Command::new(&resolved);
|
|
253
|
+
for a in args.split('\n') {
|
|
254
|
+
if !a.is_empty() { c.arg(a); }
|
|
255
|
+
}
|
|
256
|
+
if !cwd.is_empty() { c.current_dir(cwd); }
|
|
257
|
+
// Detach: we never wait on it, and we do not want its output in ours.
|
|
258
|
+
c.stdin(std::process::Stdio::null())
|
|
259
|
+
.stdout(std::process::Stdio::null())
|
|
260
|
+
.stderr(std::process::Stdio::null());
|
|
261
|
+
let r = c.spawn();
|
|
262
|
+
match r {
|
|
263
|
+
Ok(child) => child.id() as f64,
|
|
264
|
+
Err(_) => 0.0,
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// bloom_file_exists [source: macos]
|
|
270
|
+
#[no_mangle]
|
|
271
|
+
pub extern "C" fn bloom_file_exists(path_ptr: *const u8) -> f64 {
|
|
272
|
+
$crate::ffi::guard("bloom_file_exists", move || {
|
|
273
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
274
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
275
|
+
if std::path::Path::new(path).exists() { 1.0 } else { 0.0 }
|
|
276
|
+
})
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// bloom_read_file [source: curated]
|
|
280
|
+
#[no_mangle]
|
|
281
|
+
pub extern "C" fn bloom_read_file(path_ptr: *const u8) -> *const u8 {
|
|
282
|
+
$crate::ffi::guard("bloom_read_file", move || {
|
|
283
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
284
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
285
|
+
match std::fs::read_to_string(path) {
|
|
286
|
+
Ok(contents) => $crate::string_header::alloc_perry_string(&contents),
|
|
287
|
+
Err(_) => $crate::string_header::alloc_perry_string(""),
|
|
288
|
+
}
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// bloom_load_render_texture [source: macos]
|
|
293
|
+
#[no_mangle]
|
|
294
|
+
pub extern "C" fn bloom_load_render_texture(width: f64, height: f64) -> f64 {
|
|
295
|
+
$crate::ffi::guard("bloom_load_render_texture", move || {
|
|
296
|
+
let w = width as u32;
|
|
297
|
+
let h = height as u32;
|
|
298
|
+
let mut eng = engine();
|
|
299
|
+
let rt_handle = eng.textures.load_render_texture(w, h);
|
|
300
|
+
|
|
301
|
+
// Create the GPU texture via the renderer's public method.
|
|
302
|
+
let (bind_group_idx, _tex_vec_idx) = eng.renderer.create_render_texture(w, h);
|
|
303
|
+
|
|
304
|
+
// Register as a texture handle so drawTexture can sample it.
|
|
305
|
+
let tex_handle = eng.textures.textures.alloc($crate::textures::TextureData {
|
|
306
|
+
bind_group_idx, width: w, height: h,
|
|
307
|
+
});
|
|
308
|
+
eng.textures.set_render_texture_handle(rt_handle, tex_handle);
|
|
309
|
+
|
|
310
|
+
rt_handle
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// bloom_unload_render_texture [source: macos]
|
|
315
|
+
#[no_mangle]
|
|
316
|
+
pub extern "C" fn bloom_unload_render_texture(handle: f64) {
|
|
317
|
+
$crate::ffi::guard("bloom_unload_render_texture", move || {
|
|
318
|
+
engine().textures.unload_render_texture(handle);
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// bloom_stage_texture [source: macos]
|
|
323
|
+
#[no_mangle]
|
|
324
|
+
pub extern "C" fn bloom_stage_texture(path_ptr: *const u8) -> f64 {
|
|
325
|
+
$crate::ffi::guard("bloom_stage_texture", move || {
|
|
326
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
327
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
328
|
+
match std::fs::read(path) {
|
|
329
|
+
Ok(data) => $crate::staging::decode_and_stage_texture(&data),
|
|
330
|
+
Err(_) => 0.0,
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// bloom_stage_sound [source: curated]
|
|
336
|
+
#[no_mangle]
|
|
337
|
+
pub extern "C" fn bloom_stage_sound(path_ptr: *const u8) -> f64 {
|
|
338
|
+
$crate::ffi::guard("bloom_stage_sound", move || {
|
|
339
|
+
let path = $crate::string_header::str_from_header(path_ptr);
|
|
340
|
+
let path: &str = &bloom_resolve_asset_path(path);
|
|
341
|
+
let data = match std::fs::read(path) { Ok(d) => d, Err(_) => return 0.0 };
|
|
342
|
+
match $crate::audio::decode_audio(path, &data) {
|
|
343
|
+
Some(s) => $crate::staging::stage_sound(s),
|
|
344
|
+
None => 0.0,
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// bloom_commit_texture [source: macos]
|
|
350
|
+
#[no_mangle]
|
|
351
|
+
pub extern "C" fn bloom_commit_texture(staging_handle: f64) -> f64 {
|
|
352
|
+
$crate::ffi::guard("bloom_commit_texture", move || {
|
|
353
|
+
let staged = match $crate::staging::take_texture(staging_handle) {
|
|
354
|
+
Some(s) => s,
|
|
355
|
+
None => return 0.0,
|
|
356
|
+
};
|
|
357
|
+
let mut eng = engine();
|
|
358
|
+
let bind_group_idx = eng.renderer.register_texture(staged.width, staged.height, &staged.data);
|
|
359
|
+
eng.textures.textures.alloc($crate::textures::TextureData {
|
|
360
|
+
bind_group_idx, width: staged.width, height: staged.height,
|
|
361
|
+
})
|
|
362
|
+
})
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// bloom_commit_sound [source: macos]
|
|
366
|
+
#[no_mangle]
|
|
367
|
+
pub extern "C" fn bloom_commit_sound(staging_handle: f64) -> f64 {
|
|
368
|
+
$crate::ffi::guard("bloom_commit_sound", move || {
|
|
369
|
+
match $crate::staging::take_sound(staging_handle) {
|
|
370
|
+
Some(sd) => engine().audio.load_sound(sd),
|
|
371
|
+
None => 0.0,
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// bloom_commit_music [source: macos]
|
|
377
|
+
#[no_mangle]
|
|
378
|
+
pub extern "C" fn bloom_commit_music(staging_handle: f64) -> f64 {
|
|
379
|
+
$crate::ffi::guard("bloom_commit_music", move || {
|
|
380
|
+
match $crate::staging::take_sound(staging_handle) {
|
|
381
|
+
Some(sd) => engine().audio.load_music(sd),
|
|
382
|
+
None => 0.0,
|
|
383
|
+
}
|
|
384
|
+
})
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
};
|
|
388
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
//! Sound and music playback control.
|
|
2
|
+
//!
|
|
3
|
+
//! Section of [`define_core_ffi!`](crate::define_core_ffi) — see
|
|
4
|
+
//! `ffi_core/mod.rs` for the architecture and the invoking-crate contract.
|
|
5
|
+
//! Internal: platform crates must invoke `define_core_ffi!()`, never the
|
|
6
|
+
//! section macros directly.
|
|
7
|
+
|
|
8
|
+
#[doc(hidden)]
|
|
9
|
+
#[macro_export]
|
|
10
|
+
macro_rules! __bloom_ffi_audio_ffi {
|
|
11
|
+
() => {
|
|
12
|
+
|
|
13
|
+
// bloom_play_sound [source: macos]
|
|
14
|
+
#[no_mangle]
|
|
15
|
+
pub extern "C" fn bloom_play_sound(handle: f64) {
|
|
16
|
+
$crate::ffi::guard("bloom_play_sound", move || {
|
|
17
|
+
engine().audio.play_sound(handle);
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// bloom_stop_sound [source: macos]
|
|
22
|
+
#[no_mangle]
|
|
23
|
+
pub extern "C" fn bloom_stop_sound(handle: f64) {
|
|
24
|
+
$crate::ffi::guard("bloom_stop_sound", move || {
|
|
25
|
+
engine().audio.stop_sound(handle);
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// bloom_play_sound_3d [source: macos]
|
|
30
|
+
#[no_mangle]
|
|
31
|
+
pub extern "C" fn bloom_play_sound_3d(handle: f64, x: f64, y: f64, z: f64) {
|
|
32
|
+
$crate::ffi::guard("bloom_play_sound_3d", move || {
|
|
33
|
+
engine().audio.play_sound_3d(handle, x as f32, y as f32, z as f32);
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// bloom_play_music [source: macos]
|
|
38
|
+
#[no_mangle]
|
|
39
|
+
pub extern "C" fn bloom_play_music(handle: f64) {
|
|
40
|
+
$crate::ffi::guard("bloom_play_music", move || {
|
|
41
|
+
engine().audio.play_music(handle);
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// bloom_stop_music [source: macos]
|
|
46
|
+
#[no_mangle]
|
|
47
|
+
pub extern "C" fn bloom_stop_music(handle: f64) {
|
|
48
|
+
$crate::ffi::guard("bloom_stop_music", move || {
|
|
49
|
+
engine().audio.stop_music(handle);
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// bloom_is_music_playing [source: macos]
|
|
54
|
+
#[no_mangle]
|
|
55
|
+
pub extern "C" fn bloom_is_music_playing(handle: f64) -> f64 {
|
|
56
|
+
$crate::ffi::guard("bloom_is_music_playing", move || {
|
|
57
|
+
if engine().audio.is_music_playing(handle) { 1.0 } else { 0.0 }
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---- EN-029: buses, reverb send, occlusion low-pass -------------
|
|
62
|
+
//
|
|
63
|
+
// The mixer was master + per-voice gain and nothing else. These three
|
|
64
|
+
// additions are what separate "sounds are playing" from "the space
|
|
65
|
+
// sounds like a place": a bus you can duck, a tail you can send to, and
|
|
66
|
+
// a filter that makes a wall audible.
|
|
67
|
+
|
|
68
|
+
// bloom_set_sound_bus — 0 = SFX, 1 = music, 2 = UI.
|
|
69
|
+
#[no_mangle]
|
|
70
|
+
pub extern "C" fn bloom_set_sound_bus(handle: f64, bus: f64) {
|
|
71
|
+
$crate::ffi::guard("bloom_set_sound_bus", move || {
|
|
72
|
+
engine().audio.set_sound_bus(handle, bus as u8);
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// bloom_set_sound_reverb_send — 0..1.
|
|
77
|
+
#[no_mangle]
|
|
78
|
+
pub extern "C" fn bloom_set_sound_reverb_send(handle: f64, send: f64) {
|
|
79
|
+
$crate::ffi::guard("bloom_set_sound_reverb_send", move || {
|
|
80
|
+
engine().audio.set_sound_reverb_send(handle, send as f32);
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// bloom_set_sound_lowpass — cutoff Hz; 0 = bypass.
|
|
85
|
+
#[no_mangle]
|
|
86
|
+
pub extern "C" fn bloom_set_sound_lowpass(handle: f64, cutoff: f64) {
|
|
87
|
+
$crate::ffi::guard("bloom_set_sound_lowpass", move || {
|
|
88
|
+
engine().audio.set_sound_lowpass(handle, cutoff as f32);
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// bloom_set_bus_gain
|
|
93
|
+
#[no_mangle]
|
|
94
|
+
pub extern "C" fn bloom_set_bus_gain(bus: f64, gain: f64) {
|
|
95
|
+
$crate::ffi::guard("bloom_set_bus_gain", move || {
|
|
96
|
+
engine().audio.set_bus_gain(bus as u8, gain as f32);
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// bloom_duck_bus — momentary attenuation with attack/hold/release.
|
|
101
|
+
#[no_mangle]
|
|
102
|
+
pub extern "C" fn bloom_duck_bus(bus: f64, amount: f64, attack: f64, release: f64, hold: f64) {
|
|
103
|
+
$crate::ffi::guard("bloom_duck_bus", move || {
|
|
104
|
+
engine().audio.duck_bus(
|
|
105
|
+
bus as u8, amount as f32, attack as f32, release as f32, hold as f32);
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// bloom_set_reverb — size / damp / wet, all 0..1. wet = 0 bypasses the
|
|
110
|
+
// whole reverb path, so it costs nothing until a game asks for it.
|
|
111
|
+
#[no_mangle]
|
|
112
|
+
pub extern "C" fn bloom_set_reverb(size: f64, damp: f64, wet: f64) {
|
|
113
|
+
$crate::ffi::guard("bloom_set_reverb", move || {
|
|
114
|
+
engine().audio.set_reverb(size as f32, damp as f32, wet as f32);
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ---- EN-062: live spatial voices ---------------------------------
|
|
119
|
+
//
|
|
120
|
+
// bloom_play_sound_3d is fire-and-forget: it cannot loop and it cannot
|
|
121
|
+
// move. These six calls are the emitter API — a voice id you hold onto
|
|
122
|
+
// and steer. A river you walk along, wind in a treeline, a creature
|
|
123
|
+
// circling closer: all of them are one looping voice plus a per-frame
|
|
124
|
+
// position/volume ride.
|
|
125
|
+
|
|
126
|
+
// bloom_play_sound_3d_ex — returns the voice id (0 = unknown sound).
|
|
127
|
+
// looping != 0 loops until bloom_voice_stop. ref_dist = full-volume
|
|
128
|
+
// range, rolloff = fall-off steepness (1,1 == the classic 1/d),
|
|
129
|
+
// max_dist = cull range (<= 0 = never cull).
|
|
130
|
+
#[no_mangle]
|
|
131
|
+
pub extern "C" fn bloom_play_sound_3d_ex(
|
|
132
|
+
handle: f64, x: f64, y: f64, z: f64,
|
|
133
|
+
looping: f64, ref_dist: f64, max_dist: f64, rolloff: f64,
|
|
134
|
+
) -> f64 {
|
|
135
|
+
$crate::ffi::guard("bloom_play_sound_3d_ex", move || {
|
|
136
|
+
engine().audio.play_sound_3d_ex(
|
|
137
|
+
handle, x as f32, y as f32, z as f32,
|
|
138
|
+
looping != 0.0, ref_dist as f32, max_dist as f32, rolloff as f32)
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// bloom_voice_set_position — move a live voice (doppler falls out of
|
|
143
|
+
// the motion automatically).
|
|
144
|
+
#[no_mangle]
|
|
145
|
+
pub extern "C" fn bloom_voice_set_position(voice: f64, x: f64, y: f64, z: f64) {
|
|
146
|
+
$crate::ffi::guard("bloom_voice_set_position", move || {
|
|
147
|
+
engine().audio.set_voice_position(voice, x as f32, y as f32, z as f32);
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// bloom_voice_stop — click-free: fades over one mix block, then drops.
|
|
152
|
+
#[no_mangle]
|
|
153
|
+
pub extern "C" fn bloom_voice_stop(voice: f64) {
|
|
154
|
+
$crate::ffi::guard("bloom_voice_stop", move || {
|
|
155
|
+
engine().audio.stop_voice(voice);
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// bloom_voice_set_volume
|
|
160
|
+
#[no_mangle]
|
|
161
|
+
pub extern "C" fn bloom_voice_set_volume(voice: f64, volume: f64) {
|
|
162
|
+
$crate::ffi::guard("bloom_voice_set_volume", move || {
|
|
163
|
+
engine().audio.set_voice_volume(voice, volume as f32);
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// bloom_voice_set_pitch — 0.25..4 playback-rate multiplier.
|
|
168
|
+
#[no_mangle]
|
|
169
|
+
pub extern "C" fn bloom_voice_set_pitch(voice: f64, pitch: f64) {
|
|
170
|
+
$crate::ffi::guard("bloom_voice_set_pitch", move || {
|
|
171
|
+
engine().audio.set_voice_pitch(voice, pitch as f32);
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// bloom_voice_set_lowpass — per-VOICE occlusion (Hz; 0 = bypass).
|
|
176
|
+
#[no_mangle]
|
|
177
|
+
pub extern "C" fn bloom_voice_set_lowpass(voice: f64, cutoff: f64) {
|
|
178
|
+
$crate::ffi::guard("bloom_voice_set_lowpass", move || {
|
|
179
|
+
engine().audio.set_voice_lowpass(voice, cutoff as f32);
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
};
|
|
184
|
+
}
|