@bloomengine/engine 0.3.1 → 0.3.3

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.
Files changed (65) hide show
  1. package/README.md +33 -11
  2. package/native/linux/Cargo.lock +1571 -12
  3. package/native/linux/Cargo.toml +3 -0
  4. package/native/linux/src/lib.rs +745 -40
  5. package/native/macos/src/lib.rs +30 -118
  6. package/native/shared/build.rs +32 -4
  7. package/native/shared/src/postfx.rs +16 -10
  8. package/native/shared/src/renderer/formats.rs +1 -7
  9. package/native/shared/src/renderer/impulse_field.rs +2 -1
  10. package/native/shared/src/renderer/material_system.rs +15 -3
  11. package/native/shared/src/renderer/shaders.rs +7 -1
  12. package/native/shared/src/renderer/transient.rs +12 -12
  13. package/native/shared/src/string_header.rs +32 -0
  14. package/native/third_party/JoltPhysics/Build/Android/PerformanceTest/build.gradle +51 -0
  15. package/native/third_party/JoltPhysics/Build/Android/PerformanceTest/src/main/AndroidManifest.xml +20 -0
  16. package/native/third_party/JoltPhysics/Build/Android/PerformanceTest/src/main/cpp/CMakeLists.txt +20 -0
  17. package/native/third_party/JoltPhysics/Build/Android/UnitTests/build.gradle +51 -0
  18. package/native/third_party/JoltPhysics/Build/Android/UnitTests/src/main/AndroidManifest.xml +20 -0
  19. package/native/third_party/JoltPhysics/Build/Android/UnitTests/src/main/cpp/CMakeLists.txt +20 -0
  20. package/native/third_party/JoltPhysics/Build/Android/build.gradle +17 -0
  21. package/native/third_party/JoltPhysics/Build/Android/gradle/wrapper/gradle-wrapper.jar +0 -0
  22. package/native/third_party/JoltPhysics/Build/Android/gradle/wrapper/gradle-wrapper.properties +5 -0
  23. package/native/third_party/JoltPhysics/Build/Android/gradle.properties +21 -0
  24. package/native/third_party/JoltPhysics/Build/Android/gradlew +185 -0
  25. package/native/third_party/JoltPhysics/Build/Android/gradlew.bat +89 -0
  26. package/native/third_party/JoltPhysics/Build/Android/settings.gradle +10 -0
  27. package/native/third_party/JoltPhysics/Build/CMakeLists.txt +449 -0
  28. package/native/third_party/JoltPhysics/Build/README.md +250 -0
  29. package/native/third_party/JoltPhysics/Build/cmake_linux_clang_gcc.sh +28 -0
  30. package/native/third_party/JoltPhysics/Build/cmake_linux_emscripten.sh +19 -0
  31. package/native/third_party/JoltPhysics/Build/cmake_linux_mingw.sh +19 -0
  32. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl.bat +3 -0
  33. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_32bit.bat +3 -0
  34. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_arm.bat +3 -0
  35. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_arm_32bit.bat +4 -0
  36. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_cross_platform_deterministic.bat +3 -0
  37. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_double.bat +3 -0
  38. package/native/third_party/JoltPhysics/Build/cmake_vs2022_cl_no_object_stream.bat +3 -0
  39. package/native/third_party/JoltPhysics/Build/cmake_vs2022_clang.bat +10 -0
  40. package/native/third_party/JoltPhysics/Build/cmake_vs2022_clang_cross_platform_deterministic.bat +10 -0
  41. package/native/third_party/JoltPhysics/Build/cmake_vs2022_clang_double.bat +10 -0
  42. package/native/third_party/JoltPhysics/Build/cmake_vs2022_uwp.bat +5 -0
  43. package/native/third_party/JoltPhysics/Build/cmake_vs2022_uwp_arm.bat +5 -0
  44. package/native/third_party/JoltPhysics/Build/cmake_vs2026_cl.bat +3 -0
  45. package/native/third_party/JoltPhysics/Build/cmake_vs2026_cl_cross_platform_deterministic.bat +3 -0
  46. package/native/third_party/JoltPhysics/Build/cmake_vs2026_cl_double.bat +3 -0
  47. package/native/third_party/JoltPhysics/Build/cmake_vs2026_clang.bat +10 -0
  48. package/native/third_party/JoltPhysics/Build/cmake_vs2026_clang_cross_platform_deterministic.bat +10 -0
  49. package/native/third_party/JoltPhysics/Build/cmake_vs2026_clang_double.bat +10 -0
  50. package/native/third_party/JoltPhysics/Build/cmake_windows_mingw.sh +19 -0
  51. package/native/third_party/JoltPhysics/Build/cmake_xcode_ios.sh +4 -0
  52. package/native/third_party/JoltPhysics/Build/cmake_xcode_macos.sh +4 -0
  53. package/native/third_party/JoltPhysics/Build/iOS/JoltViewerInfo.plist +34 -0
  54. package/native/third_party/JoltPhysics/Build/iOS/SamplesInfo.plist +34 -0
  55. package/native/third_party/JoltPhysics/Build/iOS/UnitTestsInfo.plist +34 -0
  56. package/native/third_party/JoltPhysics/Build/macOS/icon.icns +0 -0
  57. package/native/third_party/JoltPhysics/Build/macos_install_vulkan_sdk.sh +13 -0
  58. package/native/third_party/JoltPhysics/Build/ubuntu24_install_vulkan_sdk.sh +4 -0
  59. package/native/third_party/bloom_jolt/CMakeLists.txt +14 -5
  60. package/native/windows/Cargo.lock +1 -0
  61. package/native/windows/Cargo.toml +10 -1
  62. package/native/windows/src/lib.rs +226 -18
  63. package/package.json +9 -7
  64. package/src/core/colors.ts +34 -27
  65. package/src/core/index.ts +1 -2
