@bloomengine/engine 0.3.1

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 (562) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/native/android/Cargo.lock +1848 -0
  4. package/native/android/Cargo.toml +20 -0
  5. package/native/android/src/lib.rs +1747 -0
  6. package/native/ios/Cargo.lock +1688 -0
  7. package/native/ios/Cargo.toml +19 -0
  8. package/native/ios/src/lib.rs +2258 -0
  9. package/native/linux/Cargo.lock +1719 -0
  10. package/native/linux/Cargo.toml +22 -0
  11. package/native/linux/src/lib.rs +2236 -0
  12. package/native/macos/Cargo.lock +3310 -0
  13. package/native/macos/Cargo.toml +29 -0
  14. package/native/macos/src/lib.rs +3444 -0
  15. package/native/shared/Cargo.lock +1898 -0
  16. package/native/shared/Cargo.toml +42 -0
  17. package/native/shared/assets/default_font.ttf +0 -0
  18. package/native/shared/build.rs +77 -0
  19. package/native/shared/shaders/common/fog.wgsl +16 -0
  20. package/native/shared/shaders/common/imposter.wgsl +112 -0
  21. package/native/shared/shaders/common/pbr.wgsl +186 -0
  22. package/native/shared/shaders/common/shadows.wgsl +77 -0
  23. package/native/shared/shaders/common/sky.wgsl +8 -0
  24. package/native/shared/shaders/common/tonemap.wgsl +25 -0
  25. package/native/shared/shaders/impulse_field.wgsl +53 -0
  26. package/native/shared/shaders/material_abi.wgsl +360 -0
  27. package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
  28. package/native/shared/src/audio.rs +363 -0
  29. package/native/shared/src/custom_shaders.rs +104 -0
  30. package/native/shared/src/drs.rs +211 -0
  31. package/native/shared/src/engine.rs +186 -0
  32. package/native/shared/src/frame_callbacks.rs +88 -0
  33. package/native/shared/src/geometry.rs +236 -0
  34. package/native/shared/src/handles.rs +76 -0
  35. package/native/shared/src/input.rs +273 -0
  36. package/native/shared/src/jolt_sys.rs +822 -0
  37. package/native/shared/src/lib.rs +43 -0
  38. package/native/shared/src/models.rs +1941 -0
  39. package/native/shared/src/physics_jolt.rs +1528 -0
  40. package/native/shared/src/picking.rs +298 -0
  41. package/native/shared/src/postfx.rs +339 -0
  42. package/native/shared/src/profiler.rs +416 -0
  43. package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
  44. package/native/shared/src/renderer/brdf_lut.rs +154 -0
  45. package/native/shared/src/renderer/formats.rs +778 -0
  46. package/native/shared/src/renderer/graph.rs +465 -0
  47. package/native/shared/src/renderer/hot_reload.rs +390 -0
  48. package/native/shared/src/renderer/impulse_field.rs +455 -0
  49. package/native/shared/src/renderer/material_pipeline.rs +604 -0
  50. package/native/shared/src/renderer/material_system.rs +2106 -0
  51. package/native/shared/src/renderer/mod.rs +13923 -0
  52. package/native/shared/src/renderer/planar_reflection.rs +458 -0
  53. package/native/shared/src/renderer/post_pass.rs +249 -0
  54. package/native/shared/src/renderer/shader_include.rs +205 -0
  55. package/native/shared/src/renderer/shader_library.rs +134 -0
  56. package/native/shared/src/renderer/shaders.rs +5855 -0
  57. package/native/shared/src/renderer/transient.rs +576 -0
  58. package/native/shared/src/renderer/types.rs +259 -0
  59. package/native/shared/src/renderer/util.rs +151 -0
  60. package/native/shared/src/scene.rs +1066 -0
  61. package/native/shared/src/sdf_cache.rs +274 -0
  62. package/native/shared/src/shadows.rs +551 -0
  63. package/native/shared/src/staging.rs +90 -0
  64. package/native/shared/src/string_header.rs +35 -0
  65. package/native/shared/src/text_renderer.rs +456 -0
  66. package/native/shared/src/textures.rs +154 -0
  67. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.cpp +242 -0
  68. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.h +121 -0
  69. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeToBuffer.h +296 -0
  70. package/native/third_party/JoltPhysics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h +323 -0
  71. package/native/third_party/JoltPhysics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h +555 -0
  72. package/native/third_party/JoltPhysics/Jolt/ConfigurationString.h +112 -0
  73. package/native/third_party/JoltPhysics/Jolt/Core/ARMNeon.h +94 -0
  74. package/native/third_party/JoltPhysics/Jolt/Core/Array.h +713 -0
  75. package/native/third_party/JoltPhysics/Jolt/Core/Atomics.h +44 -0
  76. package/native/third_party/JoltPhysics/Jolt/Core/BinaryHeap.h +96 -0
  77. package/native/third_party/JoltPhysics/Jolt/Core/ByteBuffer.h +74 -0
  78. package/native/third_party/JoltPhysics/Jolt/Core/Color.cpp +38 -0
  79. package/native/third_party/JoltPhysics/Jolt/Core/Color.h +98 -0
  80. package/native/third_party/JoltPhysics/Jolt/Core/Core.h +652 -0
  81. package/native/third_party/JoltPhysics/Jolt/Core/FPControlWord.h +143 -0
  82. package/native/third_party/JoltPhysics/Jolt/Core/FPException.h +96 -0
  83. package/native/third_party/JoltPhysics/Jolt/Core/FPFlushDenormals.h +43 -0
  84. package/native/third_party/JoltPhysics/Jolt/Core/Factory.cpp +92 -0
  85. package/native/third_party/JoltPhysics/Jolt/Core/Factory.h +54 -0
  86. package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.h +122 -0
  87. package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.inl +215 -0
  88. package/native/third_party/JoltPhysics/Jolt/Core/HashCombine.h +234 -0
  89. package/native/third_party/JoltPhysics/Jolt/Core/HashTable.h +876 -0
  90. package/native/third_party/JoltPhysics/Jolt/Core/InsertionSort.h +58 -0
  91. package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.cpp +27 -0
  92. package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.h +38 -0
  93. package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.h +311 -0
  94. package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.inl +56 -0
  95. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.cpp +65 -0
  96. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.h +62 -0
  97. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.cpp +364 -0
  98. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.h +101 -0
  99. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.cpp +230 -0
  100. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.h +85 -0
  101. package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.cpp +51 -0
  102. package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.h +67 -0
  103. package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.h +182 -0
  104. package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.inl +351 -0
  105. package/native/third_party/JoltPhysics/Jolt/Core/Memory.cpp +85 -0
  106. package/native/third_party/JoltPhysics/Jolt/Core/Memory.h +85 -0
  107. package/native/third_party/JoltPhysics/Jolt/Core/Mutex.h +223 -0
  108. package/native/third_party/JoltPhysics/Jolt/Core/MutexArray.h +98 -0
  109. package/native/third_party/JoltPhysics/Jolt/Core/NonCopyable.h +18 -0
  110. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.cpp +677 -0
  111. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.h +301 -0
  112. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.inl +90 -0
  113. package/native/third_party/JoltPhysics/Jolt/Core/QuickSort.h +137 -0
  114. package/native/third_party/JoltPhysics/Jolt/Core/RTTI.cpp +149 -0
  115. package/native/third_party/JoltPhysics/Jolt/Core/RTTI.h +436 -0
  116. package/native/third_party/JoltPhysics/Jolt/Core/Reference.h +244 -0
  117. package/native/third_party/JoltPhysics/Jolt/Core/Result.h +174 -0
  118. package/native/third_party/JoltPhysics/Jolt/Core/STLAlignedAllocator.h +72 -0
  119. package/native/third_party/JoltPhysics/Jolt/Core/STLAllocator.h +127 -0
  120. package/native/third_party/JoltPhysics/Jolt/Core/STLLocalAllocator.h +170 -0
  121. package/native/third_party/JoltPhysics/Jolt/Core/STLTempAllocator.h +80 -0
  122. package/native/third_party/JoltPhysics/Jolt/Core/ScopeExit.h +49 -0
  123. package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.cpp +135 -0
  124. package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.h +68 -0
  125. package/native/third_party/JoltPhysics/Jolt/Core/StaticArray.h +329 -0
  126. package/native/third_party/JoltPhysics/Jolt/Core/StreamIn.h +120 -0
  127. package/native/third_party/JoltPhysics/Jolt/Core/StreamOut.h +97 -0
  128. package/native/third_party/JoltPhysics/Jolt/Core/StreamUtils.h +168 -0
  129. package/native/third_party/JoltPhysics/Jolt/Core/StreamWrapper.h +53 -0
  130. package/native/third_party/JoltPhysics/Jolt/Core/StridedPtr.h +63 -0
  131. package/native/third_party/JoltPhysics/Jolt/Core/StringTools.cpp +101 -0
  132. package/native/third_party/JoltPhysics/Jolt/Core/StringTools.h +38 -0
  133. package/native/third_party/JoltPhysics/Jolt/Core/TempAllocator.h +209 -0
  134. package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.cpp +37 -0
  135. package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.h +58 -0
  136. package/native/third_party/JoltPhysics/Jolt/Core/UnorderedMap.h +80 -0
  137. package/native/third_party/JoltPhysics/Jolt/Core/UnorderedSet.h +32 -0
  138. package/native/third_party/JoltPhysics/Jolt/Geometry/AABox.h +313 -0
  139. package/native/third_party/JoltPhysics/Jolt/Geometry/AABox4.h +224 -0
  140. package/native/third_party/JoltPhysics/Jolt/Geometry/ClipPoly.h +200 -0
  141. package/native/third_party/JoltPhysics/Jolt/Geometry/ClosestPoint.h +498 -0
  142. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.cpp +1467 -0
  143. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.h +276 -0
  144. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.cpp +335 -0
  145. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.h +105 -0
  146. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexSupport.h +188 -0
  147. package/native/third_party/JoltPhysics/Jolt/Geometry/EPAConvexHullBuilder.h +845 -0
  148. package/native/third_party/JoltPhysics/Jolt/Geometry/EPAPenetrationDepth.h +557 -0
  149. package/native/third_party/JoltPhysics/Jolt/Geometry/Ellipse.h +77 -0
  150. package/native/third_party/JoltPhysics/Jolt/Geometry/GJKClosestPoint.h +945 -0
  151. package/native/third_party/JoltPhysics/Jolt/Geometry/IndexedTriangle.h +130 -0
  152. package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.cpp +222 -0
  153. package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.h +19 -0
  154. package/native/third_party/JoltPhysics/Jolt/Geometry/MortonCode.h +40 -0
  155. package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.cpp +178 -0
  156. package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.h +39 -0
  157. package/native/third_party/JoltPhysics/Jolt/Geometry/Plane.h +104 -0
  158. package/native/third_party/JoltPhysics/Jolt/Geometry/RayAABox.h +241 -0
  159. package/native/third_party/JoltPhysics/Jolt/Geometry/RayCapsule.h +37 -0
  160. package/native/third_party/JoltPhysics/Jolt/Geometry/RayCylinder.h +101 -0
  161. package/native/third_party/JoltPhysics/Jolt/Geometry/RaySphere.h +96 -0
  162. package/native/third_party/JoltPhysics/Jolt/Geometry/RayTriangle.h +158 -0
  163. package/native/third_party/JoltPhysics/Jolt/Geometry/Sphere.h +72 -0
  164. package/native/third_party/JoltPhysics/Jolt/Geometry/Triangle.h +34 -0
  165. package/native/third_party/JoltPhysics/Jolt/Jolt.cmake +703 -0
  166. package/native/third_party/JoltPhysics/Jolt/Jolt.h +16 -0
  167. package/native/third_party/JoltPhysics/Jolt/Jolt.natvis +116 -0
  168. package/native/third_party/JoltPhysics/Jolt/Math/BVec16.h +99 -0
  169. package/native/third_party/JoltPhysics/Jolt/Math/BVec16.inl +177 -0
  170. package/native/third_party/JoltPhysics/Jolt/Math/DMat44.h +158 -0
  171. package/native/third_party/JoltPhysics/Jolt/Math/DMat44.inl +310 -0
  172. package/native/third_party/JoltPhysics/Jolt/Math/DVec3.h +291 -0
  173. package/native/third_party/JoltPhysics/Jolt/Math/DVec3.inl +941 -0
  174. package/native/third_party/JoltPhysics/Jolt/Math/Double3.h +48 -0
  175. package/native/third_party/JoltPhysics/Jolt/Math/DynMatrix.h +31 -0
  176. package/native/third_party/JoltPhysics/Jolt/Math/EigenValueSymmetric.h +177 -0
  177. package/native/third_party/JoltPhysics/Jolt/Math/FindRoot.h +42 -0
  178. package/native/third_party/JoltPhysics/Jolt/Math/Float2.h +36 -0
  179. package/native/third_party/JoltPhysics/Jolt/Math/Float3.h +50 -0
  180. package/native/third_party/JoltPhysics/Jolt/Math/Float4.h +44 -0
  181. package/native/third_party/JoltPhysics/Jolt/Math/GaussianElimination.h +102 -0
  182. package/native/third_party/JoltPhysics/Jolt/Math/HalfFloat.h +208 -0
  183. package/native/third_party/JoltPhysics/Jolt/Math/Mat44.h +243 -0
  184. package/native/third_party/JoltPhysics/Jolt/Math/Mat44.inl +952 -0
  185. package/native/third_party/JoltPhysics/Jolt/Math/Math.h +208 -0
  186. package/native/third_party/JoltPhysics/Jolt/Math/MathTypes.h +32 -0
  187. package/native/third_party/JoltPhysics/Jolt/Math/Matrix.h +259 -0
  188. package/native/third_party/JoltPhysics/Jolt/Math/Quat.h +268 -0
  189. package/native/third_party/JoltPhysics/Jolt/Math/Quat.inl +406 -0
  190. package/native/third_party/JoltPhysics/Jolt/Math/Real.h +44 -0
  191. package/native/third_party/JoltPhysics/Jolt/Math/Swizzle.h +19 -0
  192. package/native/third_party/JoltPhysics/Jolt/Math/Trigonometry.h +79 -0
  193. package/native/third_party/JoltPhysics/Jolt/Math/UVec4.h +232 -0
  194. package/native/third_party/JoltPhysics/Jolt/Math/UVec4.inl +636 -0
  195. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.cpp +71 -0
  196. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.h +308 -0
  197. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.inl +942 -0
  198. package/native/third_party/JoltPhysics/Jolt/Math/Vec4.h +320 -0
  199. package/native/third_party/JoltPhysics/Jolt/Math/Vec4.inl +1152 -0
  200. package/native/third_party/JoltPhysics/Jolt/Math/Vector.h +211 -0
  201. package/native/third_party/JoltPhysics/Jolt/ObjectStream/GetPrimitiveTypeOfType.h +54 -0
  202. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.cpp +38 -0
  203. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.h +337 -0
  204. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.cpp +252 -0
  205. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.h +57 -0
  206. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.cpp +165 -0
  207. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.h +57 -0
  208. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.cpp +635 -0
  209. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.h +148 -0
  210. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.cpp +166 -0
  211. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.h +101 -0
  212. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.cpp +418 -0
  213. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.h +55 -0
  214. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.cpp +255 -0
  215. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.h +62 -0
  216. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTypes.h +26 -0
  217. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttribute.h +111 -0
  218. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeEnum.h +67 -0
  219. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeTyped.h +60 -0
  220. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.cpp +15 -0
  221. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.h +170 -0
  222. package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.cpp +70 -0
  223. package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.h +45 -0
  224. package/native/third_party/JoltPhysics/Jolt/Physics/Body/AllowedDOFs.h +68 -0
  225. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.cpp +426 -0
  226. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.h +452 -0
  227. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.inl +197 -0
  228. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyAccess.h +68 -0
  229. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyActivationListener.h +28 -0
  230. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.cpp +234 -0
  231. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.h +124 -0
  232. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyFilter.h +130 -0
  233. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyID.h +101 -0
  234. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.cpp +1099 -0
  235. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.h +324 -0
  236. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLock.h +111 -0
  237. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockInterface.h +134 -0
  238. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockMulti.h +120 -0
  239. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.cpp +1220 -0
  240. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.h +403 -0
  241. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyPair.h +36 -0
  242. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyType.h +19 -0
  243. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.cpp +185 -0
  244. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.h +58 -0
  245. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.cpp +92 -0
  246. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.h +308 -0
  247. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.inl +178 -0
  248. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionQuality.h +31 -0
  249. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionType.h +17 -0
  250. package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.cpp +354 -0
  251. package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.h +159 -0
  252. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.cpp +59 -0
  253. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.h +157 -0
  254. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterID.h +98 -0
  255. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.cpp +1933 -0
  256. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.h +752 -0
  257. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/AABoxCast.h +20 -0
  258. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdgeMode.h +17 -0
  259. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdges.h +114 -0
  260. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BackFaceMode.h +16 -0
  261. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.cpp +16 -0
  262. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h +109 -0
  263. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp +313 -0
  264. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h +38 -0
  265. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h +148 -0
  266. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceMask.h +92 -0
  267. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceTable.h +64 -0
  268. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp +629 -0
  269. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h +108 -0
  270. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuery.h +56 -0
  271. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterMask.h +35 -0
  272. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterTable.h +66 -0
  273. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp +1768 -0
  274. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.h +389 -0
  275. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.cpp +107 -0
  276. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.h +46 -0
  277. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastResult.h +37 -0
  278. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp +223 -0
  279. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.h +49 -0
  280. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollectFacesMode.h +16 -0
  281. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.cpp +155 -0
  282. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.h +56 -0
  283. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollidePointResult.h +25 -0
  284. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShape.h +106 -0
  285. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShapeVsShapePerLeaf.h +94 -0
  286. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVertexIterator.h +110 -0
  287. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVerticesVsTriangles.h +102 -0
  288. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.cpp +121 -0
  289. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.h +50 -0
  290. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollector.h +109 -0
  291. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollectorImpl.h +219 -0
  292. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.cpp +107 -0
  293. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.h +97 -0
  294. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.cpp +35 -0
  295. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.h +97 -0
  296. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ContactListener.h +143 -0
  297. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.cpp +213 -0
  298. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.h +48 -0
  299. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.cpp +32 -0
  300. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.h +46 -0
  301. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.cpp +38 -0
  302. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.h +130 -0
  303. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h +279 -0
  304. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.cpp +271 -0
  305. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.h +44 -0
  306. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp +448 -0
  307. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.h +77 -0
  308. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.cpp +62 -0
  309. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.h +110 -0
  310. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayer.h +111 -0
  311. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterMask.h +52 -0
  312. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterTable.h +78 -0
  313. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.cpp +35 -0
  314. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.h +57 -0
  315. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.cpp +38 -0
  316. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.h +37 -0
  317. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/RayCast.h +87 -0
  318. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.cpp +318 -0
  319. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.h +115 -0
  320. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.cpp +438 -0
  321. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.h +129 -0
  322. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.cpp +433 -0
  323. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.h +354 -0
  324. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShapeVisitors.h +461 -0
  325. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp +1311 -0
  326. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.h +202 -0
  327. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.cpp +566 -0
  328. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.h +150 -0
  329. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.cpp +418 -0
  330. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.h +126 -0
  331. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.cpp +87 -0
  332. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.h +80 -0
  333. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.cpp +64 -0
  334. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.h +75 -0
  335. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/GetTrianglesContext.h +248 -0
  336. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp +2754 -0
  337. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.h +380 -0
  338. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.cpp +1305 -0
  339. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.h +228 -0
  340. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.cpp +596 -0
  341. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.h +176 -0
  342. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp +217 -0
  343. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h +140 -0
  344. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.cpp +541 -0
  345. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.h +147 -0
  346. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PolyhedronSubmergedVolumeCalculator.h +319 -0
  347. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp +333 -0
  348. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h +161 -0
  349. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaleHelpers.h +83 -0
  350. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.cpp +238 -0
  351. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.h +145 -0
  352. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.cpp +325 -0
  353. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.h +466 -0
  354. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.cpp +347 -0
  355. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.h +125 -0
  356. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.cpp +674 -0
  357. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.h +139 -0
  358. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeID.h +138 -0
  359. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h +65 -0
  360. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp +453 -0
  361. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.gliffy +1 -0
  362. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h +135 -0
  363. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp +691 -0
  364. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.h +132 -0
  365. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.cpp +430 -0
  366. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.h +143 -0
  367. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeCast.h +173 -0
  368. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeFilter.h +73 -0
  369. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilter.h +40 -0
  370. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilterWrapper.h +58 -0
  371. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SortReverseAndStore.h +48 -0
  372. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.cpp +180 -0
  373. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.h +194 -0
  374. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/CalculateSolverSteps.h +70 -0
  375. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.cpp +246 -0
  376. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.h +133 -0
  377. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.cpp +73 -0
  378. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.h +243 -0
  379. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.cpp +289 -0
  380. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.h +100 -0
  381. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AngleConstraintPart.h +257 -0
  382. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h +682 -0
  383. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h +276 -0
  384. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/GearConstraintPart.h +195 -0
  385. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h +222 -0
  386. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/IndependentAxisConstraintPart.h +246 -0
  387. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/PointConstraintPart.h +239 -0
  388. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RackAndPinionConstraintPart.h +196 -0
  389. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h +283 -0
  390. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationQuatConstraintPart.h +246 -0
  391. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SpringPart.h +169 -0
  392. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h +597 -0
  393. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.cpp +1804 -0
  394. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.h +524 -0
  395. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.cpp +266 -0
  396. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.h +120 -0
  397. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.cpp +215 -0
  398. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.h +96 -0
  399. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.cpp +188 -0
  400. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.h +116 -0
  401. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.cpp +443 -0
  402. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.h +205 -0
  403. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.cpp +43 -0
  404. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.h +66 -0
  405. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.cpp +458 -0
  406. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.h +191 -0
  407. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.cpp +85 -0
  408. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.h +76 -0
  409. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.cpp +308 -0
  410. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.h +54 -0
  411. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.cpp +157 -0
  412. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.h +94 -0
  413. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.cpp +253 -0
  414. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.h +137 -0
  415. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.cpp +189 -0
  416. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.h +118 -0
  417. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.cpp +900 -0
  418. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.h +289 -0
  419. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.cpp +501 -0
  420. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.h +198 -0
  421. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.cpp +35 -0
  422. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.h +70 -0
  423. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.cpp +524 -0
  424. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.h +197 -0
  425. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.cpp +56 -0
  426. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.h +65 -0
  427. package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.cpp +17 -0
  428. package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.h +159 -0
  429. package/native/third_party/JoltPhysics/Jolt/Physics/EActivation.h +16 -0
  430. package/native/third_party/JoltPhysics/Jolt/Physics/EPhysicsUpdateError.h +37 -0
  431. package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.cpp +492 -0
  432. package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.h +144 -0
  433. package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.cpp +582 -0
  434. package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.h +187 -0
  435. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsLock.h +169 -0
  436. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.cpp +261 -0
  437. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.h +104 -0
  438. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSettings.h +125 -0
  439. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsStepListener.h +37 -0
  440. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.cpp +2915 -0
  441. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.h +391 -0
  442. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.cpp +25 -0
  443. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.h +176 -0
  444. package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.cpp +744 -0
  445. package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.h +245 -0
  446. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyContactListener.h +55 -0
  447. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp +128 -0
  448. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.h +75 -0
  449. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyManifold.h +74 -0
  450. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp +1501 -0
  451. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h +333 -0
  452. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.cpp +354 -0
  453. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.h +73 -0
  454. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp +1487 -0
  455. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h +390 -0
  456. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyUpdateContext.h +63 -0
  457. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyVertex.h +36 -0
  458. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorder.h +136 -0
  459. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.cpp +90 -0
  460. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.h +50 -0
  461. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.cpp +306 -0
  462. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.h +119 -0
  463. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.cpp +547 -0
  464. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.h +169 -0
  465. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.cpp +33 -0
  466. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.h +33 -0
  467. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.cpp +376 -0
  468. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.h +146 -0
  469. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.cpp +703 -0
  470. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.h +252 -0
  471. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.cpp +17 -0
  472. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.h +87 -0
  473. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.cpp +81 -0
  474. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.h +39 -0
  475. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.cpp +122 -0
  476. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.h +93 -0
  477. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.cpp +52 -0
  478. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.h +56 -0
  479. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.cpp +159 -0
  480. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.h +87 -0
  481. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.cpp +93 -0
  482. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.h +148 -0
  483. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.cpp +866 -0
  484. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.h +205 -0
  485. package/native/third_party/JoltPhysics/Jolt/RegisterTypes.cpp +204 -0
  486. package/native/third_party/JoltPhysics/Jolt/RegisterTypes.h +29 -0
  487. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.cpp +1107 -0
  488. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.h +383 -0
  489. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.cpp +168 -0
  490. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.h +48 -0
  491. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.cpp +158 -0
  492. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.h +130 -0
  493. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.cpp +80 -0
  494. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.h +88 -0
  495. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.cpp +165 -0
  496. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.h +91 -0
  497. package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.cpp +82 -0
  498. package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.h +72 -0
  499. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.cpp +237 -0
  500. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.h +145 -0
  501. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.cpp +87 -0
  502. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.h +82 -0
  503. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.cpp +73 -0
  504. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.h +84 -0
  505. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.cpp +139 -0
  506. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.h +52 -0
  507. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.cpp +43 -0
  508. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.h +28 -0
  509. package/native/third_party/JoltPhysics/LICENSE +7 -0
  510. package/native/third_party/JoltPhysics/README.md +173 -0
  511. package/native/third_party/bloom_jolt/CMakeLists.txt +78 -0
  512. package/native/third_party/bloom_jolt/include/bloom_jolt.h +519 -0
  513. package/native/third_party/bloom_jolt/src/bloom_jolt.cpp +1780 -0
  514. package/native/tvos/Cargo.lock +1692 -0
  515. package/native/tvos/Cargo.toml +22 -0
  516. package/native/tvos/src/lib.rs +3179 -0
  517. package/native/watchos/Cargo.lock +16 -0
  518. package/native/watchos/Cargo.toml +19 -0
  519. package/native/watchos/shaders/bloom_postfx.metal +99 -0
  520. package/native/watchos/src/BloomWatchApp.swift +1236 -0
  521. package/native/watchos/src/BloomWatchAudio.swift +179 -0
  522. package/native/watchos/src/audio.rs +55 -0
  523. package/native/watchos/src/draw_list.rs +223 -0
  524. package/native/watchos/src/ffi_stubs.rs +454 -0
  525. package/native/watchos/src/lib.rs +1013 -0
  526. package/native/watchos/src/models.rs +746 -0
  527. package/native/watchos/src/postfx.rs +91 -0
  528. package/native/watchos/src/scene.rs +534 -0
  529. package/native/watchos/src/textures.rs +184 -0
  530. package/native/web/Cargo.lock +1656 -0
  531. package/native/web/Cargo.toml +38 -0
  532. package/native/web/bloom_glue.js +218 -0
  533. package/native/web/build.sh +101 -0
  534. package/native/web/index.html +390 -0
  535. package/native/web/jolt_bridge.js +1311 -0
  536. package/native/web/src/lib.rs +2739 -0
  537. package/native/windows/Cargo.lock +1813 -0
  538. package/native/windows/Cargo.toml +31 -0
  539. package/native/windows/src/lib.rs +1933 -0
  540. package/package.json +558 -0
  541. package/src/audio/index.ts +151 -0
  542. package/src/core/colors.ts +56 -0
  543. package/src/core/index.ts +903 -0
  544. package/src/core/keys.ts +63 -0
  545. package/src/core/types.ts +102 -0
  546. package/src/index.ts +158 -0
  547. package/src/math/index.ts +502 -0
  548. package/src/mobile/index.ts +294 -0
  549. package/src/models/index.ts +859 -0
  550. package/src/physics/index.ts +1072 -0
  551. package/src/scene/index.ts +570 -0
  552. package/src/shapes/index.ts +120 -0
  553. package/src/text/index.ts +48 -0
  554. package/src/textures/index.ts +173 -0
  555. package/src/world/index.ts +22 -0
  556. package/src/world/loader.ts +385 -0
  557. package/src/world/prefab.ts +205 -0
  558. package/src/world/saver.ts +61 -0
  559. package/src/world/terrain.ts +254 -0
  560. package/src/world/types.ts +136 -0
  561. package/src/world/validate.ts +202 -0
  562. package/src/world/version.ts +47 -0
