@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.
Files changed (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/native/android/Cargo.lock +1848 -0
  4. package/native/android/Cargo.toml +24 -0
  5. package/native/android/src/lib.rs +702 -0
  6. package/native/ios/Cargo.lock +1690 -0
  7. package/native/ios/Cargo.toml +32 -0
  8. package/native/ios/src/lib.rs +1267 -0
  9. package/native/linux/Cargo.lock +3279 -0
  10. package/native/linux/Cargo.toml +29 -0
  11. package/native/linux/src/lib.rs +1331 -0
  12. package/native/macos/Cargo.lock +3310 -0
  13. package/native/macos/Cargo.toml +46 -0
  14. package/native/macos/src/lib.rs +1302 -0
  15. package/native/shared/Cargo.lock +1899 -0
  16. package/native/shared/Cargo.toml +62 -0
  17. package/native/shared/assets/default_font.ttf +0 -0
  18. package/native/shared/build.rs +270 -0
  19. package/native/shared/shaders/common/clouds.wgsl +122 -0
  20. package/native/shared/shaders/common/fog.wgsl +16 -0
  21. package/native/shared/shaders/common/foliage_wind.wgsl +98 -0
  22. package/native/shared/shaders/common/imposter.wgsl +112 -0
  23. package/native/shared/shaders/common/pbr.wgsl +186 -0
  24. package/native/shared/shaders/common/shadows.wgsl +186 -0
  25. package/native/shared/shaders/common/sky.wgsl +8 -0
  26. package/native/shared/shaders/common/tonemap.wgsl +25 -0
  27. package/native/shared/shaders/impulse_field.wgsl +57 -0
  28. package/native/shared/shaders/material_abi.wgsl +383 -0
  29. package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
  30. package/native/shared/src/anim_mixer.rs +61 -0
  31. package/native/shared/src/attach.rs +263 -0
  32. package/native/shared/src/audio/decode.rs +123 -0
  33. package/native/shared/src/audio/mod.rs +863 -0
  34. package/native/shared/src/audio/render.rs +892 -0
  35. package/native/shared/src/audio/spsc.rs +156 -0
  36. package/native/shared/src/audio/stream.rs +226 -0
  37. package/native/shared/src/custom_shaders.rs +104 -0
  38. package/native/shared/src/decals.rs +245 -0
  39. package/native/shared/src/drs.rs +211 -0
  40. package/native/shared/src/engine.rs +261 -0
  41. package/native/shared/src/ffi.rs +116 -0
  42. package/native/shared/src/ffi_core/assets.rs +388 -0
  43. package/native/shared/src/ffi_core/audio_ffi.rs +184 -0
  44. package/native/shared/src/ffi_core/draw.rs +334 -0
  45. package/native/shared/src/ffi_core/game_loop.rs +577 -0
  46. package/native/shared/src/ffi_core/input.rs +234 -0
  47. package/native/shared/src/ffi_core/mod.rs +127 -0
  48. package/native/shared/src/ffi_core/models.rs +1154 -0
  49. package/native/shared/src/ffi_core/ragdoll_ffi.rs +261 -0
  50. package/native/shared/src/ffi_core/scene.rs +626 -0
  51. package/native/shared/src/ffi_core/vfx.rs +212 -0
  52. package/native/shared/src/ffi_core/visual.rs +691 -0
  53. package/native/shared/src/frame_callbacks.rs +122 -0
  54. package/native/shared/src/geometry.rs +236 -0
  55. package/native/shared/src/handles.rs +182 -0
  56. package/native/shared/src/input.rs +448 -0
  57. package/native/shared/src/jolt_sys.rs +822 -0
  58. package/native/shared/src/lib.rs +55 -0
  59. package/native/shared/src/models.rs +1093 -0
  60. package/native/shared/src/models_gltf.rs +1280 -0
  61. package/native/shared/src/particles.rs +391 -0
  62. package/native/shared/src/physics_jolt.rs +1908 -0
  63. package/native/shared/src/picking.rs +298 -0
  64. package/native/shared/src/postfx.rs +345 -0
  65. package/native/shared/src/profiler.rs +492 -0
  66. package/native/shared/src/ragdoll.rs +474 -0
  67. package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
  68. package/native/shared/src/renderer/brdf_lut.rs +154 -0
  69. package/native/shared/src/renderer/draw2d.rs +143 -0
  70. package/native/shared/src/renderer/formats.rs +822 -0
  71. package/native/shared/src/renderer/froxel.rs +421 -0
  72. package/native/shared/src/renderer/gi_bake.rs +653 -0
  73. package/native/shared/src/renderer/graph.rs +462 -0
  74. package/native/shared/src/renderer/hiz.rs +269 -0
  75. package/native/shared/src/renderer/hot_reload.rs +390 -0
  76. package/native/shared/src/renderer/impulse_field.rs +456 -0
  77. package/native/shared/src/renderer/lighting.rs +154 -0
  78. package/native/shared/src/renderer/material_instancing.rs +171 -0
  79. package/native/shared/src/renderer/material_pipeline.rs +700 -0
  80. package/native/shared/src/renderer/material_system.rs +1996 -0
  81. package/native/shared/src/renderer/material_system_tests.rs +601 -0
  82. package/native/shared/src/renderer/material_system_wasm.rs +41 -0
  83. package/native/shared/src/renderer/mod.rs +12556 -0
  84. package/native/shared/src/renderer/model_draw.rs +641 -0
  85. package/native/shared/src/renderer/occlusion.rs +429 -0
  86. package/native/shared/src/renderer/planar_pass.rs +593 -0
  87. package/native/shared/src/renderer/planar_reflection.rs +499 -0
  88. package/native/shared/src/renderer/post_pass.rs +249 -0
  89. package/native/shared/src/renderer/postfx_chain.rs +728 -0
  90. package/native/shared/src/renderer/pt_pass.rs +577 -0
  91. package/native/shared/src/renderer/scene_pass.rs +607 -0
  92. package/native/shared/src/renderer/shader_include.rs +205 -0
  93. package/native/shared/src/renderer/shader_library.rs +135 -0
  94. package/native/shared/src/renderer/shaders/ao.rs +570 -0
  95. package/native/shared/src/renderer/shaders/core.rs +1243 -0
  96. package/native/shared/src/renderer/shaders/env.rs +907 -0
  97. package/native/shared/src/renderer/shaders/gi.rs +810 -0
  98. package/native/shared/src/renderer/shaders/mod.rs +19 -0
  99. package/native/shared/src/renderer/shaders/post.rs +1558 -0
  100. package/native/shared/src/renderer/shaders/pt.rs +1859 -0
  101. package/native/shared/src/renderer/shaders/ssgi.rs +1586 -0
  102. package/native/shared/src/renderer/shadow_pass.rs +731 -0
  103. package/native/shared/src/renderer/ssgi_pass.rs +392 -0
  104. package/native/shared/src/renderer/ssr_pass.rs +188 -0
  105. package/native/shared/src/renderer/texture_store.rs +473 -0
  106. package/native/shared/src/renderer/transient.rs +591 -0
  107. package/native/shared/src/renderer/types.rs +941 -0
  108. package/native/shared/src/renderer/util.rs +152 -0
  109. package/native/shared/src/scene.rs +1362 -0
  110. package/native/shared/src/sdf_cache.rs +274 -0
  111. package/native/shared/src/shadows.rs +1036 -0
  112. package/native/shared/src/staging.rs +102 -0
  113. package/native/shared/src/string_header.rs +266 -0
  114. package/native/shared/src/text_renderer.rs +502 -0
  115. package/native/shared/src/textures.rs +197 -0
  116. package/native/tvos/Cargo.lock +1693 -0
  117. package/native/tvos/Cargo.toml +36 -0
  118. package/native/tvos/metal-patched/Cargo.toml +178 -0
  119. package/native/tvos/metal-patched/LICENSE-APACHE +201 -0
  120. package/native/tvos/metal-patched/LICENSE-MIT +25 -0
  121. package/native/tvos/metal-patched/src/acceleration_structure.rs +667 -0
  122. package/native/tvos/metal-patched/src/acceleration_structure_pass.rs +108 -0
  123. package/native/tvos/metal-patched/src/argument.rs +366 -0
  124. package/native/tvos/metal-patched/src/blitpass.rs +102 -0
  125. package/native/tvos/metal-patched/src/buffer.rs +71 -0
  126. package/native/tvos/metal-patched/src/capturedescriptor.rs +76 -0
  127. package/native/tvos/metal-patched/src/capturemanager.rs +113 -0
  128. package/native/tvos/metal-patched/src/commandbuffer.rs +192 -0
  129. package/native/tvos/metal-patched/src/commandqueue.rs +44 -0
  130. package/native/tvos/metal-patched/src/computepass.rs +107 -0
  131. package/native/tvos/metal-patched/src/constants.rs +152 -0
  132. package/native/tvos/metal-patched/src/counters.rs +119 -0
  133. package/native/tvos/metal-patched/src/depthstencil.rs +190 -0
  134. package/native/tvos/metal-patched/src/device.rs +2134 -0
  135. package/native/tvos/metal-patched/src/drawable.rs +39 -0
  136. package/native/tvos/metal-patched/src/encoder.rs +2041 -0
  137. package/native/tvos/metal-patched/src/heap.rs +281 -0
  138. package/native/tvos/metal-patched/src/indirect_encoder.rs +344 -0
  139. package/native/tvos/metal-patched/src/lib.rs +657 -0
  140. package/native/tvos/metal-patched/src/library.rs +902 -0
  141. package/native/tvos/metal-patched/src/mps.rs +575 -0
  142. package/native/tvos/metal-patched/src/pipeline/compute.rs +475 -0
  143. package/native/tvos/metal-patched/src/pipeline/mod.rs +71 -0
  144. package/native/tvos/metal-patched/src/pipeline/render.rs +762 -0
  145. package/native/tvos/metal-patched/src/renderpass.rs +443 -0
  146. package/native/tvos/metal-patched/src/resource.rs +182 -0
  147. package/native/tvos/metal-patched/src/sampler.rs +165 -0
  148. package/native/tvos/metal-patched/src/sync.rs +178 -0
  149. package/native/tvos/metal-patched/src/texture.rs +352 -0
  150. package/native/tvos/metal-patched/src/types.rs +90 -0
  151. package/native/tvos/metal-patched/src/vertexdescriptor.rs +250 -0
  152. package/native/tvos/src/audio_backend.rs +197 -0
  153. package/native/tvos/src/lib.rs +1891 -0
  154. package/native/visionos/Cargo.lock +1693 -0
  155. package/native/visionos/Cargo.toml +40 -0
  156. package/native/visionos/src/audio_backend.rs +197 -0
  157. package/native/visionos/src/lib.rs +1887 -0
  158. package/native/watchos/Cargo.lock +16 -0
  159. package/native/watchos/Cargo.toml +19 -0
  160. package/native/watchos/shaders/bloom_postfx.metal +99 -0
  161. package/native/watchos/src/BloomWatchApp.swift +1267 -0
  162. package/native/watchos/src/BloomWatchAudio.swift +179 -0
  163. package/native/watchos/src/audio.rs +55 -0
  164. package/native/watchos/src/draw_list.rs +229 -0
  165. package/native/watchos/src/ffi_stubs.rs +915 -0
  166. package/native/watchos/src/ffi_stubs_manual.rs +35 -0
  167. package/native/watchos/src/lib.rs +1124 -0
  168. package/native/watchos/src/models.rs +746 -0
  169. package/native/watchos/src/postfx.rs +95 -0
  170. package/native/watchos/src/scene.rs +534 -0
  171. package/native/watchos/src/textures.rs +184 -0
  172. package/native/web/Cargo.lock +1657 -0
  173. package/native/web/Cargo.toml +43 -0
  174. package/native/web/bloom_glue.js +695 -0
  175. package/native/web/build.sh +131 -0
  176. package/native/web/index.html +35 -0
  177. package/native/web/jolt_bridge.js +1519 -0
  178. package/native/web/src/input_ffi.rs +286 -0
  179. package/native/web/src/lib.rs +1796 -0
  180. package/native/web/src/material_ffi.rs +710 -0
  181. package/native/web/src/parity_ffi.rs +343 -0
  182. package/native/web/src/physics_ffi.rs +643 -0
  183. package/native/web/src/ragdoll_ffi.rs +250 -0
  184. package/native/web/src/render_settings.rs +98 -0
  185. package/native/windows/Cargo.lock +1815 -0
  186. package/native/windows/Cargo.toml +68 -0
  187. package/native/windows/src/lib.rs +1486 -0
  188. package/package.json +4279 -0
  189. package/src/audio/index.ts +315 -0
  190. package/src/core/colors.ts +63 -0
  191. package/src/core/index.ts +1206 -0
  192. package/src/core/keys.ts +63 -0
  193. package/src/core/types.ts +104 -0
  194. package/src/index.ts +171 -0
  195. package/src/math/index.ts +516 -0
  196. package/src/mobile/index.ts +294 -0
  197. package/src/models/index.ts +1258 -0
  198. package/src/physics/index.ts +1134 -0
  199. package/src/scene/index.ts +698 -0
  200. package/src/shapes/index.ts +120 -0
  201. package/src/text/index.ts +48 -0
  202. package/src/textures/index.ts +187 -0
  203. package/src/vfx/index.ts +191 -0
  204. package/src/world/index.ts +24 -0
  205. package/src/world/loader.ts +423 -0
  206. package/src/world/prefab.ts +217 -0
  207. package/src/world/render.ts +172 -0
  208. package/src/world/saver.ts +108 -0
  209. package/src/world/serialize.ts +301 -0
  210. package/src/world/terrain.ts +355 -0
  211. package/src/world/types.ts +160 -0
  212. package/src/world/validate.ts +319 -0
  213. package/src/world/version.ts +114 -0
@@ -0,0 +1,120 @@
1
+ import { Color, Rect, Vec2 } from '../core/types';
2
+
3
+ // FFI declarations
4
+ declare function bloom_draw_line(x1: number, y1: number, x2: number, y2: number, thickness: number, r: number, g: number, b: number, a: number): void;
5
+ declare function bloom_draw_rect(x: number, y: number, w: number, h: number, r: number, g: number, b: number, a: number): void;
6
+ declare function bloom_draw_rect_lines(x: number, y: number, w: number, h: number, thickness: number, r: number, g: number, b: number, a: number): void;
7
+ declare function bloom_draw_circle(cx: number, cy: number, radius: number, r: number, g: number, b: number, a: number): void;
8
+ declare function bloom_draw_circle_lines(cx: number, cy: number, radius: number, r: number, g: number, b: number, a: number): void;
9
+ declare function bloom_draw_triangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, r: number, g: number, b: number, a: number): void;
10
+ declare function bloom_draw_poly(cx: number, cy: number, sides: number, radius: number, rotation: number, r: number, g: number, b: number, a: number): void;
11
+
12
+ // Drawing functions
13
+
14
+ export function drawLine(startX: number, startY: number, endX: number, endY: number, thickness: number, color: Color): void {
15
+ bloom_draw_line(startX, startY, endX, endY, thickness, color.r, color.g, color.b, color.a);
16
+ }
17
+
18
+ export function drawRect(x: number, y: number, width: number, height: number, color: Color): void {
19
+ bloom_draw_rect(x, y, width, height, color.r, color.g, color.b, color.a);
20
+ }
21
+
22
+ export function drawRectRec(rec: Rect, color: Color): void {
23
+ bloom_draw_rect(rec.x, rec.y, rec.width, rec.height, color.r, color.g, color.b, color.a);
24
+ }
25
+
26
+ export function drawRectLines(x: number, y: number, width: number, height: number, thickness: number, color: Color): void {
27
+ bloom_draw_rect_lines(x, y, width, height, thickness, color.r, color.g, color.b, color.a);
28
+ }
29
+
30
+ export function drawCircle(centerX: number, centerY: number, radius: number, color: Color): void {
31
+ bloom_draw_circle(centerX, centerY, radius, color.r, color.g, color.b, color.a);
32
+ }
33
+
34
+ export function drawCircleLines(centerX: number, centerY: number, radius: number, color: Color): void {
35
+ bloom_draw_circle_lines(centerX, centerY, radius, color.r, color.g, color.b, color.a);
36
+ }
37
+
38
+ export function drawTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, color: Color): void {
39
+ bloom_draw_triangle(x1, y1, x2, y2, x3, y3, color.r, color.g, color.b, color.a);
40
+ }
41
+
42
+ export function drawPoly(centerX: number, centerY: number, sides: number, radius: number, rotation: number, color: Color): void {
43
+ bloom_draw_poly(centerX, centerY, sides, radius, rotation, color.r, color.g, color.b, color.a);
44
+ }
45
+
46
+ // Bezier curve drawing (pure TS — subdivides cubic bezier into line segments)
47
+
48
+ export function drawBezier(
49
+ startX: number, startY: number,
50
+ cp1X: number, cp1Y: number,
51
+ cp2X: number, cp2Y: number,
52
+ endX: number, endY: number,
53
+ thickness: number, color: Color,
54
+ ): void {
55
+ const segments = 24;
56
+ let prevX = startX;
57
+ let prevY = startY;
58
+ for (let i = 1; i <= segments; i++) {
59
+ const t = i / segments;
60
+ const u = 1 - t;
61
+ const x = u * u * u * startX + 3 * u * u * t * cp1X + 3 * u * t * t * cp2X + t * t * t * endX;
62
+ const y = u * u * u * startY + 3 * u * u * t * cp1Y + 3 * u * t * t * cp2Y + t * t * t * endY;
63
+ bloom_draw_line(prevX, prevY, x, y, thickness, color.r, color.g, color.b, color.a);
64
+ prevX = x;
65
+ prevY = y;
66
+ }
67
+ }
68
+
69
+ // Pure TypeScript collision detection
70
+
71
+ export function checkCollisionRecs(rec1: Rect, rec2: Rect): boolean {
72
+ return (
73
+ rec1.x < rec2.x + rec2.width &&
74
+ rec1.x + rec1.width > rec2.x &&
75
+ rec1.y < rec2.y + rec2.height &&
76
+ rec1.y + rec1.height > rec2.y
77
+ );
78
+ }
79
+
80
+ export function checkCollisionCircles(center1: Vec2, radius1: number, center2: Vec2, radius2: number): boolean {
81
+ const dx = center2.x - center1.x;
82
+ const dy = center2.y - center1.y;
83
+ const distSq = dx * dx + dy * dy;
84
+ const radiusSum = radius1 + radius2;
85
+ return distSq <= radiusSum * radiusSum;
86
+ }
87
+
88
+ export function checkCollisionCircleRec(center: Vec2, radius: number, rec: Rect): boolean {
89
+ const closestX = Math.max(rec.x, Math.min(center.x, rec.x + rec.width));
90
+ const closestY = Math.max(rec.y, Math.min(center.y, rec.y + rec.height));
91
+ const dx = center.x - closestX;
92
+ const dy = center.y - closestY;
93
+ return (dx * dx + dy * dy) <= radius * radius;
94
+ }
95
+
96
+ export function checkCollisionPointRec(point: Vec2, rec: Rect): boolean {
97
+ return (
98
+ point.x >= rec.x &&
99
+ point.x <= rec.x + rec.width &&
100
+ point.y >= rec.y &&
101
+ point.y <= rec.y + rec.height
102
+ );
103
+ }
104
+
105
+ export function checkCollisionPointCircle(point: Vec2, center: Vec2, radius: number): boolean {
106
+ const dx = point.x - center.x;
107
+ const dy = point.y - center.y;
108
+ return (dx * dx + dy * dy) <= radius * radius;
109
+ }
110
+
111
+ export function getCollisionRec(rec1: Rect, rec2: Rect): Rect {
112
+ const x = Math.max(rec1.x, rec2.x);
113
+ const y = Math.max(rec1.y, rec2.y);
114
+ const right = Math.min(rec1.x + rec1.width, rec2.x + rec2.width);
115
+ const bottom = Math.min(rec1.y + rec1.height, rec2.y + rec2.height);
116
+ if (right <= x || bottom <= y) {
117
+ return { x: 0, y: 0, width: 0, height: 0 };
118
+ }
119
+ return { x, y, width: right - x, height: bottom - y };
120
+ }
@@ -0,0 +1,48 @@
1
+ import { Color, Font, Vec2 } from '../core/types';
2
+
3
+ // FFI declarations
4
+ declare function bloom_draw_text(text: number, x: number, y: number, size: number, r: number, g: number, b: number, a: number): void;
5
+ declare function bloom_measure_text(text: number, size: number): number;
6
+ declare function bloom_load_font(path: number, size: number): number;
7
+ declare function bloom_draw_text_ex(font: number, text: number, x: number, y: number, size: number, spacing: number, r: number, g: number, b: number, a: number): void;
8
+ declare function bloom_measure_text_ex(font: number, text: number, size: number, spacing: number): number;
9
+ declare function bloom_unload_font(font: number): void;
10
+
11
+ export function drawText(text: string, x: number, y: number, size: number, color: Color): void {
12
+ bloom_draw_text(text as any, x, y, size, color.r, color.g, color.b, color.a);
13
+ }
14
+
15
+ /// RGBA variant of `drawText`. Prefer this over passing a `Color` object on
16
+ /// Android (aarch64): Perry 0.5.x miscompiles `color.r` field reads that feed
17
+ /// straight into an f64 FFI slot, producing NaN for all color components and
18
+ /// dropping the glyph quads. Passing raw numbers bypasses the object read.
19
+ export function drawTextRgba(text: string, x: number, y: number, size: number, r: number, g: number, b: number, a: number): void {
20
+ bloom_draw_text(text as any, x, y, size, r, g, b, a);
21
+ }
22
+
23
+ export function measureText(text: string, size: number): number {
24
+ return bloom_measure_text(text as any, size);
25
+ }
26
+
27
+ export function loadFont(path: string, size: number): Font {
28
+ const handle = bloom_load_font(path as any, size);
29
+ return { handle, size };
30
+ }
31
+
32
+ export function loadFontEx(path: string, size: number): Font {
33
+ const handle = bloom_load_font(path as any, size);
34
+ return { handle, size };
35
+ }
36
+
37
+ export function unloadFont(font: Font): void {
38
+ bloom_unload_font(font.handle);
39
+ }
40
+
41
+ export function drawTextEx(font: Font, text: string, pos: Vec2, size: number, spacing: number, color: Color): void {
42
+ bloom_draw_text_ex(font.handle, text as any, pos.x, pos.y, size, spacing, color.r, color.g, color.b, color.a);
43
+ }
44
+
45
+ export function measureTextEx(font: Font, text: string, size: number, spacing: number): Vec2 {
46
+ const width = bloom_measure_text_ex(font.handle, text as any, size, spacing);
47
+ return { x: width, y: size };
48
+ }
@@ -0,0 +1,187 @@
1
+ import { spawn, parallelMap } from 'perry/thread';
2
+ import { Color, Rect, Texture } from '../core/types';
3
+
4
+ // FFI declarations
5
+ declare function bloom_load_texture(path: number): number;
6
+ declare function bloom_unload_texture(handle: number): void;
7
+ declare function bloom_draw_texture(handle: number, x: number, y: number, r: number, g: number, b: number, a: number): void;
8
+ declare function bloom_draw_texture_rec(handle: number, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, r: number, g: number, b: number, a: number): void;
9
+ declare function bloom_draw_texture_pro(handle: number, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number, ox: number, oy: number, rot: number, r: number, g: number, b: number, a: number): void;
10
+ declare function bloom_get_texture_width(handle: number): number;
11
+ declare function bloom_get_texture_height(handle: number): number;
12
+ declare function bloom_load_image(path: number): number;
13
+ declare function bloom_image_resize(handle: number, w: number, h: number): void;
14
+ declare function bloom_image_crop(handle: number, x: number, y: number, w: number, h: number): void;
15
+ declare function bloom_image_flip_h(handle: number): void;
16
+ declare function bloom_image_flip_v(handle: number): void;
17
+ declare function bloom_load_texture_from_image(handle: number): number;
18
+ declare function bloom_gen_texture_mipmaps(handle: number): void;
19
+ declare function bloom_set_texture_filter(handle: number, mode: number): void;
20
+
21
+ export const FILTER_LINEAR = 0;
22
+ export const FILTER_NEAREST = 1;
23
+
24
+ export function setTextureFilter(texture: Texture, mode: number): void {
25
+ bloom_set_texture_filter(texture.handle, mode);
26
+ }
27
+
28
+ /**
29
+ * Load a texture from a PNG/JPEG/BMP/TGA file.
30
+ *
31
+ * On failure (missing file, undecodable data) returns a Texture with
32
+ * `handle === 0` and zero dimensions — drawing it is a safe no-op and the
33
+ * engine logs the failure once. Check `tex.handle !== 0` when you need to
34
+ * react to missing assets.
35
+ */
36
+ export function loadTexture(path: string): Texture {
37
+ const id = bloom_load_texture(path as any);
38
+ const width = bloom_get_texture_width(id);
39
+ const height = bloom_get_texture_height(id);
40
+ return { handle: id, width, height };
41
+ }
42
+
43
+ export function unloadTexture(texture: Texture): void {
44
+ bloom_unload_texture(texture.handle);
45
+ }
46
+
47
+ export function drawTexture(texture: Texture, x: number, y: number, tint: Color): void {
48
+ bloom_draw_texture(texture.handle, x, y, tint.r, tint.g, tint.b, tint.a);
49
+ }
50
+
51
+ export function drawTextureRec(texture: Texture, source: Rect, position: { x: number; y: number }, tint: Color): void {
52
+ bloom_draw_texture_rec(texture.handle, source.x, source.y, source.width, source.height, position.x, position.y, tint.r, tint.g, tint.b, tint.a);
53
+ }
54
+
55
+ export function drawTexturePro(
56
+ texture: Texture, source: Rect, dest: Rect,
57
+ origin: { x: number; y: number }, rotation: number, tint: Color,
58
+ ): void {
59
+ bloom_draw_texture_pro(
60
+ texture.handle,
61
+ source.x, source.y, source.width, source.height,
62
+ dest.x, dest.y, dest.width, dest.height,
63
+ origin.x, origin.y, rotation,
64
+ tint.r, tint.g, tint.b, tint.a,
65
+ );
66
+ }
67
+
68
+ // Raw variant: takes primitives directly. Workaround for aarch64 Android
69
+ // Perry miscompilation where obj.field reads feeding f64 FFI args arrive as NaN.
70
+ export function drawTextureProRaw(
71
+ textureId: number,
72
+ sx: number, sy: number, sw: number, sh: number,
73
+ dx: number, dy: number, dw: number, dh: number,
74
+ ox: number, oy: number, rotation: number,
75
+ r: number, g: number, b: number, a: number,
76
+ ): void {
77
+ bloom_draw_texture_pro(textureId, sx, sy, sw, sh, dx, dy, dw, dh, ox, oy, rotation, r, g, b, a);
78
+ }
79
+
80
+ export function getTextureWidth(texture: Texture): number {
81
+ return texture.width;
82
+ }
83
+
84
+ export function getTextureHeight(texture: Texture): number {
85
+ return texture.height;
86
+ }
87
+
88
+ export function loadImage(path: string): number {
89
+ return bloom_load_image(path as any);
90
+ }
91
+
92
+ export function imageResize(imageHandle: number, width: number, height: number): void {
93
+ bloom_image_resize(imageHandle, width, height);
94
+ }
95
+
96
+ export function imageCrop(imageHandle: number, x: number, y: number, width: number, height: number): void {
97
+ bloom_image_crop(imageHandle, x, y, width, height);
98
+ }
99
+
100
+ export function imageFlipH(imageHandle: number): void {
101
+ bloom_image_flip_h(imageHandle);
102
+ }
103
+
104
+ export function imageFlipV(imageHandle: number): void {
105
+ bloom_image_flip_v(imageHandle);
106
+ }
107
+
108
+ export function loadTextureFromImage(imageHandle: number): Texture {
109
+ const id = bloom_load_texture_from_image(imageHandle);
110
+ const width = bloom_get_texture_width(id);
111
+ const height = bloom_get_texture_height(id);
112
+ return { handle: id, width, height };
113
+ }
114
+
115
+ export function genTextureMipmaps(texture: Texture): void {
116
+ bloom_gen_texture_mipmaps(texture.handle);
117
+ }
118
+
119
+ // Async / threaded loading
120
+
121
+ declare function bloom_stage_texture(path: number): number;
122
+ declare function bloom_commit_texture(handle: number): number;
123
+ declare function bloom_load_render_texture(width: number, height: number): number;
124
+ declare function bloom_unload_render_texture(handle: number): void;
125
+ declare function bloom_begin_texture_mode(handle: number): void;
126
+ declare function bloom_end_texture_mode(): void;
127
+ declare function bloom_get_render_texture_texture(handle: number): number;
128
+
129
+ export async function loadTextureAsync(path: string): Promise<Texture> {
130
+ const stagingHandle = await spawn(() => bloom_stage_texture(path as any));
131
+ const id = bloom_commit_texture(stagingHandle);
132
+ const width = bloom_get_texture_width(id);
133
+ const height = bloom_get_texture_height(id);
134
+ return { handle: id, width, height };
135
+ }
136
+
137
+ export function stageTextures(paths: string[]): number[] {
138
+ return parallelMap(paths, (path: string) => bloom_stage_texture(path as any));
139
+ }
140
+
141
+ export function commitTexture(stagingHandle: number): Texture {
142
+ const id = bloom_commit_texture(stagingHandle);
143
+ const width = bloom_get_texture_width(id);
144
+ const height = bloom_get_texture_height(id);
145
+ return { handle: id, width, height };
146
+ }
147
+
148
+ // ============================================================
149
+ // Q1: Offscreen Render Targets
150
+ // ============================================================
151
+
152
+ /**
153
+ * Create an offscreen render texture. Rendering commands between
154
+ * beginTextureMode and endTextureMode draw into this texture instead
155
+ * of the screen. Use getRenderTextureTexture to get a Texture for
156
+ * drawing the result via drawTexture.
157
+ *
158
+ * NOTE: GPU implementation is a stub in this version. The FFI surface
159
+ * is stable; the actual render-to-texture plumbing will land in a
160
+ * focused GPU session.
161
+ */
162
+ export function loadRenderTexture(width: number, height: number): number {
163
+ return bloom_load_render_texture(width, height);
164
+ }
165
+
166
+ export function unloadRenderTexture(handle: number): void {
167
+ bloom_unload_render_texture(handle);
168
+ }
169
+
170
+ export function beginTextureMode(handle: number): void {
171
+ bloom_begin_texture_mode(handle);
172
+ }
173
+
174
+ export function endTextureMode(): void {
175
+ bloom_end_texture_mode();
176
+ }
177
+
178
+ export function getRenderTextureTexture(handle: number): Texture {
179
+ // `handle`, not `id` — Texture renamed the field in v0.5 and this function
180
+ // was never migrated. Every draw call reads texture.handle, so the old
181
+ // `{ id }` shape fed `undefined` into a native f64 param the first time
182
+ // anyone drew a render texture (nobody had, until editor thumbnails).
183
+ // Width/height are 0 because the FFI only returns the texture id; callers
184
+ // pass explicit source rects.
185
+ const id = bloom_get_render_texture_texture(handle);
186
+ return { handle: id, width: 0, height: 0 };
187
+ }
@@ -0,0 +1,191 @@
1
+ // EN-026 particles + EN-027 decals.
2
+ //
3
+ // Both are engine-simulated and game-drawn. You supply the material (so the
4
+ // look stays authorable in WGSL) and the quad mesh; the engine owns the pool
5
+ // and rewrites a dynamic instance buffer every frame. Per-frame FFI traffic is
6
+ // therefore one `update` + one `draw` per system, regardless of how many
7
+ // thousand particles are live.
8
+ //
9
+ // The instanced vertex shader receives, per instance:
10
+ //
11
+ // @location(7) instance_pos: vec3<f32> world position
12
+ // @location(8) instance_rot_y: f32 roll (particles) / roll about
13
+ // the surface normal (decals)
14
+ // @location(9) instance_scale: f32 size in metres
15
+ // @location(10) instance_tint: vec4<f32> rgba, alpha already faded
16
+ // @location(11) instance_extra: vec3<f32> particles: (age01, frame, stretch)
17
+ // decals: (frame, azimuth, elevation)
18
+ //
19
+ // For decals the normal is packed as two angles, so reconstruct it with:
20
+ // let n = vec3(sin(el)*cos(az), cos(el), sin(el)*sin(az));
21
+
22
+ declare function bloom_particles_create(capacity: number): number;
23
+ declare function bloom_particles_configure(sys: number): void;
24
+ declare function bloom_particles_emit(sys: number, x: number, y: number, z: number, dx: number, dy: number, dz: number, count: number): void;
25
+ declare function bloom_particles_update(sys: number, dt: number): number;
26
+ declare function bloom_particles_instance_buffer(sys: number): number;
27
+ declare function bloom_particles_clear(sys: number): void;
28
+ declare function bloom_particles_live(sys: number): number;
29
+
30
+ declare function bloom_decals_init(capacity: number): number;
31
+ declare function bloom_decals_spawn(x: number, y: number, z: number, nx: number, ny: number, nz: number, size: number, roll: number): void;
32
+ declare function bloom_decals_set_style(frame: number, r: number, g: number, b: number, a: number, life: number, fade: number): void;
33
+ declare function bloom_decals_update(dt: number): number;
34
+ declare function bloom_decals_instance_buffer(): number;
35
+ declare function bloom_decals_clear(): void;
36
+
37
+ declare function bloom_mesh_scratch_reset(): void;
38
+ declare function bloom_mesh_scratch_push_f32(v: number): void;
39
+
40
+ /// How one system's particles are born, move and look. Every field has a
41
+ /// sane default; pass only what you care about.
42
+ export interface ParticleConfig {
43
+ /// Seconds. `lifeVar` jitters it symmetrically.
44
+ life?: number;
45
+ lifeVar?: number;
46
+ /// Initial speed along the emit direction, m/s.
47
+ speed?: number;
48
+ speedVar?: number;
49
+ /// Half-angle of the emission cone, radians. Emitting with a zero direction
50
+ /// ignores this and sprays into the full sphere.
51
+ spread?: number;
52
+ /// Constant acceleration, m/s². Default is real gravity.
53
+ gravity?: number;
54
+ /// Linear drag per second. Smoke wants ~2; a spark wants ~0.
55
+ drag?: number;
56
+ /// Size in metres at birth and at death — smoke grows, sparks shrink.
57
+ size0?: number;
58
+ size1?: number;
59
+ sizeVar?: number;
60
+ /// Colour at birth and at death. Put the fade-out in `color1`'s alpha.
61
+ color0?: [number, number, number, number];
62
+ color1?: [number, number, number, number];
63
+ /// Billboard roll, rad/s.
64
+ spin?: number;
65
+ spinVar?: number;
66
+ /// Spawn jitter radius, metres.
67
+ posJitter?: number;
68
+ /// > 0 stretches the quad along velocity by this many seconds of travel.
69
+ /// This is the difference between a round spark and a tracer streak.
70
+ stretch?: number;
71
+ /// Fraction of emitter velocity inherited (reserved; the emitter is
72
+ /// stateless today).
73
+ inherit?: number;
74
+ /// Atlas frames. The shader gets a frame index in `extra.y`.
75
+ frames?: number;
76
+ /// Bounce plane. `restitution` <= 0 (the default) means no collision;
77
+ /// shells want ~0.35 so they clatter instead of sinking.
78
+ floorY?: number;
79
+ restitution?: number;
80
+ }
81
+
82
+ /// Allocate a pool. One system per *look* (smoke, sparks, blood) — each wants
83
+ /// its own material and blend bucket anyway, and one draw per look is cheap.
84
+ export function createParticleSystem(capacity: number, cfg: ParticleConfig): number {
85
+ const sys = bloom_particles_create(capacity);
86
+ if (sys > 0) configureParticleSystem(sys, cfg);
87
+ return sys;
88
+ }
89
+
90
+ /// Re-tune a system at runtime. Config crosses via the mesh scratch (Perry
91
+ /// rejects JS arrays in pointer params); it is a startup-shaped call, not a
92
+ /// per-frame one.
93
+ export function configureParticleSystem(sys: number, cfg: ParticleConfig): void {
94
+ const c0 = cfg.color0 !== undefined ? cfg.color0 : [1, 1, 1, 1];
95
+ const c1 = cfg.color1 !== undefined ? cfg.color1 : [1, 1, 1, 0];
96
+ const p: number[] = new Array<number>(26);
97
+ p[0] = cfg.life !== undefined ? cfg.life : 1.0;
98
+ p[1] = cfg.lifeVar !== undefined ? cfg.lifeVar : 0.0;
99
+ p[2] = cfg.speed !== undefined ? cfg.speed : 1.0;
100
+ p[3] = cfg.speedVar !== undefined ? cfg.speedVar : 0.0;
101
+ p[4] = cfg.spread !== undefined ? cfg.spread : 0.3;
102
+ p[5] = cfg.gravity !== undefined ? cfg.gravity : -9.81;
103
+ p[6] = cfg.drag !== undefined ? cfg.drag : 0.0;
104
+ p[7] = cfg.size0 !== undefined ? cfg.size0 : 0.2;
105
+ p[8] = cfg.size1 !== undefined ? cfg.size1 : 0.2;
106
+ p[9] = cfg.sizeVar !== undefined ? cfg.sizeVar : 0.0;
107
+ p[10] = c0[0]; p[11] = c0[1]; p[12] = c0[2]; p[13] = c0[3];
108
+ p[14] = c1[0]; p[15] = c1[1]; p[16] = c1[2]; p[17] = c1[3];
109
+ p[18] = cfg.spin !== undefined ? cfg.spin : 0.0;
110
+ p[19] = cfg.spinVar !== undefined ? cfg.spinVar : 0.0;
111
+ p[20] = cfg.posJitter !== undefined ? cfg.posJitter : 0.0;
112
+ p[21] = cfg.stretch !== undefined ? cfg.stretch : 0.0;
113
+ p[22] = cfg.inherit !== undefined ? cfg.inherit : 0.0;
114
+ p[23] = cfg.frames !== undefined ? cfg.frames : 1.0;
115
+ p[24] = cfg.floorY !== undefined ? cfg.floorY : 0.0;
116
+ p[25] = cfg.restitution !== undefined ? cfg.restitution : 0.0;
117
+
118
+ bloom_mesh_scratch_reset();
119
+ for (let i = 0; i < 26; i++) bloom_mesh_scratch_push_f32(p[i]);
120
+ bloom_particles_configure(sys);
121
+ }
122
+
123
+ /// Spawn a burst. `dir` biases the cone — pass a surface normal for an impact,
124
+ /// or (0,0,0) for an omnidirectional pop.
125
+ export function emitParticles(
126
+ sys: number,
127
+ x: number, y: number, z: number,
128
+ dx: number, dy: number, dz: number,
129
+ count: number,
130
+ ): void {
131
+ bloom_particles_emit(sys, x, y, z, dx, dy, dz, count);
132
+ }
133
+
134
+ /// Integrate + upload. Returns the live count — pass it straight to
135
+ /// `drawMeshWithMaterialInstanced` as the instance count.
136
+ export function updateParticles(sys: number, dt: number): number {
137
+ return bloom_particles_update(sys, dt);
138
+ }
139
+
140
+ export function particleInstanceBuffer(sys: number): number {
141
+ return bloom_particles_instance_buffer(sys);
142
+ }
143
+
144
+ export function clearParticles(sys: number): void {
145
+ bloom_particles_clear(sys);
146
+ }
147
+
148
+ export function particleCount(sys: number): number {
149
+ return bloom_particles_live(sys);
150
+ }
151
+
152
+ // ---- Decals -----------------------------------------------------------------
153
+
154
+ /// Allocate the decal ring. One ring for the whole game: decals are all the
155
+ /// same draw (an oriented quad against an atlas), so they share a buffer and
156
+ /// the style selects which atlas cell a given spawn uses.
157
+ export function initDecals(capacity: number): number {
158
+ return bloom_decals_init(capacity);
159
+ }
160
+
161
+ /// Look + lifetime of subsequent `spawnDecal` calls. `life <= 0` = permanent
162
+ /// (until the ring wraps); `fade` is how many trailing seconds it fades over.
163
+ export function setDecalStyle(
164
+ frame: number,
165
+ r: number, g: number, b: number, a: number,
166
+ life: number, fade: number,
167
+ ): void {
168
+ bloom_decals_set_style(frame, r, g, b, a, life, fade);
169
+ }
170
+
171
+ /// Stick a decal to a surface. `n` is the surface normal (from your raycast);
172
+ /// `roll` spins it about that normal so repeated hits don't look stamped.
173
+ export function spawnDecal(
174
+ x: number, y: number, z: number,
175
+ nx: number, ny: number, nz: number,
176
+ size: number, roll: number,
177
+ ): void {
178
+ bloom_decals_spawn(x, y, z, nx, ny, nz, size, roll);
179
+ }
180
+
181
+ export function updateDecals(dt: number): number {
182
+ return bloom_decals_update(dt);
183
+ }
184
+
185
+ export function decalInstanceBuffer(): number {
186
+ return bloom_decals_instance_buffer();
187
+ }
188
+
189
+ export function clearDecals(): void {
190
+ bloom_decals_clear();
191
+ }
@@ -0,0 +1,24 @@
1
+ // Bloom shared world module.
2
+ //
3
+ // Defines the on-disk world/prefab schema that the Bloom world editor writes
4
+ // and every Bloom game reads. Games and the editor both import from this
5
+ // module via `import { ... } from 'bloom/world'`.
6
+ //
7
+ // Files:
8
+ // - types.ts schema interfaces (WorldData, PrefabData, ...)
9
+ // - version.ts schema version + migration
10
+ // - validate.ts runtime schema validation
11
+ // - loader.ts loadWorld / instantiateWorld (reads JSON, spawns scene nodes)
12
+ // - render.ts spawnWaterVolume / spawnRiver (shared by games + editor)
13
+ // - saver.ts saveWorld / savePrefab (writes JSON)
14
+ // - prefab.ts loadPrefab / expandPrefab / cycle detection
15
+ // - terrain.ts buildHeightmapMesh / sampleHeight / raycastTerrain / defaultTerrain
16
+
17
+ export * from './types';
18
+ export * from './version';
19
+ export * from './validate';
20
+ export * from './loader';
21
+ export * from './render';
22
+ export * from './saver';
23
+ export * from './prefab';
24
+ export * from './terrain';