@@ -8,11 +8,18 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
8
8
 
9
9
  # ---------------------------------------------------------------------------
10
10
  # JoltPhysics build options.
11
- # Matches the "Distribution" flavour: no asserts, no profile, no debug renderer,
12
- # interprocedural optimisation on. We keep object stream off — we don't use
13
- # Jolt's scene serialisation (Bloom handles save/load itself).
11
+ # Matches the "Distribution" flavour: no asserts, no profile, no debug renderer.
12
+ # We keep object stream off — we don't use Jolt's scene serialisation (Bloom
13
+ # handles save/load itself).
14
+ #
15
+ # IPO is OFF because Rust's link step on Linux/GCC routes through rust-lld,
16
+ # which doesn't load gcc's lto-wrapper plugin. With IPO on, libJolt.a's archive
17
+ # members are GIMPLE bitcode and rust-lld leaves their implementations
18
+ # unresolved (undefined-symbol errors on JPH::Free, BodyManager locks, vtables,
19
+ # etc — see issue #44). Jolt is heavily inlined via its precompiled header
20
+ # already, so the perf delta from skipping LTO on the static archive is small.
14
21
  # ---------------------------------------------------------------------------
15
- set(INTERPROCEDURAL_OPTIMIZATION ON CACHE BOOL "" FORCE)
22
+ set(INTERPROCEDURAL_OPTIMIZATION OFF CACHE BOOL "" FORCE)
16
23
  set(USE_STATIC_MSVC_RUNTIME_LIBRARY OFF CACHE BOOL "" FORCE)
17
24
  set(TARGET_UNIT_TESTS OFF CACHE BOOL "" FORCE)
18
25
  set(TARGET_HELLO_WORLD OFF CACHE BOOL "" FORCE)
@@ -21,8 +28,10 @@ set(TARGET_SAMPLES OFF CACHE BOOL "" FORCE)
21
28
  set(TARGET_VIEWER OFF CACHE BOOL "" FORCE)
22
29
  set(OBJECT_LAYER_BITS 16 CACHE STRING "" FORCE)
23
30
  set(USE_ASSERTS OFF CACHE BOOL "" FORCE)
