@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,577 @@
|
|
|
1
|
+
//! Game loop, timing, frame callbacks, profiler, window-state getters.
|
|
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_game_loop {
|
|
11
|
+
() => {
|
|
12
|
+
|
|
13
|
+
// --- game loop hooks --------------------------------------------
|
|
14
|
+
|
|
15
|
+
// No-op on native: the TypeScript runGame() helper drives the
|
|
16
|
+
// loop. (On web, the JS glue hooks requestAnimationFrame.)
|
|
17
|
+
#[no_mangle]
|
|
18
|
+
pub extern "C" fn bloom_run_game(_callback: extern "C" fn(f64)) {}
|
|
19
|
+
|
|
20
|
+
#[no_mangle]
|
|
21
|
+
pub extern "C" fn bloom_register_frame_callback(priority: f64, callback: extern "C" fn(f64)) -> f64 {
|
|
22
|
+
$crate::ffi::guard("bloom_register_frame_callback", move || {
|
|
23
|
+
engine().frame_callbacks.register(priority as i32, callback) as f64
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// bloom_get_delta_time [source: macos]
|
|
28
|
+
#[no_mangle]
|
|
29
|
+
pub extern "C" fn bloom_get_delta_time() -> f64 {
|
|
30
|
+
$crate::ffi::guard("bloom_get_delta_time", move || {
|
|
31
|
+
engine().delta_time
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// bloom_get_fps [source: macos]
|
|
36
|
+
#[no_mangle]
|
|
37
|
+
pub extern "C" fn bloom_get_fps() -> f64 {
|
|
38
|
+
$crate::ffi::guard("bloom_get_fps", move || {
|
|
39
|
+
engine().get_fps()
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// bloom_get_screen_width [source: macos]
|
|
44
|
+
#[no_mangle]
|
|
45
|
+
pub extern "C" fn bloom_get_screen_width() -> f64 {
|
|
46
|
+
$crate::ffi::guard("bloom_get_screen_width", move || {
|
|
47
|
+
engine().screen_width()
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// bloom_get_screen_height [source: macos]
|
|
52
|
+
#[no_mangle]
|
|
53
|
+
pub extern "C" fn bloom_get_screen_height() -> f64 {
|
|
54
|
+
$crate::ffi::guard("bloom_get_screen_height", move || {
|
|
55
|
+
engine().screen_height()
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// bloom_create_instance_buffer [source: macos]
|
|
60
|
+
#[no_mangle]
|
|
61
|
+
pub extern "C" fn bloom_create_instance_buffer(
|
|
62
|
+
data_ptr: *const f64, instance_count: f64,
|
|
63
|
+
) -> f64 {
|
|
64
|
+
$crate::ffi::guard("bloom_create_instance_buffer", move || {
|
|
65
|
+
if data_ptr.is_null() || instance_count <= 0.0 { return 0.0; }
|
|
66
|
+
let count = instance_count as u32;
|
|
67
|
+
let slot_count = (count as usize) * 9;
|
|
68
|
+
let raw_f64 = unsafe { std::slice::from_raw_parts(data_ptr, slot_count) };
|
|
69
|
+
let raw_f32: Vec<f32> = raw_f64.iter().map(|&v| v as f32).collect();
|
|
70
|
+
engine().renderer.create_instance_buffer(&raw_f32, count) as f64
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// bloom_create_instance_buffer_scratch — instance data arrives via
|
|
75
|
+
// the mesh scratch (bloom_mesh_scratch_reset + push_f32 × 9·N)
|
|
76
|
+
// instead of the i64-array pointer above, which Perry 0.5.x rejects
|
|
77
|
+
// ("Expected safe integer for native i64 parameter"). Same idiom as
|
|
78
|
+
// bloom_create_mesh_scratch. 9 f32 slots per instance.
|
|
79
|
+
#[no_mangle]
|
|
80
|
+
pub extern "C" fn bloom_create_instance_buffer_scratch(instance_count: f64) -> f64 {
|
|
81
|
+
$crate::ffi::guard("bloom_create_instance_buffer_scratch", move || {
|
|
82
|
+
let mut eng = engine();
|
|
83
|
+
let count = instance_count as u32;
|
|
84
|
+
let need = (count as usize) * 9;
|
|
85
|
+
if count == 0 || eng.models.scratch_f32.len() < need { return 0.0; }
|
|
86
|
+
let data: Vec<f32> = eng.models.scratch_f32[..need].to_vec();
|
|
87
|
+
eng.models.mesh_scratch_reset();
|
|
88
|
+
eng.renderer.create_instance_buffer(&data, count) as f64
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// bloom_destroy_instance_buffer [source: macos]
|
|
93
|
+
#[no_mangle]
|
|
94
|
+
pub extern "C" fn bloom_destroy_instance_buffer(handle: f64) {
|
|
95
|
+
$crate::ffi::guard("bloom_destroy_instance_buffer", move || {
|
|
96
|
+
engine().renderer.destroy_instance_buffer(handle as u32);
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// bloom_create_planar_reflection [source: macos]
|
|
101
|
+
#[no_mangle]
|
|
102
|
+
pub extern "C" fn bloom_create_planar_reflection(
|
|
103
|
+
plane_y: f64, nx: f64, ny: f64, nz: f64, resolution: f64,
|
|
104
|
+
) -> f64 {
|
|
105
|
+
$crate::ffi::guard("bloom_create_planar_reflection", move || {
|
|
106
|
+
engine().renderer.create_planar_reflection(
|
|
107
|
+
plane_y as f32,
|
|
108
|
+
[nx as f32, ny as f32, nz as f32],
|
|
109
|
+
resolution as u32,
|
|
110
|
+
) as f64
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// bloom_create_texture_array [source: macos]
|
|
115
|
+
#[no_mangle]
|
|
116
|
+
pub extern "C" fn bloom_create_texture_array(
|
|
117
|
+
data_ptr: *const u8,
|
|
118
|
+
data_len: f64,
|
|
119
|
+
width: f64,
|
|
120
|
+
height: f64,
|
|
121
|
+
layer_count: f64,
|
|
122
|
+
) -> f64 {
|
|
123
|
+
$crate::ffi::guard("bloom_create_texture_array", move || {
|
|
124
|
+
// EN-014 V2 — V1 stays callable; forwards to _ex with default
|
|
125
|
+
// format = sRGB (0) and mip_levels = 1 (no mips).
|
|
126
|
+
bloom_create_texture_array_ex(data_ptr, data_len, width, height, layer_count, 0.0, 1.0)
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// bloom_create_texture_array_ex [source: macos]
|
|
131
|
+
#[no_mangle]
|
|
132
|
+
pub extern "C" fn bloom_create_texture_array_ex(
|
|
133
|
+
data_ptr: *const u8,
|
|
134
|
+
data_len: f64,
|
|
135
|
+
width: f64,
|
|
136
|
+
height: f64,
|
|
137
|
+
layer_count: f64,
|
|
138
|
+
format: f64,
|
|
139
|
+
mip_levels: f64,
|
|
140
|
+
) -> f64 {
|
|
141
|
+
$crate::ffi::guard("bloom_create_texture_array_ex", move || {
|
|
142
|
+
if data_ptr.is_null() || data_len <= 0.0 { return 0.0; }
|
|
143
|
+
let w = width as u32;
|
|
144
|
+
let h = height as u32;
|
|
145
|
+
if w == 0 || h == 0 { return 0.0; }
|
|
146
|
+
let layers_count = (layer_count as u32)
|
|
147
|
+
.min($crate::renderer::material_system::MAX_TEXTURE_ARRAY_LAYERS);
|
|
148
|
+
if layers_count == 0 { return 0.0; }
|
|
149
|
+
let layer_size = (w as usize) * (h as usize) * 4;
|
|
150
|
+
let total_bytes = (data_len as usize)
|
|
151
|
+
.min(layers_count as usize * layer_size);
|
|
152
|
+
let bytes = unsafe { std::slice::from_raw_parts(data_ptr, total_bytes) };
|
|
153
|
+
let mut layers: Vec<(&[u8], u32, u32)> = Vec::with_capacity(layers_count as usize);
|
|
154
|
+
for i in 0..(layers_count as usize) {
|
|
155
|
+
let start = i * layer_size;
|
|
156
|
+
let end = start + layer_size;
|
|
157
|
+
if end > bytes.len() { break; }
|
|
158
|
+
layers.push((&bytes[start..end], w, h));
|
|
159
|
+
}
|
|
160
|
+
engine().renderer.create_texture_array_ex(&layers, format as u32, mip_levels as u32) as f64
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// bloom_create_texture_array_scratch [EN-049]
|
|
165
|
+
//
|
|
166
|
+
// The byte-array path above takes a `*const u8`, which the manifest has
|
|
167
|
+
// to declare as `i64` — and Perry cannot put a `number[]` in an i64
|
|
168
|
+
// param (it raises "Expected safe integer for native i64 parameter").
|
|
169
|
+
// So from Perry, `bloom_create_texture_array_ex` is only callable with a
|
|
170
|
+
// pointer nobody has. Every real caller ended up on the from_files path,
|
|
171
|
+
// which is fine for ART and useless for DATA: a splat map is computed at
|
|
172
|
+
// load from the world file, and there is no file to name.
|
|
173
|
+
//
|
|
174
|
+
// Same fix the mesh path already uses (`bloom_create_mesh_scratch`):
|
|
175
|
+
// push the payload through the scratch buffer, then call this with the
|
|
176
|
+
// dimensions. Texels are pushed as PACKED u32 (one per texel, RGBA in
|
|
177
|
+
// little-endian byte order = R | G<<8 | B<<16 | A<<24), so a 128² splat
|
|
178
|
+
// is 16,384 pushes rather than 65,536.
|
|
179
|
+
#[no_mangle]
|
|
180
|
+
pub extern "C" fn bloom_create_texture_array_scratch(
|
|
181
|
+
width: f64,
|
|
182
|
+
height: f64,
|
|
183
|
+
layer_count: f64,
|
|
184
|
+
format: f64,
|
|
185
|
+
mip_levels: f64,
|
|
186
|
+
) -> f64 {
|
|
187
|
+
$crate::ffi::guard("bloom_create_texture_array_scratch", move || {
|
|
188
|
+
let w = width as u32;
|
|
189
|
+
let h = height as u32;
|
|
190
|
+
if w == 0 || h == 0 { return 0.0; }
|
|
191
|
+
let layers_count = (layer_count as u32)
|
|
192
|
+
.min($crate::renderer::material_system::MAX_TEXTURE_ARRAY_LAYERS);
|
|
193
|
+
if layers_count == 0 { return 0.0; }
|
|
194
|
+
|
|
195
|
+
let texels = (w as usize) * (h as usize) * (layers_count as usize);
|
|
196
|
+
// Scoped so the scratch borrow ends before the renderer borrow.
|
|
197
|
+
let bytes: Vec<u8> = {
|
|
198
|
+
let eng = engine();
|
|
199
|
+
if eng.models.scratch_u32.len() < texels {
|
|
200
|
+
// Short buffer: refuse rather than upload uninitialised
|
|
201
|
+
// memory as a texture. Silent garbage here surfaces as a
|
|
202
|
+
// terrain painted in noise, three layers from the cause.
|
|
203
|
+
return 0.0;
|
|
204
|
+
}
|
|
205
|
+
eng.models.scratch_u32[..texels]
|
|
206
|
+
.iter()
|
|
207
|
+
.flat_map(|p| p.to_le_bytes())
|
|
208
|
+
.collect()
|
|
209
|
+
};
|
|
210
|
+
let layer_size = (w as usize) * (h as usize) * 4;
|
|
211
|
+
let mut layers: Vec<(&[u8], u32, u32)> = Vec::with_capacity(layers_count as usize);
|
|
212
|
+
for i in 0..(layers_count as usize) {
|
|
213
|
+
let start = i * layer_size;
|
|
214
|
+
let end = start + layer_size;
|
|
215
|
+
if end > bytes.len() { break; }
|
|
216
|
+
layers.push((&bytes[start..end], w, h));
|
|
217
|
+
}
|
|
218
|
+
engine().renderer.create_texture_array_ex(&layers, format as u32, mip_levels as u32) as f64
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// bloom_create_texture_array_from_files [EN-014 V3]
|
|
223
|
+
//
|
|
224
|
+
// The byte-array path above asks the game to marshal every texel across
|
|
225
|
+
// the FFI — a 6-layer 256² array is 1.5 M numbers, which is exactly the
|
|
226
|
+
// shape of call Perry's array bridge is worst at. Decoding on this side
|
|
227
|
+
// from a path list is both faster and the API every actual consumer
|
|
228
|
+
// wants (VFX atlas layers, splat-terrain layers).
|
|
229
|
+
//
|
|
230
|
+
// `paths` is comma-separated, and is parsed HERE, at load time — never
|
|
231
|
+
// on a per-frame path (perry-quirks #5). Layers must share dimensions;
|
|
232
|
+
// the first file's size wins and any mismatch is skipped with a warning.
|
|
233
|
+
#[no_mangle]
|
|
234
|
+
pub extern "C" fn bloom_create_texture_array_from_files(
|
|
235
|
+
paths_ptr: *const u8, format: f64, mip_levels: f64,
|
|
236
|
+
) -> f64 {
|
|
237
|
+
$crate::ffi::guard("bloom_create_texture_array_from_files", move || {
|
|
238
|
+
let list = $crate::string_header::str_from_header(paths_ptr);
|
|
239
|
+
let mut decoded: Vec<(Vec<u8>, u32, u32)> = Vec::new();
|
|
240
|
+
for p in list.split(',') {
|
|
241
|
+
let p = p.trim();
|
|
242
|
+
if p.is_empty() { continue; }
|
|
243
|
+
let resolved = bloom_resolve_asset_path(p);
|
|
244
|
+
match image::open(resolved.as_ref()) {
|
|
245
|
+
Ok(img) => {
|
|
246
|
+
let rgba = img.to_rgba8();
|
|
247
|
+
let (w, h) = rgba.dimensions();
|
|
248
|
+
decoded.push((rgba.into_raw(), w, h));
|
|
249
|
+
}
|
|
250
|
+
Err(e) => {
|
|
251
|
+
eprintln!("[texarray] failed to load {}: {}", p, e);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if decoded.is_empty() { return 0.0; }
|
|
256
|
+
let (w, h) = (decoded[0].1, decoded[0].2);
|
|
257
|
+
let mut layers: Vec<(&[u8], u32, u32)> = Vec::with_capacity(decoded.len());
|
|
258
|
+
for (bytes, lw, lh) in decoded.iter() {
|
|
259
|
+
if *lw != w || *lh != h {
|
|
260
|
+
eprintln!("[texarray] layer size {}x{} != {}x{}; skipped", lw, lh, w, h);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
layers.push((bytes.as_slice(), w, h));
|
|
264
|
+
}
|
|
265
|
+
if layers.is_empty() { return 0.0; }
|
|
266
|
+
engine().renderer.create_texture_array_ex(
|
|
267
|
+
&layers, format as u32, mip_levels as u32) as f64
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// bloom_clear_post_pass [source: macos]
|
|
272
|
+
#[no_mangle]
|
|
273
|
+
pub extern "C" fn bloom_clear_post_pass() {
|
|
274
|
+
$crate::ffi::guard("bloom_clear_post_pass", move || {
|
|
275
|
+
engine().renderer.clear_post_pass();
|
|
276
|
+
})
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// bloom_add_post_pass [source: macos]
|
|
280
|
+
#[no_mangle]
|
|
281
|
+
pub extern "C" fn bloom_add_post_pass(source_ptr: *const u8) -> f64 {
|
|
282
|
+
$crate::ffi::guard("bloom_add_post_pass", move || {
|
|
283
|
+
let source = $crate::string_header::str_from_header(source_ptr);
|
|
284
|
+
match engine().renderer.add_post_pass(source) {
|
|
285
|
+
Ok(h) => h as f64,
|
|
286
|
+
Err(e) => { eprintln!("[post_pass] compile failed: {:?}", e); 0.0 }
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// bloom_clear_all_post_passes [source: macos]
|
|
292
|
+
#[no_mangle]
|
|
293
|
+
pub extern "C" fn bloom_clear_all_post_passes() {
|
|
294
|
+
$crate::ffi::guard("bloom_clear_all_post_passes", move || {
|
|
295
|
+
engine().renderer.clear_all_post_passes();
|
|
296
|
+
})
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// bloom_get_render_scale [source: macos]
|
|
300
|
+
#[no_mangle]
|
|
301
|
+
pub extern "C" fn bloom_get_render_scale() -> f64 {
|
|
302
|
+
$crate::ffi::guard("bloom_get_render_scale", move || {
|
|
303
|
+
engine().renderer.render_scale() as f64
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// bloom_get_physical_width [source: macos]
|
|
308
|
+
#[no_mangle]
|
|
309
|
+
pub extern "C" fn bloom_get_physical_width() -> f64 {
|
|
310
|
+
$crate::ffi::guard("bloom_get_physical_width", move || {
|
|
311
|
+
engine().renderer.physical_width() as f64
|
|
312
|
+
})
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// bloom_get_physical_height [source: macos]
|
|
316
|
+
#[no_mangle]
|
|
317
|
+
pub extern "C" fn bloom_get_physical_height() -> f64 {
|
|
318
|
+
$crate::ffi::guard("bloom_get_physical_height", move || {
|
|
319
|
+
engine().renderer.physical_height() as f64
|
|
320
|
+
})
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// bloom_get_profiler_frame_cpu_us [source: macos]
|
|
324
|
+
#[no_mangle]
|
|
325
|
+
pub extern "C" fn bloom_get_profiler_frame_cpu_us() -> f64 {
|
|
326
|
+
$crate::ffi::guard("bloom_get_profiler_frame_cpu_us", move || {
|
|
327
|
+
engine().profiler.avg_frame_cpu_us()
|
|
328
|
+
})
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// bloom_get_profiler_frame_gpu_us [source: macos]
|
|
332
|
+
#[no_mangle]
|
|
333
|
+
pub extern "C" fn bloom_get_profiler_frame_gpu_us() -> f64 {
|
|
334
|
+
$crate::ffi::guard("bloom_get_profiler_frame_gpu_us", move || {
|
|
335
|
+
engine().profiler.avg_frame_gpu_us()
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// bloom_print_profiler_summary [source: macos]
|
|
340
|
+
#[no_mangle]
|
|
341
|
+
pub extern "C" fn bloom_print_profiler_summary() {
|
|
342
|
+
$crate::ffi::guard("bloom_print_profiler_summary", move || {
|
|
343
|
+
print!("{}", engine().profiler.summary());
|
|
344
|
+
})
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// bloom_inject_key_down [source: macos]
|
|
348
|
+
#[no_mangle]
|
|
349
|
+
pub extern "C" fn bloom_inject_key_down(key: f64) {
|
|
350
|
+
$crate::ffi::guard("bloom_inject_key_down", move || {
|
|
351
|
+
engine().input.inject_key_down(key as usize);
|
|
352
|
+
})
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// bloom_inject_key_up [source: macos]
|
|
356
|
+
#[no_mangle]
|
|
357
|
+
pub extern "C" fn bloom_inject_key_up(key: f64) {
|
|
358
|
+
$crate::ffi::guard("bloom_inject_key_up", move || {
|
|
359
|
+
engine().input.inject_key_up(key as usize);
|
|
360
|
+
})
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// bloom_inject_gamepad_axis [source: macos]
|
|
364
|
+
#[no_mangle]
|
|
365
|
+
pub extern "C" fn bloom_inject_gamepad_axis(axis: f64, value: f64) {
|
|
366
|
+
$crate::ffi::guard("bloom_inject_gamepad_axis", move || {
|
|
367
|
+
engine().input.set_gamepad_axis(axis as usize, value as f32);
|
|
368
|
+
})
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// bloom_inject_gamepad_button_down [source: macos]
|
|
372
|
+
#[no_mangle]
|
|
373
|
+
pub extern "C" fn bloom_inject_gamepad_button_down(button: f64) {
|
|
374
|
+
$crate::ffi::guard("bloom_inject_gamepad_button_down", move || {
|
|
375
|
+
engine().input.set_gamepad_button_down(button as usize);
|
|
376
|
+
})
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// bloom_inject_gamepad_button_up [source: macos]
|
|
380
|
+
#[no_mangle]
|
|
381
|
+
pub extern "C" fn bloom_inject_gamepad_button_up(button: f64) {
|
|
382
|
+
$crate::ffi::guard("bloom_inject_gamepad_button_up", move || {
|
|
383
|
+
engine().input.set_gamepad_button_up(button as usize);
|
|
384
|
+
})
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// bloom_is_any_input_pressed [source: macos]
|
|
388
|
+
#[no_mangle]
|
|
389
|
+
pub extern "C" fn bloom_is_any_input_pressed() -> f64 {
|
|
390
|
+
$crate::ffi::guard("bloom_is_any_input_pressed", move || {
|
|
391
|
+
if engine().input.is_any_input_pressed() { 1.0 } else { 0.0 }
|
|
392
|
+
})
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// bloom_update_music_stream [source: macos]
|
|
396
|
+
#[no_mangle]
|
|
397
|
+
pub extern "C" fn bloom_update_music_stream(handle: f64) {
|
|
398
|
+
$crate::ffi::guard("bloom_update_music_stream", move || {
|
|
399
|
+
engine().audio.update_music_stream(handle);
|
|
400
|
+
})
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// bloom_get_time [source: macos]
|
|
404
|
+
#[no_mangle]
|
|
405
|
+
pub extern "C" fn bloom_get_time() -> f64 {
|
|
406
|
+
$crate::ffi::guard("bloom_get_time", move || {
|
|
407
|
+
engine().get_time()
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// bloom_unregister_frame_callback [source: macos]
|
|
412
|
+
#[no_mangle]
|
|
413
|
+
pub extern "C" fn bloom_unregister_frame_callback(id: f64) {
|
|
414
|
+
$crate::ffi::guard("bloom_unregister_frame_callback", move || {
|
|
415
|
+
engine().frame_callbacks.unregister(id as u64);
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// bloom_get_render_texture_texture [source: macos]
|
|
420
|
+
#[no_mangle]
|
|
421
|
+
pub extern "C" fn bloom_get_render_texture_texture(handle: f64) -> f64 {
|
|
422
|
+
$crate::ffi::guard("bloom_get_render_texture_texture", move || {
|
|
423
|
+
engine().textures.get_render_texture_texture(handle)
|
|
424
|
+
})
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// bloom_postfx_set_selected [source: macos]
|
|
428
|
+
#[no_mangle]
|
|
429
|
+
pub extern "C" fn bloom_postfx_set_selected(handle: f64) {
|
|
430
|
+
$crate::ffi::guard("bloom_postfx_set_selected", move || {
|
|
431
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
432
|
+
if handle == 0.0 {
|
|
433
|
+
pfx.set_selected(Vec::new());
|
|
434
|
+
} else {
|
|
435
|
+
pfx.set_selected(vec![handle]);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
})
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// bloom_postfx_set_hovered [source: macos]
|
|
442
|
+
#[no_mangle]
|
|
443
|
+
pub extern "C" fn bloom_postfx_set_hovered(handle: f64) {
|
|
444
|
+
$crate::ffi::guard("bloom_postfx_set_hovered", move || {
|
|
445
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
446
|
+
pfx.set_hovered(handle);
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// bloom_postfx_set_outline_color [source: macos]
|
|
452
|
+
#[no_mangle]
|
|
453
|
+
pub extern "C" fn bloom_postfx_set_outline_color(r: f64, g: f64, b: f64, a: f64) {
|
|
454
|
+
$crate::ffi::guard("bloom_postfx_set_outline_color", move || {
|
|
455
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
456
|
+
pfx.outline_params.color_selected = [r as f32, g as f32, b as f32, a as f32];
|
|
457
|
+
}
|
|
458
|
+
})
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// bloom_postfx_set_outline_thickness [source: macos]
|
|
462
|
+
#[no_mangle]
|
|
463
|
+
pub extern "C" fn bloom_postfx_set_outline_thickness(thickness: f64) {
|
|
464
|
+
$crate::ffi::guard("bloom_postfx_set_outline_thickness", move || {
|
|
465
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
466
|
+
pfx.outline_params.thickness[0] = thickness as f32;
|
|
467
|
+
}
|
|
468
|
+
})
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// bloom_profiler_frame_history [source: macos]
|
|
472
|
+
#[no_mangle]
|
|
473
|
+
pub extern "C" fn bloom_profiler_frame_history() -> *const u8 {
|
|
474
|
+
$crate::ffi::guard("bloom_profiler_frame_history", move || {
|
|
475
|
+
let hist = engine().profiler.frame_history();
|
|
476
|
+
let mut s = String::with_capacity(hist.len() * 24);
|
|
477
|
+
for (cpu, gpu) in &hist {
|
|
478
|
+
s.push_str(&format!("{:.2}|{:.2}\n", cpu, gpu));
|
|
479
|
+
}
|
|
480
|
+
$crate::string_header::alloc_perry_string(&s)
|
|
481
|
+
})
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// bloom_profiler_overlay_text [source: macos]
|
|
485
|
+
#[no_mangle]
|
|
486
|
+
pub extern "C" fn bloom_profiler_overlay_text() -> *const u8 {
|
|
487
|
+
$crate::ffi::guard("bloom_profiler_overlay_text", move || {
|
|
488
|
+
let snap = engine().profiler.snapshot();
|
|
489
|
+
let mut s = String::with_capacity(snap.len() * 48);
|
|
490
|
+
for (label, cpu, gpu) in &snap {
|
|
491
|
+
s.push_str(label);
|
|
492
|
+
s.push('|');
|
|
493
|
+
s.push_str(&format!("{:.2}", cpu));
|
|
494
|
+
s.push('|');
|
|
495
|
+
match gpu {
|
|
496
|
+
Some(g) => s.push_str(&format!("{:.2}", g)),
|
|
497
|
+
None => s.push_str("-1"),
|
|
498
|
+
}
|
|
499
|
+
s.push('\n');
|
|
500
|
+
}
|
|
501
|
+
$crate::string_header::alloc_perry_string(&s)
|
|
502
|
+
})
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// EN-020 — numeric profiler ABI. The packed-text FFIs above stay
|
|
506
|
+
// for back-compat, but Perry 0.5.x's split()/parseFloat() overread
|
|
507
|
+
// their own slice allocations, so per-frame consumers must use
|
|
508
|
+
// these instead: f64s cross the FFI clean and the label is only
|
|
509
|
+
// ever drawn, never parsed. Row/hist indices address the same
|
|
510
|
+
// snapshot the text FFIs serialize; rows are few (≤ MAX_GPU_PAIRS)
|
|
511
|
+
// so the per-call snapshot() is negligible overlay-only cost.
|
|
512
|
+
|
|
513
|
+
// bloom_profiler_row_count [source: windows]
|
|
514
|
+
#[no_mangle]
|
|
515
|
+
pub extern "C" fn bloom_profiler_row_count() -> f64 {
|
|
516
|
+
$crate::ffi::guard("bloom_profiler_row_count", move || {
|
|
517
|
+
engine().profiler.snapshot().len() as f64
|
|
518
|
+
})
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// bloom_profiler_row_label [source: windows]
|
|
522
|
+
#[no_mangle]
|
|
523
|
+
pub extern "C" fn bloom_profiler_row_label(i: f64) -> *const u8 {
|
|
524
|
+
$crate::ffi::guard("bloom_profiler_row_label", move || {
|
|
525
|
+
let snap = engine().profiler.snapshot();
|
|
526
|
+
match snap.get(i as usize) {
|
|
527
|
+
Some((label, _, _)) => $crate::string_header::alloc_perry_string(label),
|
|
528
|
+
None => $crate::string_header::alloc_perry_string(""),
|
|
529
|
+
}
|
|
530
|
+
})
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// bloom_profiler_row_cpu_us [source: windows]
|
|
534
|
+
#[no_mangle]
|
|
535
|
+
pub extern "C" fn bloom_profiler_row_cpu_us(i: f64) -> f64 {
|
|
536
|
+
$crate::ffi::guard("bloom_profiler_row_cpu_us", move || {
|
|
537
|
+
engine().profiler.snapshot().get(i as usize).map(|r| r.1).unwrap_or(0.0)
|
|
538
|
+
})
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// bloom_profiler_row_gpu_us [source: windows]
|
|
542
|
+
#[no_mangle]
|
|
543
|
+
pub extern "C" fn bloom_profiler_row_gpu_us(i: f64) -> f64 {
|
|
544
|
+
$crate::ffi::guard("bloom_profiler_row_gpu_us", move || {
|
|
545
|
+
match engine().profiler.snapshot().get(i as usize) {
|
|
546
|
+
Some((_, _, Some(g))) => *g,
|
|
547
|
+
_ => -1.0,
|
|
548
|
+
}
|
|
549
|
+
})
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// bloom_profiler_hist_count [source: windows]
|
|
553
|
+
#[no_mangle]
|
|
554
|
+
pub extern "C" fn bloom_profiler_hist_count() -> f64 {
|
|
555
|
+
$crate::ffi::guard("bloom_profiler_hist_count", move || {
|
|
556
|
+
engine().profiler.frame_history().len() as f64
|
|
557
|
+
})
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// bloom_profiler_hist_cpu_us [source: windows]
|
|
561
|
+
#[no_mangle]
|
|
562
|
+
pub extern "C" fn bloom_profiler_hist_cpu_us(i: f64) -> f64 {
|
|
563
|
+
$crate::ffi::guard("bloom_profiler_hist_cpu_us", move || {
|
|
564
|
+
engine().profiler.frame_history().get(i as usize).map(|h| h.0).unwrap_or(0.0)
|
|
565
|
+
})
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// bloom_profiler_hist_gpu_us [source: windows]
|
|
569
|
+
#[no_mangle]
|
|
570
|
+
pub extern "C" fn bloom_profiler_hist_gpu_us(i: f64) -> f64 {
|
|
571
|
+
$crate::ffi::guard("bloom_profiler_hist_gpu_us", move || {
|
|
572
|
+
engine().profiler.frame_history().get(i as usize).map(|h| h.1).unwrap_or(0.0)
|
|
573
|
+
})
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
};
|
|
577
|
+
}
|