@@ -0,0 +1,1747 @@
1
+ use bloom_shared::engine::EngineState;
2
+ use bloom_shared::renderer::Renderer;
3
+ use bloom_shared::string_header::str_from_header;
4
+ use bloom_shared::audio::{parse_wav, parse_ogg, parse_mp3};
5
+
6
+ use std::sync::OnceLock;
7
+ use std::sync::atomic::{AtomicBool, Ordering};
8
+
9
+ static mut ENGINE: OnceLock<EngineState> = OnceLock::new();
10
+ static mut NATIVE_WINDOW: *mut libc::c_void = std::ptr::null_mut();
11
+ static AUDIO_RUNNING: AtomicBool = AtomicBool::new(false);
12
+ static mut ASSET_BASE_PATH: Option<String> = None;
13
+
14
+ fn engine() -> &'static mut EngineState {
15
+ unsafe { ENGINE.get_mut().expect("Engine not initialized") }
16
+ }
17
+
18
+ /// Resolve relative asset paths to the app's base asset directory.
19
+ /// On Android, relative paths like "assets/models/tree.glb" won't resolve
20
+ /// because the working directory isn't the app's data directory.
21
+ fn resolve_path(path: &str) -> String {
22
+ if path.starts_with('/') {
23
+ return path.to_string();
24
+ }
25
+ unsafe {
26
+ if let Some(ref base) = ASSET_BASE_PATH {
27
+ format!("{}/{}", base, path)
28
+ } else {
29
+ path.to_string()
30
+ }
31
+ }
32
+ }
33
+
34
+ /// Called by the Android Activity to set the base path for asset resolution.
35
+ /// Should be set to the app's files directory where assets are extracted.
36
+ #[no_mangle]
37
+ pub extern "C" fn bloom_android_set_asset_path(path_ptr: *const u8) {
38
+ let path = str_from_header(path_ptr);
39
+ unsafe {
40
+ ASSET_BASE_PATH = Some(path.to_string());
41
+ }
42
+ }
43
+
44
+ // ============================================================
45
+ // ANativeWindow FFI
46
+ // ============================================================
47
+
48
+ extern "C" {
49
+ fn ANativeWindow_getWidth(window: *mut libc::c_void) -> i32;
50
+ fn ANativeWindow_getHeight(window: *mut libc::c_void) -> i32;
51
+ fn ANativeWindow_acquire(window: *mut libc::c_void);
52
+ fn ANativeWindow_release(window: *mut libc::c_void);
53
+ }
54
+
55
+ /// Called by Perry's Android runtime to set the ANativeWindow pointer
56
+ /// before bloom_init_window is invoked.
57
+ #[no_mangle]
58
+ pub extern "C" fn bloom_android_set_native_window(window: *mut libc::c_void) {
59
+ unsafe {
60
+ if !window.is_null() {
61
+ ANativeWindow_acquire(window);
62
+ }
63
+ NATIVE_WINDOW = window;
64
+ }
65
+ }
66
+
67
+ fn pollster_block_on<F: std::future::Future>(future: F) -> F::Output {
68
+ use std::task::{Context, Poll, Wake, Waker};
69
+ use std::pin::Pin;
70
+ use std::sync::Arc;
71
+ struct NoopWaker;
72
+ impl Wake for NoopWaker { fn wake(self: Arc<Self>) {} }
73
+ let waker = Waker::from(Arc::new(NoopWaker));
74
+ let mut cx = Context::from_waker(&waker);
75
+ let mut future = unsafe { Pin::new_unchecked(Box::new(future)) };
76
+ loop {
77
+ match future.as_mut().poll(&mut cx) {
78
+ Poll::Ready(result) => return result,
79
+ Poll::Pending => std::thread::yield_now(),
80
+ }
81
+ }
82
+ }
83
+
84
+ // ============================================================
85
+ // Window + Renderer init
86
+ // ============================================================
87
+
88
+ #[no_mangle]
89
+ pub extern "C" fn bloom_init_window(width: f64, height: f64, title_ptr: *const u8, _fullscreen: f64) {
90
+ let _title = str_from_header(title_ptr);
91
+
92
+ unsafe {
93
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"bloom_init_window: starting\0".as_ptr());
94
+ let window = NATIVE_WINDOW;
95
+ // If no native window was set, use requested dimensions with a headless surface
96
+ let (pixel_w, pixel_h) = if !window.is_null() {
97
+ (ANativeWindow_getWidth(window) as u32, ANativeWindow_getHeight(window) as u32)
98
+ } else {
99
+ (width as u32, height as u32)
100
+ };
101
+ // Logical size is half of physical: the game UI (fonts, layout constants)
102
+ // was sized for ~1170×540 landscape (iPhone-sized); on Android's 2340×1080
103
+ // panel we'd otherwise render at native pixel size and everything looks
104
+ // half-scale. wgpu still renders to the full physical surface; only the
105
+ // `screen_width`/`screen_height` the game sees are halved.
106
+ let logical_w = (pixel_w / 2).max(1);
107
+ let logical_h = (pixel_h / 2).max(1);
108
+
109
+ let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
110
+ backends: wgpu::Backends::VULKAN | wgpu::Backends::GL,
111
+ flags: wgpu::InstanceFlags::default(),
112
+ ..wgpu::InstanceDescriptor::new_without_display_handle()
113
+ });
114
+
115
+ // Create surface from ANativeWindow
116
+ if window.is_null() {
117
+ // Fallback: can't render without a window, but don't panic
118
+ // Create a minimal engine state (game logic will work, rendering will no-op)
119
+ return;
120
+ }
121
+
122
+ let handle = raw_window_handle::AndroidNdkWindowHandle::new(
123
+ std::ptr::NonNull::new(window).unwrap()
124
+ );
125
+ let raw = raw_window_handle::RawWindowHandle::AndroidNdk(handle);
126
+ let surface = instance.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::RawHandle {
127
+ raw_display_handle: Some(raw_window_handle::RawDisplayHandle::Android(
128
+ raw_window_handle::AndroidDisplayHandle::new()
129
+ )),
130
+ raw_window_handle: raw,
131
+ }).expect("Failed to create surface");
132
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"bloom_init_window: surface created\0".as_ptr());
133
+
134
+ let adapter = pollster_block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
135
+ compatible_surface: Some(&surface),
136
+ power_preference: wgpu::PowerPreference::HighPerformance,
137
+ ..Default::default()
138
+ }));
139
+ let adapter = match adapter {
140
+ Ok(a) => a,
141
+ Err(_) => {
142
+ // Try again without surface compatibility requirement
143
+ match pollster_block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
144
+ power_preference: wgpu::PowerPreference::HighPerformance,
145
+ ..Default::default()
146
+ })) {
147
+ Ok(a) => a,
148
+ Err(_) => panic!("No GPU adapter found"),
149
+ }
150
+ }
151
+ };
152
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"bloom_init_window: adapter found\0".as_ptr());
153
+ {
154
+ let info = adapter.get_info();
155
+ let msg = std::ffi::CString::new(format!(
156
+ "adapter: name='{}' backend={:?} device_type={:?} driver='{}' driver_info='{}'",
157
+ info.name, info.backend, info.device_type, info.driver, info.driver_info
158
+ )).unwrap();
159
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"%s\0".as_ptr(), msg.as_ptr());
160
+ }
161
+
162
+ // Ticket 007b: most Android GPUs lack RT, but recent Adreno /
163
+ // Mali-Immortalis devices do — request the feature if advertised.
164
+ // Limits merge: start from downlevel (required for older Android
165
+ // adapters), then layer acceleration-structure minimums on top
166
+ // when RT was granted.
167
+ let supported = adapter.features();
168
+ let force_sw_gi = std::env::var("BLOOM_FORCE_SW_GI")
169
+ .map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
170
+ .unwrap_or(false);
171
+ let rt_mask = wgpu::Features::EXPERIMENTAL_RAY_QUERY;
172
+ let mut required_features = wgpu::Features::empty();
173
+ // Ticket 011: request TIMESTAMP_QUERY when supported so the profiler
174
+ // can record GPU timings. Optional — profiler falls back to CPU-only
175
+ // when the adapter doesn't grant it (many Android GPUs won't).
176
+ if supported.contains(wgpu::Features::TIMESTAMP_QUERY) {
177
+ required_features |= wgpu::Features::TIMESTAMP_QUERY;
178
+ }
179
+ if !force_sw_gi && supported.contains(rt_mask) {
180
+ required_features |= rt_mask;
181
+ }
182
+ let experimental_features = if required_features.intersects(rt_mask) {
183
+ unsafe { wgpu::ExperimentalFeatures::enabled() }
184
+ } else {
185
+ wgpu::ExperimentalFeatures::disabled()
186
+ };
187
+ let mut required_limits = wgpu::Limits::downlevel_defaults()
188
+ .using_resolution(adapter.limits());
189
+ if required_features.intersects(rt_mask) {
190
+ required_limits = required_limits
191
+ .using_minimum_supported_acceleration_structure_values();
192
+ }
193
+ let (device, queue) = pollster_block_on(adapter.request_device(
194
+ &wgpu::DeviceDescriptor {
195
+ label: Some("bloom_device"),
196
+ required_features,
197
+ required_limits,
198
+ experimental_features,
199
+ ..Default::default()
200
+ },
201
+ )).expect("Failed to create device");
202
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"bloom_init_window: device created\0".as_ptr());
203
+
204
+ let surface_caps = surface.get_capabilities(&adapter);
205
+ if surface_caps.formats.is_empty() {
206
+ panic!("Surface reports no supported formats (emulator Vulkan limitation)");
207
+ }
208
+ let format = surface_caps.formats.iter()
209
+ .find(|f| f.is_srgb()).copied()
210
+ .unwrap_or(surface_caps.formats[0]);
211
+
212
+ let alpha_mode = if surface_caps.alpha_modes.is_empty() {
213
+ wgpu::CompositeAlphaMode::Auto
214
+ } else {
215
+ surface_caps.alpha_modes[0]
216
+ };
217
+
218
+ let surface_config = wgpu::SurfaceConfiguration {
219
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
220
+ format,
221
+ width: pixel_w,
222
+ height: pixel_h,
223
+ present_mode: wgpu::PresentMode::Fifo,
224
+ alpha_mode,
225
+ view_formats: vec![],
226
+ desired_maximum_frame_latency: 2,
227
+ };
228
+ surface.configure(&device, &surface_config);
229
+
230
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"bloom_init_window: surface configured\0".as_ptr());
231
+ let renderer = Renderer::new(device, queue, surface, surface_config, logical_w, logical_h);
232
+ let _ = ENGINE.set(EngineState::new(renderer));
233
+ __android_log_print(3, b"BloomEngine\0".as_ptr(), b"bloom_init_window: engine initialized\0".as_ptr());
234
+ }
235
+ }
236
+
237
+ #[no_mangle]
238
+ pub extern "C" fn bloom_close_window() {
239
+ unsafe {
240
+ if !NATIVE_WINDOW.is_null() {
241
+ ANativeWindow_release(NATIVE_WINDOW);
242
+ NATIVE_WINDOW = std::ptr::null_mut();
243
+ }
244
+ }
245
+ }
246
+
247
+ #[no_mangle]
248
+ pub extern "C" fn bloom_window_should_close() -> f64 {
249
+ if engine().should_close { 1.0 } else { 0.0 }
250
+ }
251
+
252
+ // ============================================================
253
+ // Touch input polling (called from Perry's Android event pump)
254
+ // ============================================================
255
+
256
+ /// Called by Perry's Android layer when a touch event occurs.
257
+ #[no_mangle]
258
+ pub extern "C" fn bloom_android_on_touch(action: i32, x: f64, y: f64, pointer_index: i32) {
259
+ unsafe {
260
+ if let Some(eng) = ENGINE.get_mut() {
261
+ let sw = eng.screen_width();
262
+ let sh = eng.screen_height();
263
+ let lx = x * 0.5;
264
+ let ly = y * 0.5;
265
+ let msg = std::ffi::CString::new(format!("touch a={} raw=({},{}) scaled=({},{}) sw={} sh={}", action, x, y, lx, ly, sw, sh)).unwrap();
266
+ __android_log_print(3, b"BloomTouch\0".as_ptr(), b"%s\0".as_ptr(), msg.as_ptr());
267
+ eng.input.set_mouse_position(lx, ly);
268
+ if action == 1 || action == 3 {
269
+ eng.input.release_touch(pointer_index as usize, lx, ly); // UP / CANCEL
270
+ } else {
271
+ eng.input.set_touch(pointer_index as usize, lx, ly, true); // DOWN / MOVE
272
+ }
273
+ match action {
274
+ 0 => eng.input.set_mouse_button_down(0), // ACTION_DOWN
275
+ 1 => eng.input.set_mouse_button_up(0), // ACTION_UP
276
+ 2 => {} // ACTION_MOVE
277
+ _ => {}
278
+ }
279
+ }
280
+ }
281
+ }
282
+
283
+ #[no_mangle]
284
+ pub extern "C" fn bloom_begin_drawing() {
285
+ engine().begin_frame();
286
+ }
287
+
288
+ #[no_mangle]
289
+ pub extern "C" fn bloom_end_drawing() {
290
+ let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
291
+ engine().end_frame();
292
+ }));
293
+ if let Err(e) = result {
294
+ let msg = if let Some(s) = e.downcast_ref::<&str>() {
295
+ s.to_string()
296
+ } else if let Some(s) = e.downcast_ref::<String>() {
297
+ s.clone()
298
+ } else {
299
+ format!("unknown panic: {:?}", e.type_id())
300
+ };
301
+ // Write to file since eprintln doesn't reach logcat on Android
302
+ static mut LOGGED: bool = false;
303
+ unsafe {
304
+ if !LOGGED {
305
+ LOGGED = true;
306
+ let path = resolve_path("bloom_panic.txt");
307
+ let _ = std::fs::write(&path, format!("end_drawing panic: {}\n", msg));
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ // ============================================================
314
+ // Audio (Oboe / AAudio)
315
+ // ============================================================
316
+
317
+ #[no_mangle]
318
+ pub extern "C" fn bloom_clear_background(r: f64, g: f64, b: f64, a: f64) {
319
+ engine().renderer.set_clear_color(r, g, b, a);
320
+ }
321
+
322
+ #[no_mangle]
323
+ pub extern "C" fn bloom_set_target_fps(fps: f64) { engine().target_fps = fps; }
324
+
325
+ #[no_mangle]
326
+ pub extern "C" fn bloom_set_direct_2d_mode(on: f64) { engine().direct_2d_mode = on > 0.5; }
327
+
328
+ #[no_mangle]
329
+ pub extern "C" fn bloom_get_delta_time() -> f64 { engine().delta_time }
330
+
331
+ #[no_mangle]
332
+ pub extern "C" fn bloom_get_fps() -> f64 { engine().get_fps() }
333
+
334
+ #[no_mangle]
335
+ pub extern "C" fn bloom_get_screen_width() -> f64 { engine().screen_width() }
336
+
337
+ #[no_mangle]
338
+ pub extern "C" fn bloom_get_screen_height() -> f64 { engine().screen_height() }
339
+
340
+ #[no_mangle]
341
+ pub extern "C" fn bloom_is_key_pressed(key: f64) -> f64 {
342
+ if engine().input.is_key_pressed(key as usize) { 1.0 } else { 0.0 }
343
+ }
344
+
345
+ #[no_mangle]
346
+ pub extern "C" fn bloom_is_key_down(key: f64) -> f64 {
347
+ if engine().input.is_key_down(key as usize) { 1.0 } else { 0.0 }
348
+ }
349
+
350
+ #[no_mangle]
351
+ pub extern "C" fn bloom_is_key_released(key: f64) -> f64 {
352
+ if engine().input.is_key_released(key as usize) { 1.0 } else { 0.0 }
353
+ }
354
+
355
+ #[no_mangle]
356
+ pub extern "C" fn bloom_get_mouse_x() -> f64 { engine().input.mouse_x }
357
+
358
+ #[no_mangle]
359
+ pub extern "C" fn bloom_get_mouse_y() -> f64 { engine().input.mouse_y }
360
+
361
+ #[no_mangle]
362
+ pub extern "C" fn bloom_is_mouse_button_pressed(btn: f64) -> f64 {
363
+ if engine().input.is_mouse_button_pressed(btn as usize) { 1.0 } else { 0.0 }
364
+ }
365
+
366
+ #[no_mangle]
367
+ pub extern "C" fn bloom_is_mouse_button_down(btn: f64) -> f64 {
368
+ if engine().input.is_mouse_button_down(btn as usize) { 1.0 } else { 0.0 }
369
+ }
370
+
371
+ #[no_mangle]
372
+ pub extern "C" fn bloom_is_mouse_button_released(btn: f64) -> f64 {
373
+ if engine().input.is_mouse_button_released(btn as usize) { 1.0 } else { 0.0 }
374
+ }
375
+
376
+ #[no_mangle]
377
+ pub extern "C" fn bloom_draw_line(x1: f64, y1: f64, x2: f64, y2: f64, thickness: f64, r: f64, g: f64, b: f64, a: f64) {
378
+ engine().renderer.draw_line(x1, y1, x2, y2, thickness, r, g, b, a);
379
+ }
380
+
381
+ #[no_mangle]
382
+ pub extern "C" fn bloom_draw_rect(x: f64, y: f64, w: f64, h: f64, r: f64, g: f64, b: f64, a: f64) {
383
+ engine().renderer.draw_rect(x, y, w, h, r, g, b, a);
384
+ }
385
+
386
+ #[no_mangle]
387
+ pub extern "C" fn bloom_draw_rect_lines(x: f64, y: f64, w: f64, h: f64, thickness: f64, r: f64, g: f64, b: f64, a: f64) {
388
+ engine().renderer.draw_rect_lines(x, y, w, h, thickness, r, g, b, a);
389
+ }
390
+
391
+ #[no_mangle]
392
+ pub extern "C" fn bloom_draw_circle(cx: f64, cy: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
393
+ engine().renderer.draw_circle(cx, cy, radius, r, g, b, a);
394
+ }
395
+
396
+ #[no_mangle]
397
+ pub extern "C" fn bloom_draw_circle_lines(cx: f64, cy: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
398
+ engine().renderer.draw_circle_lines(cx, cy, radius, r, g, b, a);
399
+ }
400
+
401
+ #[no_mangle]
402
+ pub extern "C" fn bloom_draw_triangle(x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64, r: f64, g: f64, b: f64, a: f64) {
403
+ engine().renderer.draw_triangle(x1, y1, x2, y2, x3, y3, r, g, b, a);
404
+ }
405
+
406
+ #[no_mangle]
407
+ pub extern "C" fn bloom_draw_poly(cx: f64, cy: f64, sides: f64, radius: f64, rotation: f64, r: f64, g: f64, b: f64, a: f64) {
408
+ engine().renderer.draw_poly(cx, cy, sides, radius, rotation, r, g, b, a);
409
+ }
410
+
411
+ #[no_mangle]
412
+ pub extern "C" fn bloom_draw_text(text_ptr: *const u8, x: f64, y: f64, size: f64, r: f64, g: f64, b: f64, a: f64) {
413
+ let text = str_from_header(text_ptr);
414
+ let eng = engine();
415
+ let mut text_renderer = std::mem::replace(&mut eng.text, bloom_shared::text_renderer::TextRenderer::empty());
416
+ text_renderer.draw_text(&mut eng.renderer, text, x, y, size as u32, r, g, b, a);
417
+ eng.text = text_renderer;
418
+ }
419
+
420
+ #[no_mangle]
421
+ pub extern "C" fn bloom_measure_text(text_ptr: *const u8, size: f64) -> f64 {
422
+ let text = str_from_header(text_ptr);
423
+ engine().text.measure_text(text, size as u32)
424
+ }
425
+
426
+ #[no_mangle]
427
+ pub extern "C" fn bloom_load_font(path_ptr: *const u8, size: f64) -> f64 {
428
+ let path = str_from_header(path_ptr);
429
+ match std::fs::read(resolve_path(path)) { Ok(data) => engine().text.load_font(&data) as f64, Err(_) => 0.0 }
430
+ }
431
+
432
+ #[no_mangle]
433
+ pub extern "C" fn bloom_unload_font(font_handle: f64) {
434
+ engine().text.unload_font(font_handle as usize);
435
+ }
436
+
437
+ #[no_mangle]
438
+ pub extern "C" fn bloom_draw_text_ex(font_handle: f64, text_ptr: *const u8, x: f64, y: f64, size: f64, spacing: f64, r: f64, g: f64, b: f64, a: f64) {
439
+ let text = str_from_header(text_ptr);
440
+ let eng = engine();
441
+ let mut text_renderer = std::mem::replace(&mut eng.text, bloom_shared::text_renderer::TextRenderer::empty());
442
+ text_renderer.draw_text_ex(&mut eng.renderer, font_handle as usize, text, x, y, size as u32, spacing as f32, r, g, b, a);
443
+ eng.text = text_renderer;
444
+ }
445
+
446
+ #[no_mangle]
447
+ pub extern "C" fn bloom_measure_text_ex(font_handle: f64, text_ptr: *const u8, size: f64, spacing: f64) -> f64 {
448
+ let text = str_from_header(text_ptr);
449
+ engine().text.measure_text_ex(font_handle as usize, text, size as u32, spacing as f32)
450
+ }
451
+
452
+ #[no_mangle]
453
+ pub extern "C" fn bloom_init_audio() {
454
+ AUDIO_RUNNING.store(true, Ordering::SeqCst);
455
+ std::thread::spawn(|| {
456
+ android_audio_thread();
457
+ });
458
+ }
459
+
460
+ #[no_mangle]
461
+ pub extern "C" fn bloom_close_audio() {
462
+ AUDIO_RUNNING.store(false, Ordering::SeqCst);
463
+ std::thread::sleep(std::time::Duration::from_millis(50));
464
+ }
465
+
466
+ fn android_audio_thread() {
467
+ // Use oboe (AAudio/OpenSL ES wrapper) for audio output
468
+ use oboe::*;
469
+
470
+ struct BloomAudioCallback;
471
+
472
+ impl AudioOutputCallback for BloomAudioCallback {
473
+ type FrameType = (f32, Stereo);
474
+
475
+ fn on_audio_ready(&mut self, _stream: &mut dyn AudioOutputStreamSafe, frames: &mut [(f32, f32)]) -> DataCallbackResult {
476
+ // Convert frame tuples to interleaved slice
477
+ let len = frames.len() * 2;
478
+ let ptr = frames.as_mut_ptr() as *mut f32;
479
+ let interleaved = unsafe { std::slice::from_raw_parts_mut(ptr, len) };
480
+ for s in interleaved.iter_mut() { *s = 0.0; }
481
+ unsafe {
482
+ ENGINE.get_mut().map(|eng| { eng.audio.mix_output(interleaved); });
483
+ }
484
+ if AUDIO_RUNNING.load(Ordering::SeqCst) {
485
+ DataCallbackResult::Continue
486
+ } else {
487
+ DataCallbackResult::Stop
488
+ }
489
+ }
490
+ }
491
+
492
+ let mut stream = AudioStreamBuilder::default()
493
+ .set_performance_mode(PerformanceMode::LowLatency)
494
+ .set_sharing_mode(SharingMode::Shared)
495
+ .set_format::<f32>()
496
+ .set_channel_count::<Stereo>()
497
+ .set_sample_rate(44100)
498
+ .set_callback(BloomAudioCallback)
499
+ .open_stream();
500
+
501
+ match stream {
502
+ Ok(ref mut s) => {
503
+ let _ = s.start();
504
+ // Keep thread alive while audio is running
505
+ while AUDIO_RUNNING.load(Ordering::SeqCst) {
506
+ std::thread::sleep(std::time::Duration::from_millis(100));
507
+ }
508
+ let _ = s.stop();
509
+ }
510
+ Err(_) => {}
511
+ }
512
+ }
513
+
514
+ #[no_mangle]
515
+ pub extern "C" fn bloom_load_sound(path_ptr: *const u8) -> f64 {
516
+ let path = str_from_header(path_ptr);
517
+ match std::fs::read(resolve_path(path)) {
518
+ Ok(data) => {
519
+ if let Some(s) = parse_wav(&data) { engine().audio.load_sound(s) }
520
+ else if let Some(s) = parse_ogg(&data) { engine().audio.load_sound(s) }
521
+ else if let Some(s) = parse_mp3(&data) { engine().audio.load_sound(s) }
522
+ else { 0.0 }
523
+ }
524
+ Err(_) => 0.0,
525
+ }
526
+ }
527
+
528
+ #[no_mangle]
529
+ pub extern "C" fn bloom_play_sound(handle: f64) { engine().audio.play_sound(handle); }
530
+ #[no_mangle]
531
+ pub extern "C" fn bloom_stop_sound(handle: f64) { engine().audio.stop_sound(handle); }
532
+ #[no_mangle]
533
+ pub extern "C" fn bloom_set_sound_volume(handle: f64, volume: f64) { engine().audio.set_sound_volume(handle, volume as f32); }
534
+ #[no_mangle]
535
+ pub extern "C" fn bloom_set_master_volume(volume: f64) { engine().audio.master_volume = volume as f32; }
536
+
537
+ #[no_mangle]
538
+ pub extern "C" fn bloom_play_sound_3d(handle: f64, x: f64, y: f64, z: f64) {
539
+ engine().audio.play_sound_3d(handle, x as f32, y as f32, z as f32);
540
+ }
541
+
542
+ #[no_mangle]
543
+ pub extern "C" fn bloom_set_listener_position(x: f64, y: f64, z: f64, fx: f64, fy: f64, fz: f64) {
544
+ engine().audio.set_listener_position(x as f32, y as f32, z as f32, fx as f32, fy as f32, fz as f32);
545
+ }
546
+
547
+ // --- Texture FFI ---
548
+
549
+ #[no_mangle]
550
+ pub extern "C" fn bloom_load_texture(path_ptr: *const u8) -> f64 {
551
+ let path = str_from_header(path_ptr);
552
+ match std::fs::read(resolve_path(path)) {
553
+ Ok(data) => {
554
+ let eng = engine();
555
+ let renderer_ptr = &mut eng.renderer as *mut bloom_shared::renderer::Renderer;
556
+ eng.textures.load_texture(unsafe { &mut *renderer_ptr }, &data)
557
+ }
558
+ Err(_) => 0.0,
559
+ }
560
+ }
561
+
562
+ #[no_mangle]
563
+ pub extern "C" fn bloom_unload_texture(handle: f64) {
564
+ let eng = engine();
565
+ let renderer_ptr = &mut eng.renderer as *mut bloom_shared::renderer::Renderer;
566
+ eng.textures.unload_texture(handle, unsafe { &mut *renderer_ptr });
567
+ }
568
+
569
+ #[no_mangle]
570
+ pub extern "C" fn bloom_draw_texture(handle: f64, x: f64, y: f64, r: f64, g: f64, b: f64, a: f64) {
571
+ let eng = engine();
572
+ if let Some(tex) = eng.textures.get(handle) {
573
+ let idx = tex.bind_group_idx;
574
+ eng.renderer.draw_texture(idx, x, y, r, g, b, a);
575
+ }
576
+ }
577
+
578
+ #[no_mangle]
579
+ pub extern "C" fn bloom_draw_texture_rec(handle: f64, src_x: f64, src_y: f64, src_w: f64, src_h: f64, dst_x: f64, dst_y: f64, r: f64, g: f64, b: f64, a: f64) {
580
+ let eng = engine();
581
+ if let Some(tex) = eng.textures.get(handle) {
582
+ let idx = tex.bind_group_idx;
583
+ eng.renderer.draw_texture_rec(idx, src_x, src_y, src_w, src_h, dst_x, dst_y, r, g, b, a);
584
+ }
585
+ }
586
+
587
+ #[no_mangle]
588
+ pub extern "C" fn bloom_draw_texture_pro(handle: f64, src_x: f64, src_y: f64, src_w: f64, src_h: f64, dst_x: f64, dst_y: f64, dst_w: f64, dst_h: f64, origin_x: f64, origin_y: f64, rotation: f64, r: f64, g: f64, b: f64, a: f64) {
589
+ let eng = engine();
590
+ if let Some(tex) = eng.textures.get(handle) {
591
+ let idx = tex.bind_group_idx;
592
+ eng.renderer.draw_texture_pro(idx, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h, origin_x, origin_y, rotation, r, g, b, a);
593
+ }
594
+ }
595
+
596
+ #[no_mangle]
597
+ pub extern "C" fn bloom_get_texture_width(handle: f64) -> f64 {
598
+ engine().textures.get(handle).map(|t| t.width as f64).unwrap_or(0.0)
599
+ }
600
+
601
+ #[no_mangle]
602
+ pub extern "C" fn bloom_get_texture_height(handle: f64) -> f64 {
603
+ engine().textures.get(handle).map(|t| t.height as f64).unwrap_or(0.0)
604
+ }
605
+
606
+ #[no_mangle]
607
+ pub extern "C" fn bloom_gen_texture_mipmaps(_handle: f64) {
608
+ // No-op: wgpu handles mipmaps internally
609
+ }
610
+
611
+ #[no_mangle]
612
+ pub extern "C" fn bloom_set_texture_filter(handle: f64, mode: f64) {
613
+ let eng = engine();
614
+ if let Some(tex) = eng.textures.get(handle) {
615
+ let bind_group_idx = tex.bind_group_idx;
616
+ eng.renderer.set_texture_filter(bind_group_idx, mode > 0.5);
617
+ }
618
+ }
619
+
620
+ #[no_mangle]
621
+ pub extern "C" fn bloom_load_image(path_ptr: *const u8) -> f64 {
622
+ let path = str_from_header(path_ptr);
623
+ match std::fs::read(resolve_path(path)) { Ok(data) => engine().textures.load_image(&data), Err(_) => 0.0 }
624
+ }
625
+
626
+ #[no_mangle]
627
+ pub extern "C" fn bloom_image_resize(handle: f64, w: f64, h: f64) {
628
+ engine().textures.image_resize(handle, w as u32, h as u32);
629
+ }
630
+
631
+ #[no_mangle]
632
+ pub extern "C" fn bloom_image_crop(handle: f64, x: f64, y: f64, w: f64, h: f64) {
633
+ engine().textures.image_crop(handle, x as u32, y as u32, w as u32, h as u32);
634
+ }
635
+
636
+ #[no_mangle]
637
+ pub extern "C" fn bloom_image_flip_h(handle: f64) {
638
+ engine().textures.image_flip_h(handle);
639
+ }
640
+
641
+ #[no_mangle]
642
+ pub extern "C" fn bloom_image_flip_v(handle: f64) {
643
+ engine().textures.image_flip_v(handle);
644
+ }
645
+
646
+ #[no_mangle]
647
+ pub extern "C" fn bloom_load_texture_from_image(handle: f64) -> f64 {
648
+ let eng = engine();
649
+ let renderer_ptr = &mut eng.renderer as *mut bloom_shared::renderer::Renderer;
650
+ eng.textures.load_texture_from_image(handle, unsafe { &mut *renderer_ptr })
651
+ }
652
+
653
+ // --- Camera FFI ---
654
+
655
+ #[no_mangle]
656
+ pub extern "C" fn bloom_begin_mode_2d(offset_x: f64, offset_y: f64, target_x: f64, target_y: f64, rotation: f64, zoom: f64) {
657
+ engine().renderer.begin_mode_2d(offset_x as f32, offset_y as f32, target_x as f32, target_y as f32, rotation as f32, zoom as f32);
658
+ }
659
+ #[no_mangle]
660
+ pub extern "C" fn bloom_end_mode_2d() { engine().renderer.end_mode_2d(); }
661
+
662
+ #[no_mangle]
663
+ pub extern "C" fn bloom_begin_mode_3d(pos_x: f64, pos_y: f64, pos_z: f64, target_x: f64, target_y: f64, target_z: f64, up_x: f64, up_y: f64, up_z: f64, fovy: f64, projection: f64) {
664
+ engine().renderer.begin_mode_3d(pos_x as f32, pos_y as f32, pos_z as f32, target_x as f32, target_y as f32, target_z as f32, up_x as f32, up_y as f32, up_z as f32, fovy as f32, projection as f32);
665
+ }
666
+ #[no_mangle]
667
+ pub extern "C" fn bloom_end_mode_3d() { engine().renderer.end_mode_3d(); }
668
+
669
+ // --- 3D Drawing FFI ---
670
+
671
+ #[no_mangle]
672
+ pub extern "C" fn bloom_draw_cube(x: f64, y: f64, z: f64, w: f64, h: f64, d: f64, r: f64, g: f64, b: f64, a: f64) {
673
+ engine().renderer.draw_cube(x, y, z, w, h, d, r, g, b, a);
674
+ }
675
+ #[no_mangle]
676
+ pub extern "C" fn bloom_draw_cube_wires(x: f64, y: f64, z: f64, w: f64, h: f64, d: f64, r: f64, g: f64, b: f64, a: f64) {
677
+ engine().renderer.draw_cube_wires(x, y, z, w, h, d, r, g, b, a);
678
+ }
679
+ #[no_mangle]
680
+ pub extern "C" fn bloom_draw_sphere(x: f64, y: f64, z: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
681
+ engine().renderer.draw_sphere(x, y, z, radius, r, g, b, a);
682
+ }
683
+ #[no_mangle]
684
+ pub extern "C" fn bloom_draw_sphere_wires(x: f64, y: f64, z: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
685
+ engine().renderer.draw_sphere_wires(x, y, z, radius, r, g, b, a);
686
+ }
687
+ #[no_mangle]
688
+ pub extern "C" fn bloom_draw_cylinder(x: f64, y: f64, z: f64, rt: f64, rb: f64, h: f64, r: f64, g: f64, b: f64, a: f64) {
689
+ engine().renderer.draw_cylinder(x, y, z, rt, rb, h, r, g, b, a);
690
+ }
691
+ #[no_mangle]
692
+ pub extern "C" fn bloom_draw_plane(x: f64, y: f64, z: f64, w: f64, d: f64, r: f64, g: f64, b: f64, a: f64) {
693
+ engine().renderer.draw_plane(x, y, z, w, d, r, g, b, a);
694
+ }
695
+ #[no_mangle]
696
+ pub extern "C" fn bloom_draw_grid(slices: f64, spacing: f64) {
697
+ engine().renderer.draw_grid(slices as i32, spacing);
698
+ }
699
+ #[no_mangle]
700
+ pub extern "C" fn bloom_draw_ray(ox: f64, oy: f64, oz: f64, dx: f64, dy: f64, dz: f64, r: f64, g: f64, b: f64, a: f64) {
701
+ engine().renderer.draw_ray(ox, oy, oz, dx, dy, dz, r, g, b, a);
702
+ }
703
+
704
+ // --- Model FFI ---
705
+
706
+ #[no_mangle]
707
+ pub extern "C" fn bloom_load_model(path_ptr: *const u8) -> f64 {
708
+ let path = str_from_header(path_ptr);
709
+ match std::fs::read(resolve_path(path)) {
710
+ Ok(data) => {
711
+ let eng = engine();
712
+ let renderer_ptr = &mut eng.renderer as *mut crate::Renderer;
713
+ eng.models.load_model_with_textures(&data, unsafe { &mut *renderer_ptr })
714
+ }
715
+ Err(_) => 0.0,
716
+ }
717
+ }
718
+ #[no_mangle]
719
+ pub extern "C" fn bloom_draw_model(handle: f64, x: f64, y: f64, z: f64, scale: f64, r: f64, g: f64, b: f64, a: f64) {
720
+ let eng = engine();
721
+ if let Some(model) = eng.models.get(handle) {
722
+ let tint = [(r / 255.0) as f32, (g / 255.0) as f32, (b / 255.0) as f32, (a / 255.0) as f32];
723
+ let position = [x as f32, y as f32, z as f32];
724
+ let handle_bits = handle.to_bits();
725
+ if eng.renderer.cache_model_if_static(handle_bits, &model.meshes) {
726
+ eng.renderer.draw_model_cached(handle_bits, position, scale as f32, tint);
727
+ } else {
728
+ for mesh in &model.meshes {
729
+ let tex_idx = mesh.texture_idx.unwrap_or(0);
730
+ eng.renderer.draw_model_mesh_tinted(&mesh.vertices, &mesh.indices, position, scale as f32, tint, tex_idx);
731
+ }
732
+ }
733
+ }
734
+ }
735
+ #[no_mangle]
736
+ pub extern "C" fn bloom_draw_model_rotated(
737
+ handle: f64, x: f64, y: f64, z: f64,
738
+ scale: f64, rot_y: f64,
739
+ color_packed_argb: f64,
740
+ ) {
741
+ let bits = color_packed_argb as u32;
742
+ let a = ((bits >> 24) & 0xff) as f32 / 255.0;
743
+ let r = ((bits >> 16) & 0xff) as f32 / 255.0;
744
+ let g = ((bits >> 8) & 0xff) as f32 / 255.0;
745
+ let b = ( bits & 0xff) as f32 / 255.0;
746
+ let eng = engine();
747
+ if let Some(model) = eng.models.get(handle) {
748
+ let position = [x as f32, y as f32, z as f32];
749
+ let scale = scale as f32;
750
+ let tint = [r, g, b, a];
751
+ for mesh in &model.meshes {
752
+ let tex_idx = mesh.texture_idx.unwrap_or(0);
753
+ eng.renderer.draw_model_mesh_tinted_rotated(
754
+ &mesh.vertices, &mesh.indices, position, scale, tint, tex_idx, rot_y as f32,
755
+ );
756
+ }
757
+ }
758
+ }
759
+ #[no_mangle]
760
+ pub extern "C" fn bloom_unload_model(handle: f64) { engine().models.unload_model(handle); }
761
+
762
+ #[no_mangle]
763
+ pub extern "C" fn bloom_get_model_mesh_count(handle: f64) -> f64 {
764
+ match engine().models.get(handle) {
765
+ Some(model) => model.meshes.len() as f64,
766
+ None => 0.0,
767
+ }
768
+ }
769
+
770
+ #[no_mangle]
771
+ pub extern "C" fn bloom_get_model_material_count(handle: f64) -> f64 {
772
+ match engine().models.get(handle) {
773
+ Some(model) => model.meshes.len() as f64,
774
+ None => 0.0,
775
+ }
776
+ }
777
+
778
+ #[no_mangle]
779
+ pub extern "C" fn bloom_gen_mesh_cube(w: f64, h: f64, d: f64) -> f64 {
780
+ engine().models.gen_mesh_cube(w as f32, h as f32, d as f32)
781
+ }
782
+
783
+ #[no_mangle]
784
+ pub extern "C" fn bloom_gen_mesh_heightmap(image_handle: f64, size_x: f64, size_y: f64, size_z: f64) -> f64 {
785
+ let eng = engine();
786
+ if let Some(img) = eng.textures.images.get(image_handle) {
787
+ let data = img.data.clone();
788
+ let w = img.width;
789
+ let h = img.height;
790
+ eng.models.gen_mesh_heightmap(&data, w, h, size_x as f32, size_y as f32, size_z as f32)
791
+ } else {
792
+ 0.0
793
+ }
794
+ }
795
+
796
+ #[no_mangle]
797
+ pub extern "C" fn bloom_load_shader(source_ptr: *const u8) -> f64 {
798
+ let source = str_from_header(source_ptr);
799
+ engine().renderer.load_custom_shader(source) as f64
800
+ }
801
+
802
+ #[no_mangle]
803
+ pub extern "C" fn bloom_create_mesh(vertex_ptr: *const f32, vertex_count: f64, index_ptr: *const u32, index_count: f64) -> f64 {
804
+ if vertex_ptr.is_null() || index_ptr.is_null() { return 0.0; }
805
+ let vcount = vertex_count as usize;
806
+ let icount = index_count as usize;
807
+ let vertex_data = unsafe { std::slice::from_raw_parts(vertex_ptr, vcount * 12) }; // 12 floats per vertex
808
+ let index_data = unsafe { std::slice::from_raw_parts(index_ptr, icount) };
809
+ engine().models.create_mesh(vertex_data, index_data)
810
+ }
811
+
812
+ // ============================================================
813
+ // Phase 1c — material system FFI
814
+ // ============================================================
815
+
816
+ #[no_mangle]
817
+ pub extern "C" fn bloom_set_material_params(
818
+ handle: f64,
819
+ params_ptr: *const f64,
820
+ param_count: f64,
821
+ ) {
822
+ let count = param_count as usize;
823
+ if count > 64 {
824
+ eprintln!("[material] set_material_params: param_count {} > 64 (256-byte UBO cap)", count);
825
+ return;
826
+ }
827
+ let mut bytes = vec![0u8; count * 4];
828
+ if !params_ptr.is_null() && count > 0 {
829
+ let slots = unsafe { std::slice::from_raw_parts(params_ptr, count) };
830
+ for (i, &v) in slots.iter().enumerate() {
831
+ let f = v as f32;
832
+ bytes[i*4..i*4+4].copy_from_slice(&f.to_le_bytes());
833
+ }
834
+ }
835
+ let eng = engine();
836
+ if let Err(e) = eng.renderer.material_system.set_user_params(
837
+ &eng.renderer.device, &eng.renderer.queue,
838
+ handle as u32, &bytes,
839
+ ) {
840
+ eprintln!("[material] set_material_params failed: {}", e);
841
+ }
842
+ }
843
+
844
+ #[no_mangle]
845
+ pub extern "C" fn bloom_compile_material(source_ptr: *const u8) -> f64 {
846
+ let source = str_from_header(source_ptr);
847
+ match engine().renderer.compile_material(source) {
848
+ Ok(handle) => handle as f64,
849
+ Err(e) => {
850
+ eprintln!("[material] compile failed: {:?}", e);
851
+ 0.0
852
+ }
853
+ }
854
+ }
855
+
856
+ #[no_mangle]
857
+ pub extern "C" fn bloom_compile_material_refractive(source_ptr: *const u8) -> f64 {
858
+ use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
859
+ let source = str_from_header(source_ptr);
860
+ match engine().renderer.compile_material_with_options(
861
+ source, FragmentProfile::Translucent, Bucket::Refractive, true, false,
862
+ ) {
863
+ Ok(handle) => handle as f64,
864
+ Err(e) => { eprintln!("[refractive] compile failed: {:?}", e); 0.0 }
865
+ }
866
+ }
867
+
868
+ #[no_mangle]
869
+ pub extern "C" fn bloom_compile_material_transparent(source_ptr: *const u8) -> f64 {
870
+ use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
871
+ let source = str_from_header(source_ptr);
872
+ match engine().renderer.compile_material_with_options(
873
+ source, FragmentProfile::Translucent, Bucket::Transparent, false, false,
874
+ ) {
875
+ Ok(handle) => handle as f64,
876
+ Err(e) => { eprintln!("[material] compile failed: {:?}", e); 0.0 }
877
+ }
878
+ }
879
+
880
+ #[no_mangle]
881
+ pub extern "C" fn bloom_compile_material_additive(source_ptr: *const u8) -> f64 {
882
+ use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
883
+ let source = str_from_header(source_ptr);
884
+ match engine().renderer.compile_material_with_options(
885
+ source, FragmentProfile::Translucent, Bucket::Additive, false, false,
886
+ ) {
887
+ Ok(handle) => handle as f64,
888
+ Err(e) => { eprintln!("[material] compile failed: {:?}", e); 0.0 }
889
+ }
890
+ }
891
+
892
+ #[no_mangle]
893
+ pub extern "C" fn bloom_compile_material_cutout(source_ptr: *const u8) -> f64 {
894
+ use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
895
+ let source = str_from_header(source_ptr);
896
+ match engine().renderer.compile_material_with_options(
897
+ source, FragmentProfile::Opaque, Bucket::Cutout, false, false,
898
+ ) {
899
+ Ok(handle) => handle as f64,
900
+ Err(e) => { eprintln!("[material] compile failed: {:?}", e); 0.0 }
901
+ }
902
+ }
903
+
904
+ #[no_mangle]
905
+ pub extern "C" fn bloom_compile_material_instanced(source_ptr: *const u8) -> f64 {
906
+ let source = str_from_header(source_ptr);
907
+ match engine().renderer.compile_material_instanced(source) {
908
+ Ok(handle) => handle as f64,
909
+ Err(e) => { eprintln!("[material] instanced compile failed: {:?}", e); 0.0 }
910
+ }
911
+ }
912
+
913
+ #[no_mangle]
914
+ pub extern "C" fn bloom_create_instance_buffer(
915
+ data_ptr: *const f64, instance_count: f64,
916
+ ) -> f64 {
917
+ if data_ptr.is_null() || instance_count <= 0.0 { return 0.0; }
918
+ let count = instance_count as u32;
919
+ let slot_count = (count as usize) * 9;
920
+ let raw_f64 = unsafe { std::slice::from_raw_parts(data_ptr, slot_count) };
921
+ let raw_f32: Vec<f32> = raw_f64.iter().map(|&v| v as f32).collect();
922
+ engine().renderer.create_instance_buffer(&raw_f32, count) as f64
923
+ }
924
+
925
+ #[no_mangle]
926
+ pub extern "C" fn bloom_submit_material_draw_instanced(
927
+ material: f64, mesh_handle: f64, mesh_idx: f64,
928
+ instance_buffer: f64, instance_count: f64,
929
+ ) {
930
+ let eng = engine();
931
+ let handle_bits = mesh_handle.to_bits();
932
+ if let Some(model) = eng.models.get(mesh_handle) {
933
+ eng.renderer.cache_model_if_static(handle_bits, &model.meshes);
934
+ }
935
+ eng.renderer.submit_material_draw_instanced(
936
+ material as u32,
937
+ handle_bits,
938
+ mesh_idx as usize,
939
+ instance_buffer as u32,
940
+ instance_count as u32,
941
+ );
942
+ }
943
+
944
+ #[no_mangle]
945
+ pub extern "C" fn bloom_destroy_instance_buffer(handle: f64) {
946
+ engine().renderer.destroy_instance_buffer(handle as u32);
947
+ }
948
+
949
+ /// EN-011 — create a planar reflection probe. See macOS lib.rs for the
950
+ /// full doc comment; this entry-point exists on every native platform
951
+ /// so games can target the same FFI surface across iOS/tvOS/Windows/
952
+ /// Linux/Android.
953
+ #[no_mangle]
954
+ pub extern "C" fn bloom_create_planar_reflection(
955
+ plane_y: f64, nx: f64, ny: f64, nz: f64, resolution: f64,
956
+ ) -> f64 {
957
+ engine().renderer.create_planar_reflection(
958
+ plane_y as f32,
959
+ [nx as f32, ny as f32, nz as f32],
960
+ resolution as u32,
961
+ ) as f64
962
+ }
963
+
964
+ /// EN-011 — link a material to a planar reflection probe. `probe = 0`
965
+ /// reverts the binding to the engine's default 1×1 black texture.
966
+ #[no_mangle]
967
+ pub extern "C" fn bloom_set_material_reflection_probe(
968
+ material: f64, probe: f64,
969
+ ) {
970
+ engine().renderer.set_material_reflection_probe(material as u32, probe as u32);
971
+ }
972
+
973
+ /// EN-014 — create a texture array from concatenated RGBA8 byte data.
974
+ /// See macOS lib.rs for the full doc comment; this entry-point exists
975
+ /// on every native platform so a TS game targets the same FFI across
976
+ /// iOS / tvOS / Windows / Linux / Android.
977
+ #[no_mangle]
978
+ pub extern "C" fn bloom_create_texture_array(
979
+ data_ptr: *const u8,
980
+ data_len: f64,
981
+ width: f64,
982
+ height: f64,
983
+ layer_count: f64,
984
+ ) -> f64 {
985
+ // EN-014 V2 — V1 forwards to _ex with default sRGB / no mips.
986
+ bloom_create_texture_array_ex(data_ptr, data_len, width, height, layer_count, 0.0, 1.0)
987
+ }
988
+
989
+ /// EN-014 V2 — explicit format + mip control. See macOS lib.rs for docs.
990
+ #[no_mangle]
991
+ pub extern "C" fn bloom_create_texture_array_ex(
992
+ data_ptr: *const u8,
993
+ data_len: f64,
994
+ width: f64,
995
+ height: f64,
996
+ layer_count: f64,
997
+ format: f64,
998
+ mip_levels: f64,
999
+ ) -> f64 {
1000
+ if data_ptr.is_null() || data_len <= 0.0 { return 0.0; }
1001
+ let w = width as u32;
1002
+ let h = height as u32;
1003
+ if w == 0 || h == 0 { return 0.0; }
1004
+ let layers_count = (layer_count as u32)
1005
+ .min(bloom_shared::renderer::material_system::MAX_TEXTURE_ARRAY_LAYERS);
1006
+ if layers_count == 0 { return 0.0; }
1007
+ let layer_size = (w as usize) * (h as usize) * 4;
1008
+ let total_bytes = (data_len as usize)
1009
+ .min(layers_count as usize * layer_size);
1010
+ let bytes = unsafe { std::slice::from_raw_parts(data_ptr, total_bytes) };
1011
+ let mut layers: Vec<(&[u8], u32, u32)> = Vec::with_capacity(layers_count as usize);
1012
+ for i in 0..(layers_count as usize) {
1013
+ let start = i * layer_size;
1014
+ let end = start + layer_size;
1015
+ if end > bytes.len() { break; }
1016
+ layers.push((&bytes[start..end], w, h));
1017
+ }
1018
+ engine().renderer.create_texture_array_ex(&layers, format as u32, mip_levels as u32) as f64
1019
+ }
1020
+
1021
+ /// EN-014 — link a texture-array handle to a material at one of three
1022
+ /// slots: 0 = albedo (binding 14), 1 = normal (binding 15),
1023
+ /// 2 = MR (binding 16). Pass `array = 0` to revert to the stub.
1024
+ #[no_mangle]
1025
+ pub extern "C" fn bloom_set_material_texture_array(
1026
+ material: f64, slot: f64, array: f64,
1027
+ ) {
1028
+ engine().renderer.set_material_texture_array(
1029
+ material as u32, slot as u32, array as u32,
1030
+ );
1031
+ }
1032
+
1033
+ /// EN-012 — set the shading model for a material (0=default lit,
1034
+ /// 1=foliage, 2=subsurface V2 stub).
1035
+ #[no_mangle]
1036
+ pub extern "C" fn bloom_set_material_shading_model(
1037
+ material: f64, model: f64,
1038
+ ) {
1039
+ engine().renderer.set_material_shading_model(material as u32, model as u32);
1040
+ }
1041
+
1042
+ /// EN-012 — set the foliage shading parameters for a material.
1043
+ /// Only takes effect when shading_model == 1 (foliage).
1044
+ #[no_mangle]
1045
+ pub extern "C" fn bloom_set_material_foliage(
1046
+ material: f64,
1047
+ trans_r: f64, trans_g: f64, trans_b: f64,
1048
+ trans_amount: f64, wrap_factor: f64,
1049
+ ) {
1050
+ engine().renderer.set_material_foliage(
1051
+ material as u32,
1052
+ [trans_r as f32, trans_g as f32, trans_b as f32],
1053
+ trans_amount as f32, wrap_factor as f32,
1054
+ );
1055
+ }
1056
+
1057
+ #[no_mangle]
1058
+ pub extern "C" fn bloom_compile_material_from_file(
1059
+ path_ptr: *const u8,
1060
+ bucket_kind: f64,
1061
+ ) -> f64 {
1062
+ use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
1063
+ let path = str_from_header(path_ptr);
1064
+ let (profile, bucket, reads_scene) = match bucket_kind as u32 {
1065
+ 0 => (FragmentProfile::Opaque, Bucket::Opaque, false),
1066
+ 1 => (FragmentProfile::Translucent, Bucket::Transparent, false),
1067
+ 2 => (FragmentProfile::Translucent, Bucket::Refractive, true),
1068
+ 3 => (FragmentProfile::Translucent, Bucket::Additive, false),
1069
+ 4 => (FragmentProfile::Opaque, Bucket::Cutout, false),
1070
+ _ => {
1071
+ eprintln!("[material] from_file: unknown bucket_kind {bucket_kind}");
1072
+ return 0.0;
1073
+ }
1074
+ };
1075
+ match engine().renderer.compile_material_from_file(
1076
+ std::path::Path::new(path), profile, bucket, reads_scene,
1077
+ ) {
1078
+ Ok(handle) => handle as f64,
1079
+ Err(e) => { eprintln!("[material] from_file failed: {e}"); 0.0 }
1080
+ }
1081
+ }
1082
+
1083
+ /// EN-017 — compile + install a fullscreen post-pass material.
1084
+ /// See `bloom-macos::bloom_set_post_pass` for the full ABI.
1085
+ #[no_mangle]
1086
+ pub extern "C" fn bloom_set_post_pass(source_ptr: *const u8) -> f64 {
1087
+ let source = str_from_header(source_ptr);
1088
+ match engine().renderer.set_post_pass(source) {
1089
+ Ok(()) => 1.0,
1090
+ Err(e) => { eprintln!("[post_pass] compile failed: {:?}", e); 0.0 }
1091
+ }
1092
+ }
1093
+
1094
+ /// EN-017 — uninstall the active post-pass.
1095
+ #[no_mangle]
1096
+ pub extern "C" fn bloom_clear_post_pass() {
1097
+ engine().renderer.clear_post_pass();
1098
+ }
1099
+
1100
+ /// EN-017 V2 — append a post-pass to the stack.
1101
+ /// See `bloom-macos::bloom_add_post_pass` for the full ABI.
1102
+ #[no_mangle]
1103
+ pub extern "C" fn bloom_add_post_pass(source_ptr: *const u8) -> f64 {
1104
+ let source = str_from_header(source_ptr);
1105
+ match engine().renderer.add_post_pass(source) {
1106
+ Ok(h) => h as f64,
1107
+ Err(e) => { eprintln!("[post_pass] compile failed: {:?}", e); 0.0 }
1108
+ }
1109
+ }
1110
+
1111
+ /// EN-017 V2 — wipe the entire post-pass stack.
1112
+ #[no_mangle]
1113
+ pub extern "C" fn bloom_clear_all_post_passes() {
1114
+ engine().renderer.clear_all_post_passes();
1115
+ }
1116
+
1117
+ #[no_mangle]
1118
+ pub extern "C" fn bloom_draw_material(
1119
+ material: f64,
1120
+ mesh_handle: f64,
1121
+ mesh_idx: f64,
1122
+ x: f64, y: f64, z: f64, scale: f64,
1123
+ r: f64, g: f64, b: f64, a: f64,
1124
+ ) {
1125
+ let eng = engine();
1126
+ let handle_bits = mesh_handle.to_bits();
1127
+ if let Some(model) = eng.models.get(mesh_handle) {
1128
+ eng.renderer.cache_model_if_static(handle_bits, &model.meshes);
1129
+ }
1130
+ eng.renderer.submit_material_draw(
1131
+ material as u32,
1132
+ handle_bits,
1133
+ mesh_idx as usize,
1134
+ [x as f32, y as f32, z as f32],
1135
+ scale as f32,
1136
+ [(r / 255.0) as f32, (g / 255.0) as f32, (b / 255.0) as f32, (a / 255.0) as f32],
1137
+ );
1138
+ }
1139
+
1140
+ #[no_mangle]
1141
+ pub extern "C" fn bloom_load_model_animation(path_ptr: *const u8) -> f64 {
1142
+ let path = str_from_header(path_ptr);
1143
+ match std::fs::read(resolve_path(path)) {
1144
+ Ok(data) => engine().models.load_model_animation(&data),
1145
+ Err(_) => 0.0,
1146
+ }
1147
+ }
1148
+
1149
+ #[no_mangle]
1150
+ pub extern "C" fn bloom_update_model_animation(handle: f64, anim_index: f64, time: f64, scale: f64, px: f64, py: f64, pz: f64, rot_sin: f64, rot_cos: f64) {
1151
+ let eng = engine();
1152
+ eng.models.update_model_animation(handle, anim_index as usize, time as f32);
1153
+ if let Some(anim) = eng.models.get_animation(handle) {
1154
+ if !anim.joint_matrices.is_empty() {
1155
+ eng.renderer.set_joint_matrices_scaled(&anim.joint_matrices, scale as f32, [px as f32, py as f32, pz as f32], rot_sin as f32, rot_cos as f32);
1156
+ }
1157
+ }
1158
+ }
1159
+
1160
+ // --- Music FFI ---
1161
+
1162
+ #[no_mangle]
1163
+ pub extern "C" fn bloom_load_music(path_ptr: *const u8) -> f64 {
1164
+ let path = str_from_header(path_ptr);
1165
+ match std::fs::read(resolve_path(path)) {
1166
+ Ok(data) => {
1167
+ if let Some(s) = parse_ogg(&data) { engine().audio.load_music(s) }
1168
+ else if let Some(s) = parse_wav(&data) { engine().audio.load_music(s) }
1169
+ else if let Some(s) = parse_mp3(&data) { engine().audio.load_music(s) }
1170
+ else { 0.0 }
1171
+ }
1172
+ Err(_) => 0.0,
1173
+ }
1174
+ }
1175
+ #[no_mangle]
1176
+ pub extern "C" fn bloom_play_music(handle: f64) { engine().audio.play_music(handle); }
1177
+ #[no_mangle]
1178
+ pub extern "C" fn bloom_stop_music(handle: f64) { engine().audio.stop_music(handle); }
1179
+ #[no_mangle]
1180
+ pub extern "C" fn bloom_update_music_stream(handle: f64) { engine().audio.update_music_stream(handle); }
1181
+ #[no_mangle]
1182
+ pub extern "C" fn bloom_set_music_volume(handle: f64, volume: f64) { engine().audio.set_music_volume(handle, volume as f32); }
1183
+ #[no_mangle]
1184
+ pub extern "C" fn bloom_is_music_playing(handle: f64) -> f64 { if engine().audio.is_music_playing(handle) { 1.0 } else { 0.0 } }
1185
+
1186
+ // --- Gamepad FFI ---
1187
+
1188
+ #[no_mangle]
1189
+ pub extern "C" fn bloom_is_gamepad_available() -> f64 { if engine().input.is_gamepad_available() { 1.0 } else { 0.0 } }
1190
+ #[no_mangle]
1191
+ pub extern "C" fn bloom_get_gamepad_axis(axis: f64) -> f64 { engine().input.get_gamepad_axis(axis as usize) as f64 }
1192
+ #[no_mangle]
1193
+ pub extern "C" fn bloom_is_gamepad_button_pressed(btn: f64) -> f64 { if engine().input.is_gamepad_button_pressed(btn as usize) { 1.0 } else { 0.0 } }
1194
+ #[no_mangle]
1195
+ pub extern "C" fn bloom_is_gamepad_button_down(btn: f64) -> f64 { if engine().input.is_gamepad_button_down(btn as usize) { 1.0 } else { 0.0 } }
1196
+ #[no_mangle]
1197
+ pub extern "C" fn bloom_is_gamepad_button_released(btn: f64) -> f64 { if engine().input.is_gamepad_button_released(btn as usize) { 1.0 } else { 0.0 } }
1198
+ #[no_mangle]
1199
+ pub extern "C" fn bloom_get_gamepad_axis_count() -> f64 { engine().input.get_gamepad_axis_count() as f64 }
1200
+
1201
+ // --- Skeletal Animation Debug ---
1202
+
1203
+ #[no_mangle]
1204
+ pub extern "C" fn bloom_set_joint_test(_joint: f64, _angle: f64) {
1205
+ // No-op for now — skeletal animation testing
1206
+ }
1207
+
1208
+ // --- Lighting ---
1209
+
1210
+ #[no_mangle]
1211
+ pub extern "C" fn bloom_set_ambient_light(r: f64, g: f64, b: f64, intensity: f64) {
1212
+ engine().renderer.set_ambient_light(r, g, b, intensity);
1213
+ }
1214
+
1215
+ #[no_mangle]
1216
+ pub extern "C" fn bloom_set_directional_light(dx: f64, dy: f64, dz: f64, r: f64, g: f64, b: f64, intensity: f64) {
1217
+ engine().renderer.set_directional_light(dx, dy, dz, r, g, b, intensity);
1218
+ }
1219
+
1220
+ #[no_mangle]
1221
+ pub extern "C" fn bloom_set_procedural_sky(enabled: f64, rayleigh_density: f64, mie_density: f64, ground_albedo: f64) {
1222
+ engine().renderer.set_procedural_sky(
1223
+ enabled != 0.0,
1224
+ rayleigh_density as f32,
1225
+ mie_density as f32,
1226
+ ground_albedo as f32,
1227
+ );
1228
+ }
1229
+
1230
+ #[no_mangle]
1231
+ pub extern "C" fn bloom_set_sun_direction(dx: f64, dy: f64, dz: f64, intensity: f64) {
1232
+ engine().renderer.set_sun_direction(dx as f32, dy as f32, dz as f32, intensity as f32);
1233
+ }
1234
+
1235
+ // --- Utility FFI ---
1236
+
1237
+ #[no_mangle]
1238
+ pub extern "C" fn bloom_toggle_fullscreen() {}
1239
+ #[no_mangle]
1240
+ pub extern "C" fn bloom_set_window_title(title_ptr: *const u8) { let _ = str_from_header(title_ptr); }
1241
+ #[no_mangle]
1242
+ pub extern "C" fn bloom_set_window_icon(path_ptr: *const u8) { let _ = str_from_header(path_ptr); }
1243
+
1244
+ #[no_mangle]
1245
+ pub extern "C" fn bloom_disable_cursor() {
1246
+ engine().input.cursor_disabled = true;
1247
+ }
1248
+
1249
+ #[no_mangle]
1250
+ pub extern "C" fn bloom_enable_cursor() {
1251
+ engine().input.cursor_disabled = false;
1252
+ }
1253
+
1254
+ #[no_mangle]
1255
+ pub extern "C" fn bloom_get_mouse_delta_x() -> f64 {
1256
+ engine().input.mouse_delta_x
1257
+ }
1258
+
1259
+ #[no_mangle]
1260
+ pub extern "C" fn bloom_get_mouse_delta_y() -> f64 {
1261
+ engine().input.mouse_delta_y
1262
+ }
1263
+
1264
+ // Accumulated scroll wheel delta since the last call. Reading consumes the
1265
+ // value (returns 0 on the next call until the user scrolls again). Used by
1266
+ // the editor's orbit camera and any scrollable UI panel.
1267
+ #[no_mangle]
1268
+ pub extern "C" fn bloom_get_mouse_wheel() -> f64 {
1269
+ engine().input.consume_mouse_wheel()
1270
+ }
1271
+
1272
+ #[no_mangle]
1273
+ pub extern "C" fn bloom_get_char_pressed() -> f64 {
1274
+ engine().input.pop_char() as f64
1275
+ }
1276
+
1277
+ // Q2: Cursor shape
1278
+ #[no_mangle]
1279
+ pub extern "C" fn bloom_set_cursor_shape(shape: f64) {
1280
+ engine().input.cursor_shape = shape as u32;
1281
+ }
1282
+
1283
+ // E4: Clipboard (stub on this platform)
1284
+ #[no_mangle]
1285
+ pub extern "C" fn bloom_set_clipboard_text(_text_ptr: *const u8) {}
1286
+ #[no_mangle]
1287
+ pub extern "C" fn bloom_get_clipboard_text() -> *const u8 { std::ptr::null() }
1288
+
1289
+ // E5b: File dialogs (stub on this platform)
1290
+ #[no_mangle]
1291
+ pub extern "C" fn bloom_open_file_dialog(_filter_ptr: *const u8, _title_ptr: *const u8) -> *const u8 { std::ptr::null() }
1292
+ #[no_mangle]
1293
+ pub extern "C" fn bloom_save_file_dialog(_default_name_ptr: *const u8, _title_ptr: *const u8) -> *const u8 { std::ptr::null() }
1294
+
1295
+ // Model bounds accessors. Return the axis-aligned bounding box of a loaded
1296
+ // model in model-local coordinates. Editors use these to size gizmos, auto-
1297
+ // frame the camera on selection, and snap placed entities onto terrain.
1298
+ #[no_mangle]
1299
+ pub extern "C" fn bloom_get_model_bounds_min_x(model_handle: f64) -> f64 {
1300
+ engine().models.get_bounds(model_handle).0[0] as f64
1301
+ }
1302
+ #[no_mangle]
1303
+ pub extern "C" fn bloom_get_model_bounds_min_y(model_handle: f64) -> f64 {
1304
+ engine().models.get_bounds(model_handle).0[1] as f64
1305
+ }
1306
+ #[no_mangle]
1307
+ pub extern "C" fn bloom_get_model_bounds_min_z(model_handle: f64) -> f64 {
1308
+ engine().models.get_bounds(model_handle).0[2] as f64
1309
+ }
1310
+ #[no_mangle]
1311
+ pub extern "C" fn bloom_get_model_bounds_max_x(model_handle: f64) -> f64 {
1312
+ engine().models.get_bounds(model_handle).1[0] as f64
1313
+ }
1314
+ #[no_mangle]
1315
+ pub extern "C" fn bloom_get_model_bounds_max_y(model_handle: f64) -> f64 {
1316
+ engine().models.get_bounds(model_handle).1[1] as f64
1317
+ }
1318
+ #[no_mangle]
1319
+ pub extern "C" fn bloom_get_model_bounds_max_z(model_handle: f64) -> f64 {
1320
+ engine().models.get_bounds(model_handle).1[2] as f64
1321
+ }
1322
+
1323
+ #[no_mangle]
1324
+ pub extern "C" fn bloom_write_file(path_ptr: *const u8, data_ptr: *const u8) -> f64 {
1325
+ let path = str_from_header(path_ptr);
1326
+ let data = str_from_header(data_ptr);
1327
+ match std::fs::write(path, data.as_bytes()) {
1328
+ Ok(_) => 1.0,
1329
+ Err(_) => 0.0,
1330
+ }
1331
+ }
1332
+
1333
+ #[no_mangle]
1334
+ pub extern "C" fn bloom_file_exists(path_ptr: *const u8) -> f64 {
1335
+ let path = str_from_header(path_ptr);
1336
+ let resolved = resolve_path(path);
1337
+ if std::path::Path::new(&resolved).exists() { 1.0 } else { 0.0 }
1338
+ }
1339
+
1340
+ #[no_mangle]
1341
+ pub extern "C" fn bloom_read_file(path_ptr: *const u8) -> *const u8 {
1342
+ let path = str_from_header(path_ptr);
1343
+ match std::fs::read_to_string(resolve_path(path)) {
1344
+ Ok(contents) => {
1345
+ // Return Perry-format string: StringHeader (length u32 + capacity u32 + refcount u32) followed by UTF-8 data
1346
+ let bytes = contents.as_bytes();
1347
+ let len = bytes.len();
1348
+ let total = 12 + len; // 12 bytes header (3 × u32) + data
1349
+ let layout = std::alloc::Layout::from_size_align(total, 4).unwrap();
1350
+ unsafe {
1351
+ let ptr = std::alloc::alloc(layout);
1352
+ if ptr.is_null() { return std::ptr::null(); }
1353
+ *(ptr as *mut u32) = len as u32; // length
1354
+ *(ptr.add(4) as *mut u32) = len as u32; // capacity
1355
+ *(ptr.add(8) as *mut u32) = 1; // refcount (unique)
1356
+ std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.add(12), len);
1357
+ ptr
1358
+ }
1359
+ }
1360
+ Err(_) => std::ptr::null(),
1361
+ }
1362
+ }
1363
+
1364
+ #[no_mangle]
1365
+ pub extern "C" fn bloom_get_touch_x(index: f64) -> f64 { engine().input.get_touch_x(index as usize) }
1366
+ #[no_mangle]
1367
+ pub extern "C" fn bloom_get_touch_y(index: f64) -> f64 { engine().input.get_touch_y(index as usize) }
1368
+ #[no_mangle]
1369
+ pub extern "C" fn bloom_get_touch_count() -> f64 { engine().input.get_touch_count() as f64 }
1370
+ #[no_mangle]
1371
+ pub extern "C" fn bloom_get_time() -> f64 { engine().get_time() }
1372
+
1373
+ // Input injection + platform detection
1374
+ #[no_mangle]
1375
+ pub extern "C" fn bloom_inject_key_down(key: f64) {
1376
+ engine().input.set_key_down(key as usize);
1377
+ }
1378
+ #[no_mangle]
1379
+ pub extern "C" fn bloom_inject_key_up(key: f64) {
1380
+ engine().input.set_key_up(key as usize);
1381
+ }
1382
+ #[no_mangle]
1383
+ pub extern "C" fn bloom_inject_gamepad_axis(axis: f64, value: f64) {
1384
+ engine().input.set_gamepad_axis(axis as usize, value as f32);
1385
+ }
1386
+ #[no_mangle]
1387
+ pub extern "C" fn bloom_inject_gamepad_button_down(button: f64) {
1388
+ engine().input.set_gamepad_button_down(button as usize);
1389
+ }
1390
+ #[no_mangle]
1391
+ pub extern "C" fn bloom_inject_gamepad_button_up(button: f64) {
1392
+ engine().input.set_gamepad_button_up(button as usize);
1393
+ }
1394
+ #[no_mangle]
1395
+ pub extern "C" fn bloom_get_platform() -> f64 { 5.0 }
1396
+ #[no_mangle]
1397
+ pub extern "C" fn bloom_is_any_input_pressed() -> f64 {
1398
+ if engine().input.is_any_input_pressed() { 1.0 } else { 0.0 }
1399
+ }
1400
+ #[no_mangle]
1401
+ pub extern "C" fn bloom_get_crown_rotation() -> f64 {
1402
+ engine().input.consume_crown_rotation()
1403
+ }
1404
+
1405
+ // ============================================================
1406
+ // JNI Bridge for Bloom game applications
1407
+ // ============================================================
1408
+ //
1409
+ // These functions bridge the Android Java/Kotlin layer to the
1410
+ // Bloom engine. Any Bloom game on Android should use the
1411
+ // com.bloomengine.game.BloomGameBridge Kotlin class.
1412
+
1413
+ extern "C" {
1414
+ fn ANativeWindow_fromSurface(env: *mut libc::c_void, surface: *mut libc::c_void) -> *mut libc::c_void;
1415
+ fn mallopt(param: i32, value: i32) -> i32;
1416
+ fn __android_log_print(prio: i32, tag: *const u8, fmt: *const u8, ...) -> i32;
1417
+ fn main() -> i32;
1418
+ }
1419
+
1420
+ /// JNI_OnLoad: called when System.loadLibrary() loads this .so.
1421
+ /// Disables MTE heap tagging (required for Perry NaN-boxing) and
1422
+ /// reads the asset base path from BLOOM_ASSET_PATH env var.
1423
+ #[no_mangle]
1424
+ pub extern "C" fn JNI_OnLoad(_vm: *mut libc::c_void, _reserved: *mut libc::c_void) -> i32 {
1425
+ unsafe {
1426
+ // Disable MTE heap tagging for Perry NaN-boxing compatibility.
1427
+ // Perry uses 48-bit pointers; Android's scudo allocator may tag
1428
+ // the top byte, corrupting NaN-boxed pointer values.
1429
+ mallopt(-204, 0);
1430
+
1431
+ __android_log_print(
1432
+ 3, b"BloomEngine\0".as_ptr(),
1433
+ b"JNI_OnLoad: MTE disabled\0".as_ptr(),
1434
+ );
1435
+ }
1436
+
1437
+ // Read asset base path from environment (set by Activity before loadLibrary)
1438
+ if let Ok(path) = std::env::var("BLOOM_ASSET_PATH") {
1439
+ unsafe {
1440
+ __android_log_print(
1441
+ 3, b"BloomEngine\0".as_ptr(),
1442
+ b"JNI_OnLoad: asset path set\0".as_ptr(),
1443
+ );
1444
+ ASSET_BASE_PATH = Some(path);
1445
+ }
1446
+ }
1447
+
1448
+ 0x00010006 // JNI_VERSION_1_6
1449
+ }
1450
+
1451
+ /// Pass the Android Surface to the engine so it can create a wgpu rendering surface.
1452
+ /// Called from BloomGameBridge.nativeSetSurface(surface).
1453
+ #[no_mangle]
1454
+ pub unsafe extern "C" fn Java_com_bloomengine_game_BloomGameBridge_nativeSetSurface(
1455
+ env: *mut libc::c_void,
1456
+ _class: *mut libc::c_void,
1457
+ surface: *mut libc::c_void,
1458
+ ) {
1459
+ let window = ANativeWindow_fromSurface(env, surface);
1460
+ __android_log_print(
1461
+ 3, b"BloomEngine\0".as_ptr(),
1462
+ b"nativeSetSurface: ANativeWindow acquired\0".as_ptr(),
1463
+ );
1464
+ bloom_android_set_native_window(window);
1465
+ }
1466
+
1467
+ /// Run the compiled game's main() function on the game thread.
1468
+ /// Called from BloomGameBridge.nativeMain().
1469
+ #[no_mangle]
1470
+ pub unsafe extern "C" fn Java_com_bloomengine_game_BloomGameBridge_nativeMain(
1471
+ _env: *mut libc::c_void,
1472
+ _class: *mut libc::c_void,
1473
+ ) {
1474
+ __android_log_print(
1475
+ 3, b"BloomEngine\0".as_ptr(),
1476
+ b"nativeMain: calling main()\0".as_ptr(),
1477
+ );
1478
+ main();
1479
+ __android_log_print(
1480
+ 3, b"BloomEngine\0".as_ptr(),
1481
+ b"nativeMain: main() returned\0".as_ptr(),
1482
+ );
1483
+ }
1484
+
1485
+ /// Forward touch events from the Android UI thread to the engine's input system.
1486
+ /// Called from BloomGameBridge.nativeOnTouch(action, x, y, pointerIndex).
1487
+ #[no_mangle]
1488
+ pub extern "C" fn Java_com_bloomengine_game_BloomGameBridge_nativeOnTouch(
1489
+ _env: *mut libc::c_void,
1490
+ _class: *mut libc::c_void,
1491
+ action: i32,
1492
+ x: f64,
1493
+ y: f64,
1494
+ pointer_index: i32,
1495
+ ) {
1496
+ bloom_android_on_touch(action, x, y, pointer_index);
1497
+ }
1498
+
1499
+ /// Signal the engine to close when the Activity is destroyed.
1500
+ /// Called from BloomGameBridge.nativeOnDestroy().
1501
+ #[no_mangle]
1502
+ pub extern "C" fn Java_com_bloomengine_game_BloomGameBridge_nativeOnDestroy(
1503
+ _env: *mut libc::c_void,
1504
+ _class: *mut libc::c_void,
1505
+ ) {
1506
+ unsafe {
1507
+ if let Some(eng) = ENGINE.get_mut() {
1508
+ eng.should_close = true;
1509
+ }
1510
+ }
1511
+ }
1512
+
1513
+ // ============================================================
1514
+ // Thread-safe staging (for async asset loading via Perry threads)
1515
+ // ============================================================
1516
+
1517
+ #[no_mangle]
1518
+ pub extern "C" fn bloom_stage_texture(path_ptr: *const u8) -> f64 {
1519
+ let path = str_from_header(path_ptr);
1520
+ match std::fs::read(resolve_path(path)) {
1521
+ Ok(data) => bloom_shared::staging::decode_and_stage_texture(&data),
1522
+ Err(_) => 0.0,
1523
+ }
1524
+ }
1525
+
1526
+ #[no_mangle]
1527
+ pub extern "C" fn bloom_stage_model(path_ptr: *const u8) -> f64 {
1528
+ let path = str_from_header(path_ptr);
1529
+ let data = match std::fs::read(resolve_path(path)) {
1530
+ Ok(d) => d,
1531
+ Err(_) => return 0.0,
1532
+ };
1533
+ match bloom_shared::models::load_gltf_staged(&data) {
1534
+ Some(staged) => bloom_shared::staging::stage_model(staged),
1535
+ None => 0.0,
1536
+ }
1537
+ }
1538
+
1539
+ #[no_mangle]
1540
+ pub extern "C" fn bloom_stage_sound(path_ptr: *const u8) -> f64 {
1541
+ let path = str_from_header(path_ptr);
1542
+ let data = match std::fs::read(resolve_path(path)) {
1543
+ Ok(d) => d,
1544
+ Err(_) => return 0.0,
1545
+ };
1546
+ let sound_data = if path.ends_with(".ogg") || path.ends_with(".OGG") {
1547
+ parse_ogg(&data)
1548
+ } else if path.ends_with(".mp3") || path.ends_with(".MP3") {
1549
+ parse_mp3(&data)
1550
+ } else {
1551
+ parse_wav(&data)
1552
+ };
1553
+ match sound_data {
1554
+ Some(sd) => bloom_shared::staging::stage_sound(sd),
1555
+ None => 0.0,
1556
+ }
1557
+ }
1558
+
1559
+ #[no_mangle]
1560
+ pub extern "C" fn bloom_commit_texture(staging_handle: f64) -> f64 {
1561
+ let staged = match bloom_shared::staging::take_texture(staging_handle) {
1562
+ Some(s) => s,
1563
+ None => return 0.0,
1564
+ };
1565
+ let eng = engine();
1566
+ let bind_group_idx = eng.renderer.register_texture(staged.width, staged.height, &staged.data);
1567
+ eng.textures.textures.alloc(bloom_shared::textures::TextureData {
1568
+ bind_group_idx, width: staged.width, height: staged.height,
1569
+ })
1570
+ }
1571
+
1572
+ #[no_mangle]
1573
+ pub extern "C" fn bloom_commit_model(staging_handle: f64) -> f64 {
1574
+ let staged = match bloom_shared::staging::take_model(staging_handle) {
1575
+ Some(s) => s,
1576
+ None => return 0.0,
1577
+ };
1578
+ let eng = engine();
1579
+ let mut tex_map: Vec<u32> = Vec::with_capacity(staged.textures.len());
1580
+ for tex in &staged.textures {
1581
+ tex_map.push(eng.renderer.register_texture(tex.width, tex.height, &tex.data));
1582
+ }
1583
+ let mut model = staged.model;
1584
+ for mesh in &mut model.meshes {
1585
+ if let Some(ref mut idx) = mesh.texture_idx {
1586
+ let staged_idx = *idx as usize;
1587
+ if staged_idx > 0 && staged_idx <= tex_map.len() {
1588
+ *idx = tex_map[staged_idx - 1];
1589
+ } else {
1590
+ mesh.texture_idx = None;
1591
+ }
1592
+ }
1593
+ }
1594
+ eng.models.models.alloc(model)
1595
+ }
1596
+
1597
+ #[no_mangle]
1598
+ pub extern "C" fn bloom_commit_sound(staging_handle: f64) -> f64 {
1599
+ match bloom_shared::staging::take_sound(staging_handle) {
1600
+ Some(sd) => engine().audio.load_sound(sd),
1601
+ None => 0.0,
1602
+ }
1603
+ }
1604
+
1605
+ #[no_mangle]
1606
+ pub extern "C" fn bloom_commit_music(staging_handle: f64) -> f64 {
1607
+ match bloom_shared::staging::take_sound(staging_handle) {
1608
+ Some(sd) => engine().audio.load_music(sd),
1609
+ None => 0.0,
1610
+ }
1611
+ }
1612
+
1613
+ #[no_mangle]
1614
+ pub extern "C" fn bloom_run_game(_callback: extern "C" fn(f64)) {
1615
+ // No-op on native. The TypeScript runGame() helper provides the while loop.
1616
+ }
1617
+
1618
+
1619
+
1620
+ // Q6: Multi-hit picking
1621
+ static mut LAST_PICK_ALL: Vec<bloom_shared::picking::PickResult> = Vec::new();
1622
+
1623
+ #[no_mangle]
1624
+ pub extern "C" fn bloom_scene_pick_all(screen_x: f64, screen_y: f64, max_results: f64) -> f64 {
1625
+ let eng = engine();
1626
+ let inv_vp = eng.renderer.inverse_vp_matrix();
1627
+ let cam_pos = eng.renderer.camera_pos();
1628
+ let w = eng.renderer.width() as f32;
1629
+ let h = eng.renderer.height() as f32;
1630
+ let (origin, direction) = bloom_shared::picking::screen_to_ray(
1631
+ screen_x as f32, screen_y as f32, w, h, &inv_vp, &cam_pos,
1632
+ );
1633
+ let results = bloom_shared::picking::raycast_scene_all(&eng.scene, &origin, &direction, max_results as usize);
1634
+ let count = results.len();
1635
+ unsafe { LAST_PICK_ALL = results; }
1636
+ count as f64
1637
+ }
1638
+ #[no_mangle]
1639
+ pub extern "C" fn bloom_pick_all_handle(index: f64) -> f64 {
1640
+ let i = index as usize;
1641
+ unsafe { LAST_PICK_ALL.get(i).map(|r| r.handle).unwrap_or(0.0) }
1642
+ }
1643
+ #[no_mangle]
1644
+ pub extern "C" fn bloom_pick_all_distance(index: f64) -> f64 {
1645
+ let i = index as usize;
1646
+ unsafe { LAST_PICK_ALL.get(i).map(|r| r.distance as f64).unwrap_or(0.0) }
1647
+ }
1648
+ // ============================================================
1649
+
1650
+ #[no_mangle] pub extern "C" fn bloom_take_screenshot(_path_ptr: *const u8) {}
1651
+ #[no_mangle] pub extern "C" fn bloom_set_env_clear_from_hdr(_path_ptr: *const u8) {}
1652
+ #[no_mangle] pub extern "C" fn bloom_set_fog(_r: f64, _g: f64, _b: f64, _density: f64, _height_ref: f64, _height_falloff: f64) {}
1653
+ #[no_mangle] pub extern "C" fn bloom_set_chromatic_aberration(_strength: f64) {}
1654
+ #[no_mangle] pub extern "C" fn bloom_set_vignette(_strength: f64, _softness: f64) {}
1655
+ #[no_mangle] pub extern "C" fn bloom_set_film_grain(_strength: f64) {}
1656
+ #[no_mangle] pub extern "C" fn bloom_set_sun_shafts(_strength: f64, _decay: f64, _r: f64, _g: f64, _b: f64) {}
1657
+ #[no_mangle] pub extern "C" fn bloom_set_auto_exposure(_on: f64) {}
1658
+ #[no_mangle] pub extern "C" fn bloom_set_taa_enabled(_on: f64) {}
1659
+ #[no_mangle] pub extern "C" fn bloom_set_render_scale(_scale: f64) {}
1660
+ #[no_mangle] pub extern "C" fn bloom_get_render_scale() -> f64 { 1.0 }
1661
+ #[no_mangle] pub extern "C" fn bloom_set_upscale_mode(_mode: f64) {}
1662
+ #[no_mangle] pub extern "C" fn bloom_set_cas_strength(_strength: f64) {}
1663
+ #[no_mangle] pub extern "C" fn bloom_get_physical_width() -> f64 { 0.0 }
1664
+ #[no_mangle] pub extern "C" fn bloom_get_physical_height() -> f64 { 0.0 }
1665
+ #[no_mangle] pub extern "C" fn bloom_set_auto_resolution(_target_hz: f64, _enabled: f64) {}
1666
+ #[no_mangle] pub extern "C" fn bloom_set_manual_exposure(_value: f64) {}
1667
+ #[no_mangle] pub extern "C" fn bloom_set_env_intensity(_intensity: f64) {}
1668
+ #[no_mangle] pub extern "C" fn bloom_set_ssgi_enabled(_enabled: f64) {}
1669
+ #[no_mangle] pub extern "C" fn bloom_set_ssgi_intensity(_intensity: f64) {}
1670
+ #[no_mangle] pub extern "C" fn bloom_set_ssgi_radius(_radius: f64) {}
1671
+ #[no_mangle] pub extern "C" fn bloom_set_dof(_enabled: f64, _focus_distance: f64, _aperture: f64) {}
1672
+ // Ticket 011: real quality / profiler implementations. Prior build had
1673
+ // no-op stubs — TS games calling setQualityPreset / setProfilerEnabled etc.
1674
+ // linked fine but did nothing at runtime on Android.
1675
+ #[no_mangle] pub extern "C" fn bloom_set_quality_preset(preset: f64) {
1676
+ engine().renderer.apply_quality_preset(preset as u32);
1677
+ }
1678
+ #[no_mangle] pub extern "C" fn bloom_set_shadows_enabled(on: f64) {
1679
+ engine().renderer.set_shadows_enabled(on != 0.0);
1680
+ }
1681
+ #[no_mangle] pub extern "C" fn bloom_set_shadows_always_fresh(on: f64) {
1682
+ engine().renderer.set_shadows_always_fresh(on != 0.0);
1683
+ }
1684
+ #[no_mangle] pub extern "C" fn bloom_set_bloom_enabled(on: f64) {
1685
+ engine().renderer.set_bloom_enabled(on != 0.0);
1686
+ }
1687
+ #[no_mangle] pub extern "C" fn bloom_set_early_z_enabled(_on: f64) {}
1688
+ #[no_mangle] pub extern "C" fn bloom_set_ssao_enabled(on: f64) {
1689
+ engine().renderer.set_ssao_enabled(on != 0.0);
1690
+ }
1691
+ #[no_mangle] pub extern "C" fn bloom_set_ssao_intensity(value: f64) {
1692
+ engine().renderer.set_ssao_strength(value as f32);
1693
+ }
1694
+ #[no_mangle] pub extern "C" fn bloom_set_ssao_radius(world_radius: f64) {
1695
+ engine().renderer.set_ssao_radius(world_radius as f32);
1696
+ }
1697
+ #[no_mangle] pub extern "C" fn bloom_set_wind(dir_x: f64, dir_z: f64, amplitude: f64, frequency: f64) {
1698
+ engine().renderer.set_wind(dir_x as f32, dir_z as f32, amplitude as f32, frequency as f32);
1699
+ }
1700
+ #[no_mangle] pub extern "C" fn bloom_set_ssr_enabled(on: f64) {
1701
+ engine().renderer.set_ssr_enabled(on != 0.0);
1702
+ }
1703
+ #[no_mangle] pub extern "C" fn bloom_set_motion_blur_enabled(on: f64) {
1704
+ engine().renderer.set_motion_blur_enabled(on != 0.0);
1705
+ }
1706
+ #[no_mangle] pub extern "C" fn bloom_set_sss_enabled(on: f64) {
1707
+ engine().renderer.set_sss_enabled(on != 0.0);
1708
+ }
1709
+ #[no_mangle] pub extern "C" fn bloom_set_profiler_enabled(on: f64) {
1710
+ engine().profiler.set_enabled(on != 0.0);
1711
+ }
1712
+ #[no_mangle] pub extern "C" fn bloom_get_profiler_frame_cpu_us() -> f64 {
1713
+ engine().profiler.avg_frame_cpu_us()
1714
+ }
1715
+ #[no_mangle] pub extern "C" fn bloom_get_profiler_frame_gpu_us() -> f64 {
1716
+ engine().profiler.avg_frame_gpu_us()
1717
+ }
1718
+ #[no_mangle] pub extern "C" fn bloom_print_profiler_summary() {
1719
+ // Android has no stdout — log the summary via android_log so
1720
+ // `adb logcat` picks it up alongside the rest of the engine log.
1721
+ // %s + ptr variant so `%` characters in the summary (none today,
1722
+ // but cheap safety) aren't interpreted as format specifiers.
1723
+ let summary = engine().profiler.summary();
1724
+ if let Ok(c) = std::ffi::CString::new(summary) {
1725
+ unsafe {
1726
+ __android_log_print(
1727
+ 4,
1728
+ b"BloomEngine\0".as_ptr(),
1729
+ b"%s\0".as_ptr(),
1730
+ c.as_ptr(),
1731
+ );
1732
+ }
1733
+ }
1734
+ }
1735
+
1736
+ // ============================================================
1737
+ // Physics (Jolt 5.x) — FFI surface generated from shared macro
1738
+ // ============================================================
1739
+
1740
+ #[cfg(feature = "jolt")]
1741
+ #[inline]
1742
+ fn bloom_jolt_ffi_physics() -> &'static mut bloom_shared::physics_jolt::JoltPhysics {
1743
+ &mut engine().jolt
1744
+ }
1745
+
1746
+ #[cfg(feature = "jolt")]
1747
+ bloom_shared::define_physics_ffi!();