24
- set(PROFILE_ENABLED OFF CACHE BOOL "" FORCE)
31
+ set(PROFILER_IN_DEBUG_AND_RELEASE OFF CACHE BOOL "" FORCE)
32
+ set(PROFILER_IN_DISTRIBUTION OFF CACHE BOOL "" FORCE)
25
33
  set(DEBUG_RENDERER_IN_DEBUG_AND_RELEASE OFF CACHE BOOL "" FORCE)
34
+ set(DEBUG_RENDERER_IN_DISTRIBUTION OFF CACHE BOOL "" FORCE)
26
35
  set(CROSS_PLATFORM_DETERMINISTIC OFF CACHE BOOL "" FORCE)
27
36
  set(FLOATING_POINT_EXCEPTIONS_ENABLED OFF CACHE BOOL "" FORCE)
28
37
  set(DOUBLE_PRECISION OFF CACHE BOOL "" FORCE)
@@ -110,6 +110,7 @@ name = "bloom-windows"
110
110
  version = "0.1.0"
111
111
  dependencies = [
112
112
  "bloom-shared",
113
+ "image",
113
114
  "raw-window-handle",
114
115
  "wgpu",
115
116
  "windows 0.58.0",
@@ -8,11 +8,20 @@ name = "bloom_windows"
8
8
  crate-type = ["staticlib"]
9
9
 
10
10
  [features]
11
- default = ["jolt"]
11
+ # Jolt is opt-in on Windows because Perry's native-library build pipeline
12
+ # does not forward cargo `--features` to nativeLibrary crates, and bundling
13
+ # Jolt's static archives into bloom_windows.lib leaves the final lld-link
14
+ # step unable to resolve `JPH::*` symbols (the staticlib has no embedded
15
+ # search path and the C++ library lives off cargo's normal lib search).
16
+ # Games that need bloom/physics on Windows must opt in explicitly until the
17
+ # perry side gains a way to thread `cargo:rustc-link-search` through to the
18
+ # final link line.
19
+ default = []
12
20
  jolt = ["bloom-shared/jolt"]
13
21
 
14
22
  [dependencies]
15
23
  bloom-shared = { path = "../shared", default-features = false, features = ["mp3"] }
24
+ image = { version = "0.25", default-features = false, features = ["hdr"] }
16
25
  raw-window-handle = "0.6"
17
26
  wgpu = "29"
18
27
 
@@ -1,6 +1,6 @@
1
1
  use bloom_shared::engine::EngineState;
2
2
  use bloom_shared::renderer::Renderer;
3
- use bloom_shared::string_header::str_from_header;
3
+ use bloom_shared::string_header::{alloc_perry_string, str_from_header};
4
4
  use bloom_shared::audio::{parse_wav, parse_ogg, parse_mp3};
5
5
 
6
6
  use std::sync::OnceLock;
@@ -344,6 +344,11 @@ pub extern "C" fn bloom_init_window(width: f64, height: f64, title_ptr: *const u
344
344
  wgpu::ExperimentalFeatures::disabled()
345
345
  };
346
346
  let mut required_limits = wgpu::Limits::default();
347
+ // Phase 1c: the material ABI declares 5 bind groups (PerFrame,
348
+ // PerView, PerMaterial, PerDraw, SceneInputs). wgpu's default
349
+ // limit is 4. Metal / Vulkan / D3D12 support at least 7, so 5 is
350
+ // safely within every real backend's capabilities.
351
+ required_limits.max_bind_groups = 5;
347
352
  if required_features.intersects(rt_mask) {
348
353
  required_limits = required_limits
349
354
  .using_minimum_supported_acceleration_structure_values();
@@ -1587,24 +1592,14 @@ pub extern "C" fn bloom_file_exists(path_ptr: *const u8) -> f64 {
1587
1592
  #[no_mangle]
1588
1593
  pub extern "C" fn bloom_read_file(path_ptr: *const u8) -> *const u8 {
1589
1594
  let path = str_from_header(path_ptr);
1595
+ // Always return a valid Perry string. A null pointer would NaN-box into a
1596
+ // string-typed JS value pointing at address 0; subsequent `.length` /
1597
+ // `.charCodeAt` reads dereference the bogus StringHeader and segfault.
1598
+ // Callers detect "missing file" via `data.length === 0` (e.g. the
1599
+ // jump game's discoverLevels probe across level1..level10 / custom_*).
1590
1600
  match std::fs::read_to_string(path) {
1591
- Ok(contents) => {
1592
- // Return Perry-format string: StringHeader (length u32 + capacity u32 + refcount u32) followed by UTF-8 data
1593
- let bytes = contents.as_bytes();
1594
- let len = bytes.len();
1595
- let total = 12 + len; // 12 bytes header (3 × u32) + data
1596
- let layout = std::alloc::Layout::from_size_align(total, 4).unwrap();
1597
- unsafe {
1598
- let ptr = std::alloc::alloc(layout);
1599
- if ptr.is_null() { return std::ptr::null(); }
1600
- *(ptr as *mut u32) = len as u32; // length
1601
- *(ptr.add(4) as *mut u32) = len as u32; // capacity
1602
- *(ptr.add(8) as *mut u32) = 1; // refcount (unique)
1603
- std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.add(12), len);
1604
- ptr
1605
- }
1606
- }
1607
- Err(_) => std::ptr::null(),
1601
+ Ok(contents) => alloc_perry_string(&contents),
1602
+ Err(_) => alloc_perry_string(""),
1608
1603
  }
1609
1604
  }
1610
1605
 
@@ -1897,6 +1892,219 @@ pub extern "C" fn bloom_set_sss_enabled(on: f64) {
1897
1892
  engine().renderer.set_sss_enabled(on != 0.0);
1898
1893
  }
1899
1894
 
1895
+ // ============================================================
1896
+ // Render scale / upscale / DRS / post-FX / screenshots / impulse
1897
+ // Ports of the macOS / Linux FFI surface so the bloom/core TS layer
1898
+ // links cleanly on Windows. EngineState in bloom-shared already
1899
+ // exposes the underlying renderer methods, so these wrappers are
1900
+ // platform-agnostic.
1901
+ // ============================================================
1902
+
1903
+ #[no_mangle]
1904
+ pub extern "C" fn bloom_take_screenshot(path_ptr: *const u8) {
1905
+ let path = str_from_header(path_ptr).to_string();
1906
+ let eng = engine();
1907
+ eng.renderer.screenshot_requested = true;
1908
+ eng.renderer.pending_screenshot_path = Some(path);
1909
+ }
1910
+
1911
+ #[no_mangle]
1912
+ pub extern "C" fn bloom_set_env_clear_from_hdr(path_ptr: *const u8) {
1913
+ use image::ImageDecoder;
1914
+ let path = str_from_header(path_ptr).to_string();
1915
+ let file = match std::fs::File::open(&path) {
1916
+ Ok(f) => f,
1917
+ Err(_) => return,
1918
+ };
1919
+ let decoder = match image::codecs::hdr::HdrDecoder::new(std::io::BufReader::new(file)) {
1920
+ Ok(d) => d,
1921
+ Err(_) => return,
1922
+ };
1923
+ let (w, h) = decoder.dimensions();
1924
+ let byte_len = (w as usize) * (h as usize) * 3 * 4;
1925
+ let mut buf = vec![0u8; byte_len];
1926
+ if decoder.read_image(&mut buf).is_err() {
1927
+ return;
1928
+ }
1929
+ let rgb_f32: Vec<f32> = buf
1930
+ .chunks_exact(4)
1931
+ .map(|c| f32::from_le_bytes([c[0], c[1], c[2], c[3]]))
1932
+ .collect();
1933
+ engine().renderer.load_env_from_hdr(w, h, &rgb_f32);
1934
+ }
1935
+
1936
+ #[no_mangle]
1937
+ pub extern "C" fn bloom_set_fog(r: f64, g: f64, b: f64, density: f64, height_ref: f64, height_falloff: f64) {
1938
+ let r_ = engine();
1939
+ r_.renderer.set_fog_color(r as f32, g as f32, b as f32);
1940
+ r_.renderer.set_fog_density(density as f32);
1941
+ r_.renderer.set_fog_height_falloff(height_ref as f32, height_falloff as f32);
1942
+ }
1943
+
1944
+ #[no_mangle]
1945
+ pub extern "C" fn bloom_set_chromatic_aberration(strength: f64) {
1946
+ engine().renderer.set_chromatic_aberration(strength as f32);
1947
+ }
1948
+
1949
+ #[no_mangle]
1950
+ pub extern "C" fn bloom_set_vignette(strength: f64, softness: f64) {
1951
+ engine().renderer.set_vignette(strength as f32, softness as f32);
1952
+ }
1953
+
1954
+ #[no_mangle]
1955
+ pub extern "C" fn bloom_set_film_grain(strength: f64) {
1956
+ engine().renderer.set_film_grain(strength as f32);
1957
+ }
1958
+
1959
+ #[no_mangle]
1960
+ pub extern "C" fn bloom_set_sun_shafts(strength: f64, decay: f64, r: f64, g: f64, b: f64) {
1961
+ let eng = engine();
1962
+ eng.renderer.set_sun_shaft_strength(strength as f32);
1963
+ eng.renderer.set_sun_shaft_decay(decay as f32);
1964
+ eng.renderer.set_sun_shaft_color(r as f32, g as f32, b as f32);
1965
+ }
1966
+
1967
+ #[no_mangle]
1968
+ pub extern "C" fn bloom_set_auto_exposure(on: f64) {
1969
+ engine().renderer.set_auto_exposure(on != 0.0);
1970
+ }
1971
+
1972
+ #[no_mangle]
1973
+ pub extern "C" fn bloom_set_taa_enabled(on: f64) {
1974
+ engine().renderer.set_taa_enabled(on != 0.0);
1975
+ }
1976
+
1977
+ #[no_mangle]
1978
+ pub extern "C" fn bloom_set_render_scale(scale: f64) {
1979
+ engine().renderer.set_render_scale(scale as f32);
1980
+ }
1981
+
1982
+ #[no_mangle]
1983
+ pub extern "C" fn bloom_get_render_scale() -> f64 {
1984
+ engine().renderer.render_scale() as f64
1985
+ }
1986
+
1987
+ #[no_mangle]
1988
+ pub extern "C" fn bloom_set_upscale_mode(mode: f64) {
1989
+ engine().renderer.set_upscale_mode(mode as u32);
1990
+ }
1991
+
1992
+ #[no_mangle]
1993
+ pub extern "C" fn bloom_set_cas_strength(strength: f64) {
1994
+ engine().renderer.set_cas_strength(strength as f32);
1995
+ }
1996
+
1997
+ #[no_mangle]
1998
+ pub extern "C" fn bloom_get_physical_width() -> f64 {
1999
+ engine().renderer.physical_width() as f64
2000
+ }
2001
+
2002
+ #[no_mangle]
2003
+ pub extern "C" fn bloom_get_physical_height() -> f64 {
2004
+ engine().renderer.physical_height() as f64
2005
+ }
2006
+
2007
+ #[no_mangle]
2008
+ pub extern "C" fn bloom_set_auto_resolution(target_hz: f64, enabled: f64) {
2009
+ let eng = engine();
2010
+ if enabled != 0.0 {
2011
+ let current = eng.renderer.render_scale();
2012
+ eng.drs.enable(target_hz as f32, current);
2013
+ } else {
2014
+ eng.drs.disable();
2015
+ }
2016
+ }
2017
+
2018
+ #[no_mangle]
2019
+ pub extern "C" fn bloom_set_manual_exposure(value: f64) {
2020
+ engine().renderer.set_manual_exposure(value as f32);
2021
+ }
2022
+
2023
+ #[no_mangle]
2024
+ pub extern "C" fn bloom_set_env_intensity(intensity: f64) {
2025
+ engine().renderer.set_env_intensity(intensity as f32);
2026
+ }
2027
+
2028
+ #[no_mangle]
2029
+ pub extern "C" fn bloom_set_ssgi_enabled(enabled: f64) {
2030
+ engine().renderer.set_ssgi_enabled(enabled != 0.0);
2031
+ }
2032
+
2033
+ #[no_mangle]
2034
+ pub extern "C" fn bloom_set_ssgi_intensity(intensity: f64) {
2035
+ engine().renderer.set_ssgi_intensity(intensity as f32);
2036
+ }
2037
+
2038
+ #[no_mangle]
2039
+ pub extern "C" fn bloom_set_ssgi_radius(radius: f64) {
2040
+ engine().renderer.set_ssgi_radius(radius as f32);
2041
+ }
2042
+
2043
+ #[no_mangle]
2044
+ pub extern "C" fn bloom_set_dof(enabled: f64, focus_distance: f64, aperture: f64) {
2045
+ let r = &mut engine().renderer;
2046
+ r.set_dof_enabled(enabled != 0.0);
2047
+ r.set_dof_focus_distance(focus_distance as f32);
2048
+ r.set_dof_aperture(aperture as f32);
2049
+ }
2050
+
2051
+ #[no_mangle]
2052
+ pub extern "C" fn bloom_splat_impulse(x: f64, z: f64, radius: f64, strength: f64) {
2053
+ engine().renderer.impulse_field.submit_splat(
2054
+ x as f32, z as f32, radius as f32, strength as f32,
2055
+ );
2056
+ }
2057
+
2058
+ // Render texture FFI (stub — GPU implementation deferred).
2059
+ #[no_mangle]
2060
+ pub extern "C" fn bloom_load_render_texture(width: f64, height: f64) -> f64 {
2061
+ engine().textures.load_render_texture(width as u32, height as u32)
2062
+ }
2063
+ #[no_mangle]
2064
+ pub extern "C" fn bloom_unload_render_texture(handle: f64) {
2065
+ engine().textures.unload_render_texture(handle);
2066
+ }
2067
+ #[no_mangle]
2068
+ pub extern "C" fn bloom_begin_texture_mode(_handle: f64) {
2069
+ // Stub: no-op until GPU render-to-texture is wired.
2070
+ }
2071
+ #[no_mangle]
2072
+ pub extern "C" fn bloom_end_texture_mode() {
2073
+ // Stub: no-op.
2074
+ }
2075
+ #[no_mangle]
2076
+ pub extern "C" fn bloom_get_render_texture_texture(handle: f64) -> f64 {
2077
+ engine().textures.get_render_texture_texture(handle)
2078
+ }
2079
+
2080
+ #[no_mangle]
2081
+ pub extern "C" fn bloom_profiler_frame_history() -> *const u8 {
2082
+ let hist = engine().profiler.frame_history();
2083
+ let mut s = String::with_capacity(hist.len() * 24);
2084
+ for (cpu, gpu) in &hist {
2085
+ s.push_str(&format!("{:.2}|{:.2}\n", cpu, gpu));
2086
+ }
2087
+ alloc_perry_string(&s)
2088
+ }
2089
+
2090
+ #[no_mangle]
2091
+ pub extern "C" fn bloom_profiler_overlay_text() -> *const u8 {
2092
+ let snap = engine().profiler.snapshot();
2093
+ let mut s = String::with_capacity(snap.len() * 48);
2094
+ for (label, cpu, gpu) in &snap {
2095
+ s.push_str(label);
2096
+ s.push('|');
2097
+ s.push_str(&format!("{:.2}", cpu));
2098
+ s.push('|');
2099
+ match gpu {
2100
+ Some(g) => s.push_str(&format!("{:.2}", g)),
2101
+ None => s.push_str("-1"),
2102
+ }
2103
+ s.push('\n');
2104
+ }
2105
+ alloc_perry_string(&s)
2106
+ }
2107
+
1900
2108
  // ============================================================
1901
2109
  // Profiler — CPU phase timings (always available) + GPU timestamps
1902
2110
  // (when the adapter supports TIMESTAMP_QUERY). Disabled by default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloomengine/engine",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Bloom Engine: native TypeScript game engine compiled by Perry",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -60,6 +60,7 @@
60
60
  "native/third_party/bloom_jolt/include/**",
61
61
  "native/third_party/bloom_jolt/src/**",
62
62
  "native/third_party/JoltPhysics/Jolt/**",
63
+ "native/third_party/JoltPhysics/Build/**",
63
64
  "native/third_party/JoltPhysics/LICENSE",
64
65
  "native/third_party/JoltPhysics/README.md"
65
66
  ],
@@ -203,7 +204,7 @@
203
204
  { "name": "bloom_clear_all_post_passes", "params": [], "returns": "void" },
204
205
  { "name": "bloom_draw_material", "params": ["f64", "f64", "f64", "f64", "f64", "f64", "f64", "f64", "f64", "f64", "f64"], "returns": "void" },
205
206
  { "name": "bloom_load_model_animation", "params": ["i64"], "returns": "f64" },
206
- { "name": "bloom_update_model_animation", "params": ["f64", "f64", "f64", "f64", "f64", "f64", "f64"], "returns": "void" },
207
+ { "name": "bloom_update_model_animation", "params": ["f64", "f64", "f64", "f64", "f64", "f64", "f64", "f64"], "returns": "void" },
207
208
  { "name": "bloom_create_mesh", "params": ["i64", "f64", "i64", "f64"], "returns": "f64" },
208
209
  { "name": "bloom_set_joint_test", "params": ["f64", "f64"], "returns": "void" },
209
210
  { "name": "bloom_set_ambient_light", "params": ["f64", "f64", "f64", "f64"], "returns": "void" },
@@ -287,7 +288,7 @@
287
288
  { "name": "bloom_get_model_bounds_max_z", "params": ["f64"], "returns": "f64" },
288
289
  { "name": "bloom_write_file", "params": ["i64", "i64"], "returns": "f64" },
289
290
  { "name": "bloom_file_exists", "params": ["i64"], "returns": "f64" },
290
- { "name": "bloom_read_file", "params": ["i64"], "returns": "i64" },
291
+ { "name": "bloom_read_file", "params": ["i64"], "returns": "string" },
291
292
  { "name": "bloom_get_touch_x", "params": ["f64"], "returns": "f64" },
292
293
  { "name": "bloom_get_touch_y", "params": ["f64"], "returns": "f64" },
293
294
  { "name": "bloom_get_touch_count", "params": [], "returns": "f64" },
@@ -315,9 +316,9 @@
315
316
  { "name": "bloom_scene_node_index_count", "params": ["f64"], "returns": "f64" },
316
317
  { "name": "bloom_set_cursor_shape", "params": ["f64"], "returns": "void" },
317
318
  { "name": "bloom_set_clipboard_text", "params": ["i64"], "returns": "void" },
318
- { "name": "bloom_get_clipboard_text", "params": [], "returns": "i64" },
319
- { "name": "bloom_open_file_dialog", "params": ["i64", "i64"], "returns": "i64" },
320
- { "name": "bloom_save_file_dialog", "params": ["i64", "i64"], "returns": "i64" },
319
+ { "name": "bloom_get_clipboard_text", "params": [], "returns": "string" },
320
+ { "name": "bloom_open_file_dialog", "params": ["i64", "i64"], "returns": "string" },
321
+ { "name": "bloom_save_file_dialog", "params": ["i64", "i64"], "returns": "string" },
321
322
  { "name": "bloom_scene_pick_all", "params": ["f64", "f64", "f64"], "returns": "f64" },
322
323
  { "name": "bloom_pick_all_handle", "params": ["f64"], "returns": "f64" },
323
324
  { "name": "bloom_pick_all_distance", "params": ["f64"], "returns": "f64" },
@@ -538,7 +539,8 @@
538
539
  },
539
540
  "linux": {
540
541
  "crate": "native/linux/",
541
- "lib": "libbloom_linux.a",
542
+ "lib": "libbloom_linux_bundled.a",
543
+ "libs": ["stdc++"],
542
544
  "pkgConfig": ["x11", "xi", "alsa"]
543
545
  },
544
546
  "android": {
@@ -1,6 +1,10 @@
1
- import { Color } from './types';
1
+ import { Color as ColorType } from './types';
2
2
 
3
- export const ColorConstants: Record<string, Color> = {
3
+ // Canonical color palette. Re-exported as `Color` from `bloom/core` and
4
+ // declared as a real top-level binding (not an alias re-export) so Perry
5
+ // emits a `_perry_fn_src_core_colors_ts__Color` symbol that examples
6
+ // importing `Color` from `bloom/core` can link against.
7
+ export const Color: Record<string, ColorType> = {
4
8
  RayWhite: { r: 245, g: 245, b: 245, a: 255 },
5
9
  White: { r: 255, g: 255, b: 255, a: 255 },
6
10
  Black: { r: 0, g: 0, b: 0, a: 255 },
@@ -27,30 +31,33 @@ export const ColorConstants: Record<string, Color> = {
27
31
  Blank: { r: 0, g: 0, b: 0, a: 0 },
28
32
  };
29
33
 
34
+ // Backward-compatible alias — same object, kept for older imports.
35
+ export const ColorConstants = Color;
36
+
30
37
  // Backward-compatible alias with SCREAMING_SNAKE keys
31
- export const Colors: Record<string, Color> = {
32
- WHITE: ColorConstants.White,
33
- BLACK: ColorConstants.Black,
34
- RED: ColorConstants.Red,
35
- GREEN: ColorConstants.Green,
36
- BLUE: ColorConstants.Blue,
37
- YELLOW: ColorConstants.Yellow,
38
- ORANGE: ColorConstants.Orange,
39
- PINK: ColorConstants.Pink,
40
- PURPLE: ColorConstants.Purple,
41
- DARKGRAY: ColorConstants.DarkGray,
42
- LIGHTGRAY: ColorConstants.LightGray,
43
- GRAY: ColorConstants.Gray,
44
- DARKBLUE: ColorConstants.DarkBlue,
45
- SKYBLUE: ColorConstants.SkyBlue,
46
- LIME: ColorConstants.Lime,
47
- DARKGREEN: ColorConstants.DarkGreen,
48
- GOLD: ColorConstants.Gold,
49
- MAROON: ColorConstants.Maroon,
50
- BROWN: ColorConstants.Brown,
51
- BEIGE: ColorConstants.Beige,
52
- MAGENTA: ColorConstants.Magenta,
53
- VIOLET: ColorConstants.Violet,
54
- RAYWHITE: ColorConstants.RayWhite,
55
- BLANK: ColorConstants.Blank,
38
+ export const Colors: Record<string, ColorType> = {
39
+ WHITE: Color.White,
40
+ BLACK: Color.Black,
41
+ RED: Color.Red,
42
+ GREEN: Color.Green,
43
+ BLUE: Color.Blue,
44
+ YELLOW: Color.Yellow,
45
+ ORANGE: Color.Orange,
46
+ PINK: Color.Pink,
47
+ PURPLE: Color.Purple,
48
+ DARKGRAY: Color.DarkGray,
49
+ LIGHTGRAY: Color.LightGray,
50
+ GRAY: Color.Gray,
51
+ DARKBLUE: Color.DarkBlue,
52
+ SKYBLUE: Color.SkyBlue,
53
+ LIME: Color.Lime,
54
+ DARKGREEN: Color.DarkGreen,
55
+ GOLD: Color.Gold,
56
+ MAROON: Color.Maroon,
57
+ BROWN: Color.Brown,
58
+ BEIGE: Color.Beige,
59
+ MAGENTA: Color.Magenta,
60
+ VIOLET: Color.Violet,
61
+ RAYWHITE: Color.RayWhite,
62
+ BLANK: Color.Blank,
56
63
  };
package/src/core/index.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { Color, Camera2D, Camera3D } from './types';
2
2
 
3
3
  export type { Color, Vec2, Vec3, Vec4, Rect, Camera2D, Camera3D, Texture, Font, Sound, Music, Quat, Ray, BoundingBox, Model, Mat4, RayHit, FrustumPlanes } from './types';
4
- export { ColorConstants, Colors } from './colors';
5
- export { ColorConstants as Color } from './colors';
4
+ export { Color, ColorConstants, Colors } from './colors';
6
5
  export { Key, MouseButton } from './keys';
7
6
 
8
7
  // FFI declarations