@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.
- package/LICENSE +21 -0
- package/README.md +169 -0
- package/native/android/Cargo.lock +1848 -0
- package/native/android/Cargo.toml +20 -0
- package/native/android/src/lib.rs +1747 -0
- package/native/ios/Cargo.lock +1688 -0
- package/native/ios/Cargo.toml +19 -0
- package/native/ios/src/lib.rs +2258 -0
- package/native/linux/Cargo.lock +1719 -0
- package/native/linux/Cargo.toml +22 -0
- package/native/linux/src/lib.rs +2236 -0
- package/native/macos/Cargo.lock +3310 -0
- package/native/macos/Cargo.toml +29 -0
- package/native/macos/src/lib.rs +3444 -0
- package/native/shared/Cargo.lock +1898 -0
- package/native/shared/Cargo.toml +42 -0
- package/native/shared/assets/default_font.ttf +0 -0
- package/native/shared/build.rs +77 -0
- package/native/shared/shaders/common/fog.wgsl +16 -0
- package/native/shared/shaders/common/imposter.wgsl +112 -0
- package/native/shared/shaders/common/pbr.wgsl +186 -0
- package/native/shared/shaders/common/shadows.wgsl +77 -0
- package/native/shared/shaders/common/sky.wgsl +8 -0
- package/native/shared/shaders/common/tonemap.wgsl +25 -0
- package/native/shared/shaders/impulse_field.wgsl +53 -0
- package/native/shared/shaders/material_abi.wgsl +360 -0
- package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
- package/native/shared/src/audio.rs +363 -0
- package/native/shared/src/custom_shaders.rs +104 -0
- package/native/shared/src/drs.rs +211 -0
- package/native/shared/src/engine.rs +186 -0
- package/native/shared/src/frame_callbacks.rs +88 -0
- package/native/shared/src/geometry.rs +236 -0
- package/native/shared/src/handles.rs +76 -0
- package/native/shared/src/input.rs +273 -0
- package/native/shared/src/jolt_sys.rs +822 -0
- package/native/shared/src/lib.rs +43 -0
- package/native/shared/src/models.rs +1941 -0
- package/native/shared/src/physics_jolt.rs +1528 -0
- package/native/shared/src/picking.rs +298 -0
- package/native/shared/src/postfx.rs +339 -0
- package/native/shared/src/profiler.rs +416 -0
- package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
- package/native/shared/src/renderer/brdf_lut.rs +154 -0
- package/native/shared/src/renderer/formats.rs +778 -0
- package/native/shared/src/renderer/graph.rs +465 -0
- package/native/shared/src/renderer/hot_reload.rs +390 -0
- package/native/shared/src/renderer/impulse_field.rs +455 -0
- package/native/shared/src/renderer/material_pipeline.rs +604 -0
- package/native/shared/src/renderer/material_system.rs +2106 -0
- package/native/shared/src/renderer/mod.rs +13923 -0
- package/native/shared/src/renderer/planar_reflection.rs +458 -0
- package/native/shared/src/renderer/post_pass.rs +249 -0
- package/native/shared/src/renderer/shader_include.rs +205 -0
- package/native/shared/src/renderer/shader_library.rs +134 -0
- package/native/shared/src/renderer/shaders.rs +5855 -0
- package/native/shared/src/renderer/transient.rs +576 -0
- package/native/shared/src/renderer/types.rs +259 -0
- package/native/shared/src/renderer/util.rs +151 -0
- package/native/shared/src/scene.rs +1066 -0
- package/native/shared/src/sdf_cache.rs +274 -0
- package/native/shared/src/shadows.rs +551 -0
- package/native/shared/src/staging.rs +90 -0
- package/native/shared/src/string_header.rs +35 -0
- package/native/shared/src/text_renderer.rs +456 -0
- package/native/shared/src/textures.rs +154 -0
- package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.cpp +242 -0
- package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.h +121 -0
- package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeToBuffer.h +296 -0
- package/native/third_party/JoltPhysics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h +323 -0
- package/native/third_party/JoltPhysics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h +555 -0
- package/native/third_party/JoltPhysics/Jolt/ConfigurationString.h +112 -0
- package/native/third_party/JoltPhysics/Jolt/Core/ARMNeon.h +94 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Array.h +713 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Atomics.h +44 -0
- package/native/third_party/JoltPhysics/Jolt/Core/BinaryHeap.h +96 -0
- package/native/third_party/JoltPhysics/Jolt/Core/ByteBuffer.h +74 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Color.cpp +38 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Color.h +98 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Core.h +652 -0
- package/native/third_party/JoltPhysics/Jolt/Core/FPControlWord.h +143 -0
- package/native/third_party/JoltPhysics/Jolt/Core/FPException.h +96 -0
- package/native/third_party/JoltPhysics/Jolt/Core/FPFlushDenormals.h +43 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Factory.cpp +92 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Factory.h +54 -0
- package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.h +122 -0
- package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.inl +215 -0
- package/native/third_party/JoltPhysics/Jolt/Core/HashCombine.h +234 -0
- package/native/third_party/JoltPhysics/Jolt/Core/HashTable.h +876 -0
- package/native/third_party/JoltPhysics/Jolt/Core/InsertionSort.h +58 -0
- package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.cpp +27 -0
- package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.h +38 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.h +311 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.inl +56 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.cpp +65 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.h +62 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.cpp +364 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.h +101 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.cpp +230 -0
- package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.h +85 -0
- package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.cpp +51 -0
- package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.h +67 -0
- package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.h +182 -0
- package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.inl +351 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Memory.cpp +85 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Memory.h +85 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Mutex.h +223 -0
- package/native/third_party/JoltPhysics/Jolt/Core/MutexArray.h +98 -0
- package/native/third_party/JoltPhysics/Jolt/Core/NonCopyable.h +18 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Profiler.cpp +677 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Profiler.h +301 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Profiler.inl +90 -0
- package/native/third_party/JoltPhysics/Jolt/Core/QuickSort.h +137 -0
- package/native/third_party/JoltPhysics/Jolt/Core/RTTI.cpp +149 -0
- package/native/third_party/JoltPhysics/Jolt/Core/RTTI.h +436 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Reference.h +244 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Result.h +174 -0
- package/native/third_party/JoltPhysics/Jolt/Core/STLAlignedAllocator.h +72 -0
- package/native/third_party/JoltPhysics/Jolt/Core/STLAllocator.h +127 -0
- package/native/third_party/JoltPhysics/Jolt/Core/STLLocalAllocator.h +170 -0
- package/native/third_party/JoltPhysics/Jolt/Core/STLTempAllocator.h +80 -0
- package/native/third_party/JoltPhysics/Jolt/Core/ScopeExit.h +49 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.cpp +135 -0
- package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.h +68 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StaticArray.h +329 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StreamIn.h +120 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StreamOut.h +97 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StreamUtils.h +168 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StreamWrapper.h +53 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StridedPtr.h +63 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StringTools.cpp +101 -0
- package/native/third_party/JoltPhysics/Jolt/Core/StringTools.h +38 -0
- package/native/third_party/JoltPhysics/Jolt/Core/TempAllocator.h +209 -0
- package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.cpp +37 -0
- package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.h +58 -0
- package/native/third_party/JoltPhysics/Jolt/Core/UnorderedMap.h +80 -0
- package/native/third_party/JoltPhysics/Jolt/Core/UnorderedSet.h +32 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/AABox.h +313 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/AABox4.h +224 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ClipPoly.h +200 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ClosestPoint.h +498 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.cpp +1467 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.h +276 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.cpp +335 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.h +105 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexSupport.h +188 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/EPAConvexHullBuilder.h +845 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/EPAPenetrationDepth.h +557 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/Ellipse.h +77 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/GJKClosestPoint.h +945 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/IndexedTriangle.h +130 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.cpp +222 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.h +19 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/MortonCode.h +40 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.cpp +178 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.h +39 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/Plane.h +104 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/RayAABox.h +241 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/RayCapsule.h +37 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/RayCylinder.h +101 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/RaySphere.h +96 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/RayTriangle.h +158 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/Sphere.h +72 -0
- package/native/third_party/JoltPhysics/Jolt/Geometry/Triangle.h +34 -0
- package/native/third_party/JoltPhysics/Jolt/Jolt.cmake +703 -0
- package/native/third_party/JoltPhysics/Jolt/Jolt.h +16 -0
- package/native/third_party/JoltPhysics/Jolt/Jolt.natvis +116 -0
- package/native/third_party/JoltPhysics/Jolt/Math/BVec16.h +99 -0
- package/native/third_party/JoltPhysics/Jolt/Math/BVec16.inl +177 -0
- package/native/third_party/JoltPhysics/Jolt/Math/DMat44.h +158 -0
- package/native/third_party/JoltPhysics/Jolt/Math/DMat44.inl +310 -0
- package/native/third_party/JoltPhysics/Jolt/Math/DVec3.h +291 -0
- package/native/third_party/JoltPhysics/Jolt/Math/DVec3.inl +941 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Double3.h +48 -0
- package/native/third_party/JoltPhysics/Jolt/Math/DynMatrix.h +31 -0
- package/native/third_party/JoltPhysics/Jolt/Math/EigenValueSymmetric.h +177 -0
- package/native/third_party/JoltPhysics/Jolt/Math/FindRoot.h +42 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Float2.h +36 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Float3.h +50 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Float4.h +44 -0
- package/native/third_party/JoltPhysics/Jolt/Math/GaussianElimination.h +102 -0
- package/native/third_party/JoltPhysics/Jolt/Math/HalfFloat.h +208 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Mat44.h +243 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Mat44.inl +952 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Math.h +208 -0
- package/native/third_party/JoltPhysics/Jolt/Math/MathTypes.h +32 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Matrix.h +259 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Quat.h +268 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Quat.inl +406 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Real.h +44 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Swizzle.h +19 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Trigonometry.h +79 -0
- package/native/third_party/JoltPhysics/Jolt/Math/UVec4.h +232 -0
- package/native/third_party/JoltPhysics/Jolt/Math/UVec4.inl +636 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Vec3.cpp +71 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Vec3.h +308 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Vec3.inl +942 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Vec4.h +320 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Vec4.inl +1152 -0
- package/native/third_party/JoltPhysics/Jolt/Math/Vector.h +211 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/GetPrimitiveTypeOfType.h +54 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.cpp +38 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.h +337 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.cpp +252 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.h +57 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.cpp +165 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.h +57 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.cpp +635 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.h +148 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.cpp +166 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.h +101 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.cpp +418 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.h +55 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.cpp +255 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.h +62 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTypes.h +26 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttribute.h +111 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeEnum.h +67 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeTyped.h +60 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.cpp +15 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.h +170 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.cpp +70 -0
- package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.h +45 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/AllowedDOFs.h +68 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.cpp +426 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.h +452 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.inl +197 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyAccess.h +68 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyActivationListener.h +28 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.cpp +234 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.h +124 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyFilter.h +130 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyID.h +101 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.cpp +1099 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.h +324 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLock.h +111 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockInterface.h +134 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockMulti.h +120 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.cpp +1220 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.h +403 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyPair.h +36 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyType.h +19 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.cpp +185 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.h +58 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.cpp +92 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.h +308 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.inl +178 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionQuality.h +31 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionType.h +17 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.cpp +354 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.h +159 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.cpp +59 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.h +157 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterID.h +98 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.cpp +1933 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.h +752 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/AABoxCast.h +20 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdgeMode.h +17 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdges.h +114 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BackFaceMode.h +16 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.cpp +16 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h +109 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp +313 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h +38 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h +148 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceMask.h +92 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceTable.h +64 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp +629 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h +108 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuery.h +56 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterMask.h +35 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterTable.h +66 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp +1768 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.h +389 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.cpp +107 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.h +46 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastResult.h +37 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp +223 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.h +49 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollectFacesMode.h +16 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.cpp +155 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.h +56 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollidePointResult.h +25 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShape.h +106 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShapeVsShapePerLeaf.h +94 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVertexIterator.h +110 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVerticesVsTriangles.h +102 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.cpp +121 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.h +50 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollector.h +109 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollectorImpl.h +219 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.cpp +107 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.h +97 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.cpp +35 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.h +97 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ContactListener.h +143 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.cpp +213 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.h +48 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.cpp +32 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.h +46 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.cpp +38 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.h +130 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h +279 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.cpp +271 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.h +44 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp +448 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.h +77 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.cpp +62 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.h +110 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayer.h +111 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterMask.h +52 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterTable.h +78 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.cpp +35 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.h +57 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.cpp +38 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.h +37 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/RayCast.h +87 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.cpp +318 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.h +115 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.cpp +438 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.h +129 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.cpp +433 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.h +354 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShapeVisitors.h +461 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp +1311 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.h +202 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.cpp +566 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.h +150 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.cpp +418 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.h +126 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.cpp +87 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.h +80 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.cpp +64 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.h +75 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/GetTrianglesContext.h +248 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp +2754 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.h +380 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.cpp +1305 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.h +228 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.cpp +596 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.h +176 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp +217 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h +140 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.cpp +541 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.h +147 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PolyhedronSubmergedVolumeCalculator.h +319 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp +333 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h +161 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaleHelpers.h +83 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.cpp +238 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.h +145 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.cpp +325 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.h +466 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.cpp +347 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.h +125 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.cpp +674 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.h +139 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeID.h +138 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h +65 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp +453 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.gliffy +1 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h +135 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp +691 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.h +132 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.cpp +430 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.h +143 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeCast.h +173 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeFilter.h +73 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilter.h +40 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilterWrapper.h +58 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SortReverseAndStore.h +48 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.cpp +180 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.h +194 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/CalculateSolverSteps.h +70 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.cpp +246 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.h +133 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.cpp +73 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.h +243 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.cpp +289 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.h +100 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AngleConstraintPart.h +257 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h +682 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h +276 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/GearConstraintPart.h +195 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h +222 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/IndependentAxisConstraintPart.h +246 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/PointConstraintPart.h +239 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RackAndPinionConstraintPart.h +196 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h +283 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationQuatConstraintPart.h +246 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SpringPart.h +169 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h +597 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.cpp +1804 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.h +524 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.cpp +266 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.h +120 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.cpp +215 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.h +96 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.cpp +188 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.h +116 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.cpp +443 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.h +205 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.cpp +43 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.h +66 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.cpp +458 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.h +191 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.cpp +85 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.h +76 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.cpp +308 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.h +54 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.cpp +157 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.h +94 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.cpp +253 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.h +137 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.cpp +189 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.h +118 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.cpp +900 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.h +289 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.cpp +501 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.h +198 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.cpp +35 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.h +70 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.cpp +524 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.h +197 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.cpp +56 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.h +65 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.cpp +17 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.h +159 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/EActivation.h +16 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/EPhysicsUpdateError.h +37 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.cpp +492 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.h +144 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.cpp +582 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.h +187 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsLock.h +169 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.cpp +261 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.h +104 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSettings.h +125 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsStepListener.h +37 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.cpp +2915 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.h +391 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.cpp +25 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.h +176 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.cpp +744 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.h +245 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyContactListener.h +55 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp +128 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.h +75 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyManifold.h +74 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp +1501 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h +333 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.cpp +354 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.h +73 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp +1487 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h +390 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyUpdateContext.h +63 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyVertex.h +36 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorder.h +136 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.cpp +90 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.h +50 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.cpp +306 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.h +119 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.cpp +547 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.h +169 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.cpp +33 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.h +33 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.cpp +376 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.h +146 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.cpp +703 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.h +252 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.cpp +17 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.h +87 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.cpp +81 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.h +39 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.cpp +122 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.h +93 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.cpp +52 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.h +56 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.cpp +159 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.h +87 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.cpp +93 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.h +148 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.cpp +866 -0
- package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.h +205 -0
- package/native/third_party/JoltPhysics/Jolt/RegisterTypes.cpp +204 -0
- package/native/third_party/JoltPhysics/Jolt/RegisterTypes.h +29 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.cpp +1107 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.h +383 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.cpp +168 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.h +48 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.cpp +158 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.h +130 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.cpp +80 -0
- package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.h +88 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.cpp +165 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.h +91 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.cpp +82 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.h +72 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.cpp +237 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.h +145 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.cpp +87 -0
- package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.h +82 -0
- package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.cpp +73 -0
- package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.h +84 -0
- package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.cpp +139 -0
- package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.h +52 -0
- package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.cpp +43 -0
- package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.h +28 -0
- package/native/third_party/JoltPhysics/LICENSE +7 -0
- package/native/third_party/JoltPhysics/README.md +173 -0
- package/native/third_party/bloom_jolt/CMakeLists.txt +78 -0
- package/native/third_party/bloom_jolt/include/bloom_jolt.h +519 -0
- package/native/third_party/bloom_jolt/src/bloom_jolt.cpp +1780 -0
- package/native/tvos/Cargo.lock +1692 -0
- package/native/tvos/Cargo.toml +22 -0
- package/native/tvos/src/lib.rs +3179 -0
- package/native/watchos/Cargo.lock +16 -0
- package/native/watchos/Cargo.toml +19 -0
- package/native/watchos/shaders/bloom_postfx.metal +99 -0
- package/native/watchos/src/BloomWatchApp.swift +1236 -0
- package/native/watchos/src/BloomWatchAudio.swift +179 -0
- package/native/watchos/src/audio.rs +55 -0
- package/native/watchos/src/draw_list.rs +223 -0
- package/native/watchos/src/ffi_stubs.rs +454 -0
- package/native/watchos/src/lib.rs +1013 -0
- package/native/watchos/src/models.rs +746 -0
- package/native/watchos/src/postfx.rs +91 -0
- package/native/watchos/src/scene.rs +534 -0
- package/native/watchos/src/textures.rs +184 -0
- package/native/web/Cargo.lock +1656 -0
- package/native/web/Cargo.toml +38 -0
- package/native/web/bloom_glue.js +218 -0
- package/native/web/build.sh +101 -0
- package/native/web/index.html +390 -0
- package/native/web/jolt_bridge.js +1311 -0
- package/native/web/src/lib.rs +2739 -0
- package/native/windows/Cargo.lock +1813 -0
- package/native/windows/Cargo.toml +31 -0
- package/native/windows/src/lib.rs +1933 -0
- package/package.json +558 -0
- package/src/audio/index.ts +151 -0
- package/src/core/colors.ts +56 -0
- package/src/core/index.ts +903 -0
- package/src/core/keys.ts +63 -0
- package/src/core/types.ts +102 -0
- package/src/index.ts +158 -0
- package/src/math/index.ts +502 -0
- package/src/mobile/index.ts +294 -0
- package/src/models/index.ts +859 -0
- package/src/physics/index.ts +1072 -0
- package/src/scene/index.ts +570 -0
- package/src/shapes/index.ts +120 -0
- package/src/text/index.ts +48 -0
- package/src/textures/index.ts +173 -0
- package/src/world/index.ts +22 -0
- package/src/world/loader.ts +385 -0
- package/src/world/prefab.ts +205 -0
- package/src/world/saver.ts +61 -0
- package/src/world/terrain.ts +254 -0
- package/src/world/types.ts +136 -0
- package/src/world/validate.ts +202 -0
- package/src/world/version.ts +47 -0
|
@@ -0,0 +1,2236 @@
|
|
|
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::os::unix::io::RawFd;
|
|
8
|
+
|
|
9
|
+
static mut ENGINE: OnceLock<EngineState> = OnceLock::new();
|
|
10
|
+
static mut GAMEPAD_FD: RawFd = -1;
|
|
11
|
+
|
|
12
|
+
fn engine() -> &'static mut EngineState {
|
|
13
|
+
unsafe { ENGINE.get_mut().expect("Engine not initialized") }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Map X11 keysym to Bloom key code.
|
|
17
|
+
fn map_keycode(keysym: u32) -> usize {
|
|
18
|
+
match keysym {
|
|
19
|
+
0x61..=0x7a => (keysym - 0x61 + 65) as usize, // a-z → A-Z (65-90)
|
|
20
|
+
0x41..=0x5a => keysym as usize, // A-Z direct
|
|
21
|
+
0x30..=0x39 => keysym as usize, // 0-9
|
|
22
|
+
0xff52 => 256, // XK_Up
|
|
23
|
+
0xff54 => 257, // XK_Down
|
|
24
|
+
0xff51 => 258, // XK_Left
|
|
25
|
+
0xff53 => 259, // XK_Right
|
|
26
|
+
0x20 => 32, // space
|
|
27
|
+
0xff0d => 265, // XK_Return → Bloom ENTER
|
|
28
|
+
0xff1b => 27, // XK_Escape
|
|
29
|
+
0xff09 => 9, // XK_Tab
|
|
30
|
+
0xff08 => 8, // XK_BackSpace
|
|
31
|
+
0xffff => 127, // XK_Delete
|
|
32
|
+
0xff63 => 260, // XK_Insert
|
|
33
|
+
0xff50 => 261, // XK_Home
|
|
34
|
+
0xff57 => 262, // XK_End
|
|
35
|
+
0xff55 => 263, // XK_Page_Up
|
|
36
|
+
0xff56 => 264, // XK_Page_Down
|
|
37
|
+
0xffe1 => 280, // XK_Shift_L
|
|
38
|
+
0xffe2 => 281, // XK_Shift_R
|
|
39
|
+
0xffe3 => 282, // XK_Control_L
|
|
40
|
+
0xffe4 => 283, // XK_Control_R
|
|
41
|
+
0xffe9 => 284, // XK_Alt_L
|
|
42
|
+
0xffea => 285, // XK_Alt_R
|
|
43
|
+
0xffeb => 286, // XK_Super_L
|
|
44
|
+
0xffec => 287, // XK_Super_R
|
|
45
|
+
// Function keys
|
|
46
|
+
0xffbe => 112, // XK_F1
|
|
47
|
+
0xffbf => 113, // XK_F2
|
|
48
|
+
0xffc0 => 114, // XK_F3
|
|
49
|
+
0xffc1 => 115, // XK_F4
|
|
50
|
+
0xffc2 => 116, // XK_F5
|
|
51
|
+
0xffc3 => 117, // XK_F6
|
|
52
|
+
0xffc4 => 118, // XK_F7
|
|
53
|
+
0xffc5 => 119, // XK_F8
|
|
54
|
+
0xffc6 => 120, // XK_F9
|
|
55
|
+
0xffc7 => 121, // XK_F10
|
|
56
|
+
0xffc8 => 122, // XK_F11
|
|
57
|
+
0xffc9 => 123, // XK_F12
|
|
58
|
+
_ => 0,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#[cfg(target_os = "linux")]
|
|
63
|
+
mod x11_impl {
|
|
64
|
+
use super::*;
|
|
65
|
+
|
|
66
|
+
static mut DISPLAY: *mut x11::xlib::Display = std::ptr::null_mut();
|
|
67
|
+
static mut X11_WINDOW: x11::xlib::Window = 0;
|
|
68
|
+
static mut IS_FULLSCREEN: bool = false;
|
|
69
|
+
|
|
70
|
+
pub fn set_fullscreen(fullscreen: bool) {
|
|
71
|
+
unsafe {
|
|
72
|
+
if DISPLAY.is_null() || X11_WINDOW == 0 { return; }
|
|
73
|
+
|
|
74
|
+
let wm_state = x11::xlib::XInternAtom(
|
|
75
|
+
DISPLAY,
|
|
76
|
+
b"_NET_WM_STATE\0".as_ptr() as *const _,
|
|
77
|
+
0,
|
|
78
|
+
);
|
|
79
|
+
let wm_fullscreen = x11::xlib::XInternAtom(
|
|
80
|
+
DISPLAY,
|
|
81
|
+
b"_NET_WM_STATE_FULLSCREEN\0".as_ptr() as *const _,
|
|
82
|
+
0,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
let action = if fullscreen { 1 } else { 0 }; // _NET_WM_STATE_ADD / _REMOVE
|
|
86
|
+
|
|
87
|
+
let mut event: x11::xlib::XClientMessageEvent = std::mem::zeroed();
|
|
88
|
+
event.type_ = x11::xlib::ClientMessage;
|
|
89
|
+
event.window = X11_WINDOW;
|
|
90
|
+
event.message_type = wm_state;
|
|
91
|
+
event.format = 32;
|
|
92
|
+
event.data.set_long(0, action);
|
|
93
|
+
event.data.set_long(1, wm_fullscreen as i64);
|
|
94
|
+
event.data.set_long(2, 0);
|
|
95
|
+
event.data.set_long(3, 1); // source: normal application
|
|
96
|
+
|
|
97
|
+
let root = x11::xlib::XDefaultRootWindow(DISPLAY);
|
|
98
|
+
x11::xlib::XSendEvent(
|
|
99
|
+
DISPLAY,
|
|
100
|
+
root,
|
|
101
|
+
0,
|
|
102
|
+
x11::xlib::SubstructureRedirectMask | x11::xlib::SubstructureNotifyMask,
|
|
103
|
+
&mut event as *mut x11::xlib::XClientMessageEvent as *mut x11::xlib::XEvent,
|
|
104
|
+
);
|
|
105
|
+
x11::xlib::XFlush(DISPLAY);
|
|
106
|
+
IS_FULLSCREEN = fullscreen;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
pub fn toggle_fullscreen() {
|
|
111
|
+
unsafe { set_fullscreen(!IS_FULLSCREEN); }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// Returns (physical_w, physical_h). Caller's `width`/`height`
|
|
115
|
+
/// are *logical*; on a HiDPI X11 display we multiply by the
|
|
116
|
+
/// monitor's scale factor so the window appears the right size
|
|
117
|
+
/// while its surface is at the screen's physical resolution.
|
|
118
|
+
pub fn create_window(width: f64, height: f64, title: &str) -> (u32, u32) {
|
|
119
|
+
unsafe {
|
|
120
|
+
DISPLAY = x11::xlib::XOpenDisplay(std::ptr::null());
|
|
121
|
+
if DISPLAY.is_null() {
|
|
122
|
+
panic!("Failed to open X11 display");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let screen = x11::xlib::XDefaultScreen(DISPLAY);
|
|
126
|
+
let root = x11::xlib::XRootWindow(DISPLAY, screen);
|
|
127
|
+
|
|
128
|
+
let scale = display_scale(DISPLAY, screen);
|
|
129
|
+
let phys_w = (width * scale).round() as u32;
|
|
130
|
+
let phys_h = (height * scale).round() as u32;
|
|
131
|
+
|
|
132
|
+
X11_WINDOW = x11::xlib::XCreateSimpleWindow(
|
|
133
|
+
DISPLAY, root,
|
|
134
|
+
0, 0, phys_w, phys_h, 0,
|
|
135
|
+
x11::xlib::XBlackPixel(DISPLAY, screen),
|
|
136
|
+
x11::xlib::XWhitePixel(DISPLAY, screen),
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
let title_cstr = std::ffi::CString::new(title).unwrap();
|
|
140
|
+
x11::xlib::XStoreName(DISPLAY, X11_WINDOW, title_cstr.as_ptr());
|
|
141
|
+
|
|
142
|
+
x11::xlib::XSelectInput(DISPLAY, X11_WINDOW,
|
|
143
|
+
x11::xlib::ExposureMask | x11::xlib::KeyPressMask | x11::xlib::KeyReleaseMask |
|
|
144
|
+
x11::xlib::ButtonPressMask | x11::xlib::ButtonReleaseMask |
|
|
145
|
+
x11::xlib::PointerMotionMask | x11::xlib::StructureNotifyMask);
|
|
146
|
+
|
|
147
|
+
x11::xlib::XMapWindow(DISPLAY, X11_WINDOW);
|
|
148
|
+
x11::xlib::XFlush(DISPLAY);
|
|
149
|
+
(phys_w, phys_h)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// Read the current display's DPI scale factor. Computed from
|
|
154
|
+
/// physical screen dimensions (pixels / mm). Snapped to the
|
|
155
|
+
/// nearest 0.25 and clamped to [1.0, 4.0] — EDID often lies
|
|
156
|
+
/// about millimetres so we want stable integer-ish steps. A
|
|
157
|
+
/// real Wayland-style desktop environment with explicit scale
|
|
158
|
+
/// settings is out of scope here; this matches what most X11
|
|
159
|
+
/// users actually run (fractional scaling via Xft.dpi is the
|
|
160
|
+
/// only thing GTK/Qt honour by default).
|
|
161
|
+
pub fn display_scale(display: *mut x11::xlib::Display, screen: i32) -> f64 {
|
|
162
|
+
unsafe {
|
|
163
|
+
let pixels = x11::xlib::XDisplayWidth(display, screen) as f64;
|
|
164
|
+
let mm = x11::xlib::XDisplayWidthMM(display, screen) as f64;
|
|
165
|
+
if mm <= 0.0 || pixels <= 0.0 { return 1.0; }
|
|
166
|
+
let dpi = pixels / (mm / 25.4);
|
|
167
|
+
// 96 DPI = scale 1.0. Snap to 0.25 steps.
|
|
168
|
+
let raw = (dpi / 96.0).max(1.0).min(4.0);
|
|
169
|
+
(raw * 4.0).round() / 4.0
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
pub fn display() -> *mut x11::xlib::Display { unsafe { DISPLAY } }
|
|
174
|
+
pub fn window() -> x11::xlib::Window { unsafe { X11_WINDOW } }
|
|
175
|
+
|
|
176
|
+
pub fn poll_events() {
|
|
177
|
+
unsafe {
|
|
178
|
+
while x11::xlib::XPending(DISPLAY) > 0 {
|
|
179
|
+
let mut event = std::mem::zeroed::<x11::xlib::XEvent>();
|
|
180
|
+
x11::xlib::XNextEvent(DISPLAY, &mut event);
|
|
181
|
+
|
|
182
|
+
match event.type_ {
|
|
183
|
+
x11::xlib::KeyPress => {
|
|
184
|
+
let key_event = event.key;
|
|
185
|
+
let keysym = x11::xlib::XLookupKeysym(
|
|
186
|
+
&mut event.key as *mut _ as *mut _,
|
|
187
|
+
0,
|
|
188
|
+
);
|
|
189
|
+
let bloom_key = map_keycode(keysym as u32);
|
|
190
|
+
if bloom_key > 0 {
|
|
191
|
+
engine().input.set_key_down(bloom_key);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
x11::xlib::KeyRelease => {
|
|
195
|
+
let keysym = x11::xlib::XLookupKeysym(
|
|
196
|
+
&mut event.key as *mut _ as *mut _,
|
|
197
|
+
0,
|
|
198
|
+
);
|
|
199
|
+
let bloom_key = map_keycode(keysym as u32);
|
|
200
|
+
if bloom_key > 0 {
|
|
201
|
+
engine().input.set_key_up(bloom_key);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
x11::xlib::MotionNotify => {
|
|
205
|
+
let motion = event.motion;
|
|
206
|
+
engine().input.set_mouse_position(motion.x as f64, motion.y as f64);
|
|
207
|
+
}
|
|
208
|
+
x11::xlib::ButtonPress => {
|
|
209
|
+
let button = event.button.button;
|
|
210
|
+
match button {
|
|
211
|
+
1 => engine().input.set_mouse_button_down(0),
|
|
212
|
+
3 => engine().input.set_mouse_button_down(1),
|
|
213
|
+
2 => engine().input.set_mouse_button_down(2),
|
|
214
|
+
_ => {}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
x11::xlib::ButtonRelease => {
|
|
218
|
+
let button = event.button.button;
|
|
219
|
+
match button {
|
|
220
|
+
1 => engine().input.set_mouse_button_up(0),
|
|
221
|
+
3 => engine().input.set_mouse_button_up(1),
|
|
222
|
+
2 => engine().input.set_mouse_button_up(2),
|
|
223
|
+
_ => {}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
x11::xlib::ConfigureNotify => {
|
|
227
|
+
let configure = event.configure;
|
|
228
|
+
let phys_w = configure.width as u32;
|
|
229
|
+
let phys_h = configure.height as u32;
|
|
230
|
+
if phys_w > 0 && phys_h > 0 {
|
|
231
|
+
let eng = engine();
|
|
232
|
+
if phys_w != eng.renderer.physical_width()
|
|
233
|
+
|| phys_h != eng.renderer.physical_height()
|
|
234
|
+
{
|
|
235
|
+
let screen = x11::xlib::XDefaultScreen(DISPLAY);
|
|
236
|
+
let scale = display_scale(DISPLAY, screen);
|
|
237
|
+
let log_w = ((phys_w as f64) / scale).round() as u32;
|
|
238
|
+
let log_h = ((phys_h as f64) / scale).round() as u32;
|
|
239
|
+
eng.renderer.resize(phys_w, phys_h, log_w, log_h);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
x11::xlib::DestroyNotify => {
|
|
244
|
+
engine().should_close = true;
|
|
245
|
+
}
|
|
246
|
+
_ => {}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
#[no_mangle]
|
|
254
|
+
pub extern "C" fn bloom_init_window(width: f64, height: f64, title_ptr: *const u8, fullscreen: f64) {
|
|
255
|
+
let title = str_from_header(title_ptr);
|
|
256
|
+
|
|
257
|
+
#[cfg(target_os = "linux")]
|
|
258
|
+
{
|
|
259
|
+
let (phys_w, phys_h) = x11_impl::create_window(width, height, title);
|
|
260
|
+
|
|
261
|
+
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
|
262
|
+
backends: wgpu::Backends::VULKAN | wgpu::Backends::GL,
|
|
263
|
+
..wgpu::InstanceDescriptor::new_without_display_handle()
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
let surface = unsafe {
|
|
267
|
+
let raw_window = raw_window_handle::RawWindowHandle::Xlib(
|
|
268
|
+
raw_window_handle::XlibWindowHandle::new(x11_impl::window())
|
|
269
|
+
);
|
|
270
|
+
let raw_display = raw_window_handle::RawDisplayHandle::Xlib(
|
|
271
|
+
raw_window_handle::XlibDisplayHandle::new(
|
|
272
|
+
std::ptr::NonNull::new(x11_impl::display() as *mut _),
|
|
273
|
+
0,
|
|
274
|
+
)
|
|
275
|
+
);
|
|
276
|
+
instance.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::RawHandle {
|
|
277
|
+
raw_display_handle: Some(raw_display),
|
|
278
|
+
raw_window_handle: raw_window,
|
|
279
|
+
}).expect("Failed to create surface")
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
let adapter = pollster_block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
|
|
283
|
+
compatible_surface: Some(&surface),
|
|
284
|
+
..Default::default()
|
|
285
|
+
})).expect("No adapter found");
|
|
286
|
+
|
|
287
|
+
// Ticket 007b: HW ray-query via VK_KHR_ray_query on RT-capable
|
|
288
|
+
// desktop Linux GPUs. Older integrated GPUs will fall back to
|
|
289
|
+
// the SW path through this gate.
|
|
290
|
+
let supported = adapter.features();
|
|
291
|
+
let force_sw_gi = std::env::var("BLOOM_FORCE_SW_GI")
|
|
292
|
+
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
|
|
293
|
+
.unwrap_or(false);
|
|
294
|
+
let rt_mask = wgpu::Features::EXPERIMENTAL_RAY_QUERY;
|
|
295
|
+
let mut required_features = wgpu::Features::empty();
|
|
296
|
+
// Ticket 011: request TIMESTAMP_QUERY when supported so the profiler
|
|
297
|
+
// can record GPU timings. Optional — profiler falls back to CPU-only
|
|
298
|
+
// when the adapter doesn't grant it.
|
|
299
|
+
if supported.contains(wgpu::Features::TIMESTAMP_QUERY) {
|
|
300
|
+
required_features |= wgpu::Features::TIMESTAMP_QUERY;
|
|
301
|
+
}
|
|
302
|
+
if !force_sw_gi && supported.contains(rt_mask) {
|
|
303
|
+
required_features |= rt_mask;
|
|
304
|
+
}
|
|
305
|
+
let experimental_features = if required_features.intersects(rt_mask) {
|
|
306
|
+
unsafe { wgpu::ExperimentalFeatures::enabled() }
|
|
307
|
+
} else {
|
|
308
|
+
wgpu::ExperimentalFeatures::disabled()
|
|
309
|
+
};
|
|
310
|
+
let mut required_limits = wgpu::Limits::default();
|
|
311
|
+
if required_features.intersects(rt_mask) {
|
|
312
|
+
required_limits = required_limits
|
|
313
|
+
.using_minimum_supported_acceleration_structure_values();
|
|
314
|
+
}
|
|
315
|
+
let (device, queue) = pollster_block_on(adapter.request_device(
|
|
316
|
+
&wgpu::DeviceDescriptor {
|
|
317
|
+
label: Some("bloom_device"),
|
|
318
|
+
required_features,
|
|
319
|
+
required_limits,
|
|
320
|
+
experimental_features,
|
|
321
|
+
..Default::default()
|
|
322
|
+
},
|
|
323
|
+
)).expect("Failed to create device");
|
|
324
|
+
|
|
325
|
+
let surface_caps = surface.get_capabilities(&adapter);
|
|
326
|
+
let format = surface_caps.formats[0];
|
|
327
|
+
// Surface sized at the *physical* pixel count we computed
|
|
328
|
+
// from XDisplayWidth/MM; renderer is told the caller's
|
|
329
|
+
// logical size separately so screenWidth() etc. stay
|
|
330
|
+
// DPI-independent.
|
|
331
|
+
let surface_config = wgpu::SurfaceConfiguration {
|
|
332
|
+
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
|
333
|
+
format,
|
|
334
|
+
width: phys_w,
|
|
335
|
+
height: phys_h,
|
|
336
|
+
present_mode: wgpu::PresentMode::Fifo,
|
|
337
|
+
alpha_mode: surface_caps.alpha_modes[0],
|
|
338
|
+
view_formats: vec![],
|
|
339
|
+
desired_maximum_frame_latency: 2,
|
|
340
|
+
};
|
|
341
|
+
surface.configure(&device, &surface_config);
|
|
342
|
+
|
|
343
|
+
let renderer = Renderer::new(device, queue, surface, surface_config, width as u32, height as u32);
|
|
344
|
+
unsafe { let _ = ENGINE.set(EngineState::new(renderer)); }
|
|
345
|
+
|
|
346
|
+
if fullscreen != 0.0 {
|
|
347
|
+
x11_impl::set_fullscreen(true);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
#[cfg(not(target_os = "linux"))]
|
|
352
|
+
panic!("bloom-linux can only run on Linux");
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
#[no_mangle]
|
|
356
|
+
pub extern "C" fn bloom_close_window() {}
|
|
357
|
+
|
|
358
|
+
#[no_mangle]
|
|
359
|
+
pub extern "C" fn bloom_window_should_close() -> f64 {
|
|
360
|
+
if engine().should_close { 1.0 } else { 0.0 }
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
#[cfg(target_os = "linux")]
|
|
364
|
+
fn poll_linux_gamepad() {
|
|
365
|
+
unsafe {
|
|
366
|
+
// Try to open gamepad if not already
|
|
367
|
+
if GAMEPAD_FD < 0 {
|
|
368
|
+
let path = b"/dev/input/js0\0";
|
|
369
|
+
// Open non-blocking
|
|
370
|
+
GAMEPAD_FD = libc::open(path.as_ptr() as *const libc::c_char, libc::O_RDONLY | libc::O_NONBLOCK);
|
|
371
|
+
if GAMEPAD_FD >= 0 {
|
|
372
|
+
engine().input.gamepad_available = true;
|
|
373
|
+
engine().input.gamepad_axis_count = 6;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if GAMEPAD_FD < 0 { return; }
|
|
377
|
+
|
|
378
|
+
// Linux joystick event structure
|
|
379
|
+
#[repr(C)]
|
|
380
|
+
struct JsEvent {
|
|
381
|
+
time: u32,
|
|
382
|
+
value: i16,
|
|
383
|
+
event_type: u8,
|
|
384
|
+
number: u8,
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
loop {
|
|
388
|
+
let mut event = std::mem::zeroed::<JsEvent>();
|
|
389
|
+
let n = libc::read(
|
|
390
|
+
GAMEPAD_FD,
|
|
391
|
+
&mut event as *mut _ as *mut libc::c_void,
|
|
392
|
+
std::mem::size_of::<JsEvent>(),
|
|
393
|
+
);
|
|
394
|
+
if n != std::mem::size_of::<JsEvent>() as isize { break; }
|
|
395
|
+
|
|
396
|
+
let type_masked = event.event_type & 0x7f; // strip JS_EVENT_INIT
|
|
397
|
+
if type_masked == 1 {
|
|
398
|
+
// Button
|
|
399
|
+
let idx = event.number as usize;
|
|
400
|
+
if event.value != 0 {
|
|
401
|
+
engine().input.set_gamepad_button_down(idx);
|
|
402
|
+
} else {
|
|
403
|
+
engine().input.set_gamepad_button_up(idx);
|
|
404
|
+
}
|
|
405
|
+
} else if type_masked == 2 {
|
|
406
|
+
// Axis
|
|
407
|
+
let idx = event.number as usize;
|
|
408
|
+
let value = event.value as f32 / 32767.0;
|
|
409
|
+
engine().input.set_gamepad_axis(idx, value);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
#[no_mangle]
|
|
416
|
+
pub extern "C" fn bloom_begin_drawing() {
|
|
417
|
+
#[cfg(target_os = "linux")]
|
|
418
|
+
{
|
|
419
|
+
x11_impl::poll_events();
|
|
420
|
+
poll_linux_gamepad();
|
|
421
|
+
}
|
|
422
|
+
engine().begin_frame();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
#[no_mangle]
|
|
426
|
+
pub extern "C" fn bloom_end_drawing() { engine().end_frame(); }
|
|
427
|
+
|
|
428
|
+
#[no_mangle]
|
|
429
|
+
pub extern "C" fn bloom_clear_background(r: f64, g: f64, b: f64, a: f64) {
|
|
430
|
+
engine().renderer.set_clear_color(r, g, b, a);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
#[no_mangle]
|
|
434
|
+
pub extern "C" fn bloom_set_target_fps(fps: f64) { engine().target_fps = fps; }
|
|
435
|
+
|
|
436
|
+
#[no_mangle]
|
|
437
|
+
pub extern "C" fn bloom_set_direct_2d_mode(on: f64) { engine().direct_2d_mode = on > 0.5; }
|
|
438
|
+
|
|
439
|
+
#[no_mangle]
|
|
440
|
+
pub extern "C" fn bloom_get_delta_time() -> f64 { engine().delta_time }
|
|
441
|
+
|
|
442
|
+
#[no_mangle]
|
|
443
|
+
pub extern "C" fn bloom_get_fps() -> f64 { engine().get_fps() }
|
|
444
|
+
|
|
445
|
+
#[no_mangle]
|
|
446
|
+
pub extern "C" fn bloom_get_screen_width() -> f64 { engine().screen_width() }
|
|
447
|
+
|
|
448
|
+
#[no_mangle]
|
|
449
|
+
pub extern "C" fn bloom_get_screen_height() -> f64 { engine().screen_height() }
|
|
450
|
+
|
|
451
|
+
#[no_mangle]
|
|
452
|
+
pub extern "C" fn bloom_is_key_pressed(key: f64) -> f64 {
|
|
453
|
+
if engine().input.is_key_pressed(key as usize) { 1.0 } else { 0.0 }
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
#[no_mangle]
|
|
457
|
+
pub extern "C" fn bloom_is_key_down(key: f64) -> f64 {
|
|
458
|
+
if engine().input.is_key_down(key as usize) { 1.0 } else { 0.0 }
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
#[no_mangle]
|
|
462
|
+
pub extern "C" fn bloom_is_key_released(key: f64) -> f64 {
|
|
463
|
+
if engine().input.is_key_released(key as usize) { 1.0 } else { 0.0 }
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
#[no_mangle]
|
|
467
|
+
pub extern "C" fn bloom_get_mouse_x() -> f64 { engine().input.mouse_x }
|
|
468
|
+
|
|
469
|
+
#[no_mangle]
|
|
470
|
+
pub extern "C" fn bloom_get_mouse_y() -> f64 { engine().input.mouse_y }
|
|
471
|
+
|
|
472
|
+
#[no_mangle]
|
|
473
|
+
pub extern "C" fn bloom_is_mouse_button_pressed(btn: f64) -> f64 {
|
|
474
|
+
if engine().input.is_mouse_button_pressed(btn as usize) { 1.0 } else { 0.0 }
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
#[no_mangle]
|
|
478
|
+
pub extern "C" fn bloom_is_mouse_button_down(btn: f64) -> f64 {
|
|
479
|
+
if engine().input.is_mouse_button_down(btn as usize) { 1.0 } else { 0.0 }
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
#[no_mangle]
|
|
483
|
+
pub extern "C" fn bloom_is_mouse_button_released(btn: f64) -> f64 {
|
|
484
|
+
if engine().input.is_mouse_button_released(btn as usize) { 1.0 } else { 0.0 }
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
#[no_mangle]
|
|
488
|
+
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) {
|
|
489
|
+
engine().renderer.draw_line(x1, y1, x2, y2, thickness, r, g, b, a);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
#[no_mangle]
|
|
493
|
+
pub extern "C" fn bloom_draw_rect(x: f64, y: f64, w: f64, h: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
494
|
+
engine().renderer.draw_rect(x, y, w, h, r, g, b, a);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
#[no_mangle]
|
|
498
|
+
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) {
|
|
499
|
+
engine().renderer.draw_rect_lines(x, y, w, h, thickness, r, g, b, a);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
#[no_mangle]
|
|
503
|
+
pub extern "C" fn bloom_draw_circle(cx: f64, cy: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
504
|
+
engine().renderer.draw_circle(cx, cy, radius, r, g, b, a);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
#[no_mangle]
|
|
508
|
+
pub extern "C" fn bloom_draw_circle_lines(cx: f64, cy: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
509
|
+
engine().renderer.draw_circle_lines(cx, cy, radius, r, g, b, a);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
#[no_mangle]
|
|
513
|
+
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) {
|
|
514
|
+
engine().renderer.draw_triangle(x1, y1, x2, y2, x3, y3, r, g, b, a);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
#[no_mangle]
|
|
518
|
+
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) {
|
|
519
|
+
engine().renderer.draw_poly(cx, cy, sides, radius, rotation, r, g, b, a);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
#[no_mangle]
|
|
523
|
+
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) {
|
|
524
|
+
let text = str_from_header(text_ptr);
|
|
525
|
+
let eng = engine();
|
|
526
|
+
let mut text_renderer = std::mem::replace(&mut eng.text, bloom_shared::text_renderer::TextRenderer::empty());
|
|
527
|
+
text_renderer.draw_text(&mut eng.renderer, text, x, y, size as u32, r, g, b, a);
|
|
528
|
+
eng.text = text_renderer;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
#[no_mangle]
|
|
532
|
+
pub extern "C" fn bloom_measure_text(text_ptr: *const u8, size: f64) -> f64 {
|
|
533
|
+
let text = str_from_header(text_ptr);
|
|
534
|
+
engine().text.measure_text(text, size as u32)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
#[no_mangle]
|
|
538
|
+
pub extern "C" fn bloom_load_font(path_ptr: *const u8, size: f64) -> f64 {
|
|
539
|
+
let path = str_from_header(path_ptr);
|
|
540
|
+
match std::fs::read(path) { Ok(data) => engine().text.load_font(&data) as f64, Err(_) => 0.0 }
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
#[no_mangle]
|
|
544
|
+
pub extern "C" fn bloom_unload_font(font_handle: f64) {
|
|
545
|
+
engine().text.unload_font(font_handle as usize);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
#[no_mangle]
|
|
549
|
+
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) {
|
|
550
|
+
let text = str_from_header(text_ptr);
|
|
551
|
+
let eng = engine();
|
|
552
|
+
let mut text_renderer = std::mem::replace(&mut eng.text, bloom_shared::text_renderer::TextRenderer::empty());
|
|
553
|
+
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);
|
|
554
|
+
eng.text = text_renderer;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
#[no_mangle]
|
|
558
|
+
pub extern "C" fn bloom_measure_text_ex(font_handle: f64, text_ptr: *const u8, size: f64, spacing: f64) -> f64 {
|
|
559
|
+
let text = str_from_header(text_ptr);
|
|
560
|
+
engine().text.measure_text_ex(font_handle as usize, text, size as u32, spacing as f32)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
static AUDIO_RUNNING: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
|
564
|
+
|
|
565
|
+
#[no_mangle]
|
|
566
|
+
pub extern "C" fn bloom_init_audio() {
|
|
567
|
+
#[cfg(target_os = "linux")]
|
|
568
|
+
{
|
|
569
|
+
use std::sync::atomic::Ordering;
|
|
570
|
+
AUDIO_RUNNING.store(true, Ordering::SeqCst);
|
|
571
|
+
std::thread::spawn(|| {
|
|
572
|
+
alsa_audio_thread();
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
#[no_mangle]
|
|
578
|
+
pub extern "C" fn bloom_close_audio() {
|
|
579
|
+
AUDIO_RUNNING.store(false, std::sync::atomic::Ordering::SeqCst);
|
|
580
|
+
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
#[cfg(target_os = "linux")]
|
|
584
|
+
fn alsa_audio_thread() {
|
|
585
|
+
use alsa::pcm::*;
|
|
586
|
+
use alsa::{Direction, ValueOr};
|
|
587
|
+
use std::sync::atomic::Ordering;
|
|
588
|
+
|
|
589
|
+
let pcm = match PCM::new("default", Direction::Playback, false) {
|
|
590
|
+
Ok(p) => p,
|
|
591
|
+
Err(_) => return,
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
let sample_rate = 44100u32;
|
|
595
|
+
let channels = 2u32;
|
|
596
|
+
let period_size = 1024;
|
|
597
|
+
|
|
598
|
+
{
|
|
599
|
+
let hwp = HwParams::any(&pcm).unwrap();
|
|
600
|
+
let _ = hwp.set_channels(channels);
|
|
601
|
+
let _ = hwp.set_rate(sample_rate, ValueOr::Nearest);
|
|
602
|
+
let _ = hwp.set_format(Format::float());
|
|
603
|
+
let _ = hwp.set_access(Access::RWInterleaved);
|
|
604
|
+
let _ = hwp.set_period_size(period_size, ValueOr::Nearest);
|
|
605
|
+
let _ = hwp.set_buffer_size(period_size * 4);
|
|
606
|
+
let _ = pcm.hw_params(&hwp);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
let _ = pcm.prepare();
|
|
610
|
+
|
|
611
|
+
let frames = period_size as usize;
|
|
612
|
+
let mut mix_buf = vec![0.0f32; frames * channels as usize];
|
|
613
|
+
|
|
614
|
+
while AUDIO_RUNNING.load(Ordering::SeqCst) {
|
|
615
|
+
for s in mix_buf.iter_mut() { *s = 0.0; }
|
|
616
|
+
|
|
617
|
+
unsafe {
|
|
618
|
+
ENGINE.get_mut().map(|eng| {
|
|
619
|
+
eng.audio.mix_output(&mut mix_buf);
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
let io = pcm.io_f32().unwrap();
|
|
624
|
+
match io.writei(&mix_buf) {
|
|
625
|
+
Ok(_) => {}
|
|
626
|
+
Err(e) => {
|
|
627
|
+
let _ = pcm.try_recover(e, true);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
let _ = pcm.drain();
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
#[no_mangle]
|
|
636
|
+
pub extern "C" fn bloom_load_sound(path_ptr: *const u8) -> f64 {
|
|
637
|
+
let path = str_from_header(path_ptr);
|
|
638
|
+
match std::fs::read(path) {
|
|
639
|
+
Ok(data) => {
|
|
640
|
+
if let Some(s) = parse_wav(&data) { engine().audio.load_sound(s) }
|
|
641
|
+
else if let Some(s) = parse_ogg(&data) { engine().audio.load_sound(s) }
|
|
642
|
+
else if let Some(s) = parse_mp3(&data) { engine().audio.load_sound(s) }
|
|
643
|
+
else { 0.0 }
|
|
644
|
+
}
|
|
645
|
+
Err(_) => 0.0,
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
#[no_mangle]
|
|
650
|
+
pub extern "C" fn bloom_play_sound(handle: f64) { engine().audio.play_sound(handle); }
|
|
651
|
+
#[no_mangle]
|
|
652
|
+
pub extern "C" fn bloom_stop_sound(handle: f64) { engine().audio.stop_sound(handle); }
|
|
653
|
+
#[no_mangle]
|
|
654
|
+
pub extern "C" fn bloom_set_sound_volume(handle: f64, volume: f64) { engine().audio.set_sound_volume(handle, volume as f32); }
|
|
655
|
+
#[no_mangle]
|
|
656
|
+
pub extern "C" fn bloom_set_master_volume(volume: f64) { engine().audio.master_volume = volume as f32; }
|
|
657
|
+
|
|
658
|
+
#[no_mangle]
|
|
659
|
+
pub extern "C" fn bloom_play_sound_3d(handle: f64, x: f64, y: f64, z: f64) {
|
|
660
|
+
engine().audio.play_sound_3d(handle, x as f32, y as f32, z as f32);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
#[no_mangle]
|
|
664
|
+
pub extern "C" fn bloom_set_listener_position(x: f64, y: f64, z: f64, fx: f64, fy: f64, fz: f64) {
|
|
665
|
+
engine().audio.set_listener_position(x as f32, y as f32, z as f32, fx as f32, fy as f32, fz as f32);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// --- Texture FFI ---
|
|
669
|
+
|
|
670
|
+
#[no_mangle]
|
|
671
|
+
pub extern "C" fn bloom_load_texture(path_ptr: *const u8) -> f64 {
|
|
672
|
+
let path = str_from_header(path_ptr);
|
|
673
|
+
match std::fs::read(path) {
|
|
674
|
+
Ok(data) => {
|
|
675
|
+
let eng = engine();
|
|
676
|
+
let renderer_ptr = &mut eng.renderer as *mut bloom_shared::renderer::Renderer;
|
|
677
|
+
eng.textures.load_texture(unsafe { &mut *renderer_ptr }, &data)
|
|
678
|
+
}
|
|
679
|
+
Err(_) => 0.0,
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
#[no_mangle]
|
|
684
|
+
pub extern "C" fn bloom_unload_texture(handle: f64) {
|
|
685
|
+
let eng = engine();
|
|
686
|
+
let renderer_ptr = &mut eng.renderer as *mut bloom_shared::renderer::Renderer;
|
|
687
|
+
eng.textures.unload_texture(handle, unsafe { &mut *renderer_ptr });
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
#[no_mangle]
|
|
691
|
+
pub extern "C" fn bloom_draw_texture(handle: f64, x: f64, y: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
692
|
+
let eng = engine();
|
|
693
|
+
if let Some(tex) = eng.textures.get(handle) {
|
|
694
|
+
let idx = tex.bind_group_idx;
|
|
695
|
+
eng.renderer.draw_texture(idx, x, y, r, g, b, a);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
#[no_mangle]
|
|
700
|
+
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) {
|
|
701
|
+
let eng = engine();
|
|
702
|
+
if let Some(tex) = eng.textures.get(handle) {
|
|
703
|
+
let idx = tex.bind_group_idx;
|
|
704
|
+
eng.renderer.draw_texture_rec(idx, src_x, src_y, src_w, src_h, dst_x, dst_y, r, g, b, a);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
#[no_mangle]
|
|
709
|
+
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) {
|
|
710
|
+
let eng = engine();
|
|
711
|
+
if let Some(tex) = eng.textures.get(handle) {
|
|
712
|
+
let idx = tex.bind_group_idx;
|
|
713
|
+
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);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
#[no_mangle]
|
|
718
|
+
pub extern "C" fn bloom_get_texture_width(handle: f64) -> f64 {
|
|
719
|
+
engine().textures.get(handle).map(|t| t.width as f64).unwrap_or(0.0)
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
#[no_mangle]
|
|
723
|
+
pub extern "C" fn bloom_get_texture_height(handle: f64) -> f64 {
|
|
724
|
+
engine().textures.get(handle).map(|t| t.height as f64).unwrap_or(0.0)
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
#[no_mangle]
|
|
728
|
+
pub extern "C" fn bloom_gen_texture_mipmaps(_handle: f64) {
|
|
729
|
+
// No-op: wgpu handles mipmaps internally
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
#[no_mangle]
|
|
733
|
+
pub extern "C" fn bloom_set_texture_filter(handle: f64, mode: f64) {
|
|
734
|
+
let eng = engine();
|
|
735
|
+
if let Some(tex) = eng.textures.get(handle) {
|
|
736
|
+
let bind_group_idx = tex.bind_group_idx;
|
|
737
|
+
eng.renderer.set_texture_filter(bind_group_idx, mode > 0.5);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
#[no_mangle]
|
|
742
|
+
pub extern "C" fn bloom_load_image(path_ptr: *const u8) -> f64 {
|
|
743
|
+
let path = str_from_header(path_ptr);
|
|
744
|
+
match std::fs::read(path) { Ok(data) => engine().textures.load_image(&data), Err(_) => 0.0 }
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
#[no_mangle]
|
|
748
|
+
pub extern "C" fn bloom_image_resize(handle: f64, w: f64, h: f64) {
|
|
749
|
+
engine().textures.image_resize(handle, w as u32, h as u32);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
#[no_mangle]
|
|
753
|
+
pub extern "C" fn bloom_image_crop(handle: f64, x: f64, y: f64, w: f64, h: f64) {
|
|
754
|
+
engine().textures.image_crop(handle, x as u32, y as u32, w as u32, h as u32);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
#[no_mangle]
|
|
758
|
+
pub extern "C" fn bloom_image_flip_h(handle: f64) {
|
|
759
|
+
engine().textures.image_flip_h(handle);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
#[no_mangle]
|
|
763
|
+
pub extern "C" fn bloom_image_flip_v(handle: f64) {
|
|
764
|
+
engine().textures.image_flip_v(handle);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
#[no_mangle]
|
|
768
|
+
pub extern "C" fn bloom_load_texture_from_image(handle: f64) -> f64 {
|
|
769
|
+
let eng = engine();
|
|
770
|
+
let renderer_ptr = &mut eng.renderer as *mut bloom_shared::renderer::Renderer;
|
|
771
|
+
eng.textures.load_texture_from_image(handle, unsafe { &mut *renderer_ptr })
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// --- Camera FFI ---
|
|
775
|
+
|
|
776
|
+
#[no_mangle]
|
|
777
|
+
pub extern "C" fn bloom_begin_mode_2d(offset_x: f64, offset_y: f64, target_x: f64, target_y: f64, rotation: f64, zoom: f64) {
|
|
778
|
+
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);
|
|
779
|
+
}
|
|
780
|
+
#[no_mangle]
|
|
781
|
+
pub extern "C" fn bloom_end_mode_2d() { engine().renderer.end_mode_2d(); }
|
|
782
|
+
|
|
783
|
+
#[no_mangle]
|
|
784
|
+
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) {
|
|
785
|
+
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);
|
|
786
|
+
}
|
|
787
|
+
#[no_mangle]
|
|
788
|
+
pub extern "C" fn bloom_end_mode_3d() { engine().renderer.end_mode_3d(); }
|
|
789
|
+
|
|
790
|
+
// --- 3D Drawing FFI ---
|
|
791
|
+
|
|
792
|
+
#[no_mangle]
|
|
793
|
+
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) {
|
|
794
|
+
engine().renderer.draw_cube(x, y, z, w, h, d, r, g, b, a);
|
|
795
|
+
}
|
|
796
|
+
#[no_mangle]
|
|
797
|
+
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) {
|
|
798
|
+
engine().renderer.draw_cube_wires(x, y, z, w, h, d, r, g, b, a);
|
|
799
|
+
}
|
|
800
|
+
#[no_mangle]
|
|
801
|
+
pub extern "C" fn bloom_draw_sphere(x: f64, y: f64, z: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
802
|
+
engine().renderer.draw_sphere(x, y, z, radius, r, g, b, a);
|
|
803
|
+
}
|
|
804
|
+
#[no_mangle]
|
|
805
|
+
pub extern "C" fn bloom_draw_sphere_wires(x: f64, y: f64, z: f64, radius: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
806
|
+
engine().renderer.draw_sphere_wires(x, y, z, radius, r, g, b, a);
|
|
807
|
+
}
|
|
808
|
+
#[no_mangle]
|
|
809
|
+
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) {
|
|
810
|
+
engine().renderer.draw_cylinder(x, y, z, rt, rb, h, r, g, b, a);
|
|
811
|
+
}
|
|
812
|
+
#[no_mangle]
|
|
813
|
+
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) {
|
|
814
|
+
engine().renderer.draw_plane(x, y, z, w, d, r, g, b, a);
|
|
815
|
+
}
|
|
816
|
+
#[no_mangle]
|
|
817
|
+
pub extern "C" fn bloom_draw_grid(slices: f64, spacing: f64) {
|
|
818
|
+
engine().renderer.draw_grid(slices as i32, spacing);
|
|
819
|
+
}
|
|
820
|
+
#[no_mangle]
|
|
821
|
+
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) {
|
|
822
|
+
engine().renderer.draw_ray(ox, oy, oz, dx, dy, dz, r, g, b, a);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// --- Model FFI ---
|
|
826
|
+
|
|
827
|
+
#[no_mangle]
|
|
828
|
+
pub extern "C" fn bloom_load_model(path_ptr: *const u8) -> f64 {
|
|
829
|
+
let path = str_from_header(path_ptr);
|
|
830
|
+
match std::fs::read(path) { Ok(data) => engine().models.load_model(&data), Err(_) => 0.0 }
|
|
831
|
+
}
|
|
832
|
+
#[no_mangle]
|
|
833
|
+
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) {
|
|
834
|
+
let eng = engine();
|
|
835
|
+
if let Some(model) = eng.models.get(handle) {
|
|
836
|
+
let tint = [(r / 255.0) as f32, (g / 255.0) as f32, (b / 255.0) as f32, (a / 255.0) as f32];
|
|
837
|
+
let position = [x as f32, y as f32, z as f32];
|
|
838
|
+
let handle_bits = handle.to_bits();
|
|
839
|
+
if eng.renderer.cache_model_if_static(handle_bits, &model.meshes) {
|
|
840
|
+
eng.renderer.draw_model_cached(handle_bits, position, scale as f32, tint);
|
|
841
|
+
} else {
|
|
842
|
+
for mesh in &model.meshes {
|
|
843
|
+
let tex_idx = mesh.texture_idx.unwrap_or(0);
|
|
844
|
+
eng.renderer.draw_model_mesh_tinted(&mesh.vertices, &mesh.indices, position, scale as f32, tint, tex_idx);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
#[no_mangle]
|
|
850
|
+
pub extern "C" fn bloom_draw_model_rotated(
|
|
851
|
+
handle: f64, x: f64, y: f64, z: f64,
|
|
852
|
+
scale: f64, rot_y: f64,
|
|
853
|
+
color_packed_argb: f64,
|
|
854
|
+
) {
|
|
855
|
+
let bits = color_packed_argb as u32;
|
|
856
|
+
let a = ((bits >> 24) & 0xff) as f32 / 255.0;
|
|
857
|
+
let r = ((bits >> 16) & 0xff) as f32 / 255.0;
|
|
858
|
+
let g = ((bits >> 8) & 0xff) as f32 / 255.0;
|
|
859
|
+
let b = ( bits & 0xff) as f32 / 255.0;
|
|
860
|
+
let eng = engine();
|
|
861
|
+
if let Some(model) = eng.models.get(handle) {
|
|
862
|
+
let position = [x as f32, y as f32, z as f32];
|
|
863
|
+
let scale = scale as f32;
|
|
864
|
+
let tint = [r, g, b, a];
|
|
865
|
+
for mesh in &model.meshes {
|
|
866
|
+
let tex_idx = mesh.texture_idx.unwrap_or(0);
|
|
867
|
+
eng.renderer.draw_model_mesh_tinted_rotated(
|
|
868
|
+
&mesh.vertices, &mesh.indices, position, scale, tint, tex_idx, rot_y as f32,
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
#[no_mangle]
|
|
874
|
+
pub extern "C" fn bloom_unload_model(handle: f64) { engine().models.unload_model(handle); }
|
|
875
|
+
|
|
876
|
+
#[no_mangle]
|
|
877
|
+
pub extern "C" fn bloom_get_model_mesh_count(handle: f64) -> f64 {
|
|
878
|
+
match engine().models.get(handle) {
|
|
879
|
+
Some(model) => model.meshes.len() as f64,
|
|
880
|
+
None => 0.0,
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
#[no_mangle]
|
|
885
|
+
pub extern "C" fn bloom_get_model_material_count(handle: f64) -> f64 {
|
|
886
|
+
match engine().models.get(handle) {
|
|
887
|
+
Some(model) => model.meshes.len() as f64,
|
|
888
|
+
None => 0.0,
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
#[no_mangle]
|
|
893
|
+
pub extern "C" fn bloom_gen_mesh_cube(w: f64, h: f64, d: f64) -> f64 {
|
|
894
|
+
engine().models.gen_mesh_cube(w as f32, h as f32, d as f32)
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
#[no_mangle]
|
|
898
|
+
pub extern "C" fn bloom_gen_mesh_heightmap(image_handle: f64, size_x: f64, size_y: f64, size_z: f64) -> f64 {
|
|
899
|
+
let eng = engine();
|
|
900
|
+
if let Some(img) = eng.textures.images.get(image_handle) {
|
|
901
|
+
let data = img.data.clone();
|
|
902
|
+
let w = img.width;
|
|
903
|
+
let h = img.height;
|
|
904
|
+
eng.models.gen_mesh_heightmap(&data, w, h, size_x as f32, size_y as f32, size_z as f32)
|
|
905
|
+
} else {
|
|
906
|
+
0.0
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
#[no_mangle]
|
|
911
|
+
pub extern "C" fn bloom_load_shader(source_ptr: *const u8) -> f64 {
|
|
912
|
+
let source = str_from_header(source_ptr);
|
|
913
|
+
engine().renderer.load_custom_shader(source) as f64
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
#[no_mangle]
|
|
917
|
+
pub extern "C" fn bloom_create_mesh(vertex_ptr: *const f32, vertex_count: f64, index_ptr: *const u32, index_count: f64) -> f64 {
|
|
918
|
+
if vertex_ptr.is_null() || index_ptr.is_null() { return 0.0; }
|
|
919
|
+
let vcount = vertex_count as usize;
|
|
920
|
+
let icount = index_count as usize;
|
|
921
|
+
let vertex_data = unsafe { std::slice::from_raw_parts(vertex_ptr, vcount * 12) }; // 12 floats per vertex
|
|
922
|
+
let index_data = unsafe { std::slice::from_raw_parts(index_ptr, icount) };
|
|
923
|
+
engine().models.create_mesh(vertex_data, index_data)
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// ============================================================
|
|
927
|
+
// Phase 1c — material system FFI
|
|
928
|
+
// ============================================================
|
|
929
|
+
|
|
930
|
+
#[no_mangle]
|
|
931
|
+
pub extern "C" fn bloom_set_material_params(
|
|
932
|
+
handle: f64,
|
|
933
|
+
params_ptr: *const f64,
|
|
934
|
+
param_count: f64,
|
|
935
|
+
) {
|
|
936
|
+
let count = param_count as usize;
|
|
937
|
+
if count > 64 {
|
|
938
|
+
eprintln!("[material] set_material_params: param_count {} > 64 (256-byte UBO cap)", count);
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
let mut bytes = vec![0u8; count * 4];
|
|
942
|
+
if !params_ptr.is_null() && count > 0 {
|
|
943
|
+
let slots = unsafe { std::slice::from_raw_parts(params_ptr, count) };
|
|
944
|
+
for (i, &v) in slots.iter().enumerate() {
|
|
945
|
+
let f = v as f32;
|
|
946
|
+
bytes[i*4..i*4+4].copy_from_slice(&f.to_le_bytes());
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
let eng = engine();
|
|
950
|
+
if let Err(e) = eng.renderer.material_system.set_user_params(
|
|
951
|
+
&eng.renderer.device, &eng.renderer.queue,
|
|
952
|
+
handle as u32, &bytes,
|
|
953
|
+
) {
|
|
954
|
+
eprintln!("[material] set_material_params failed: {}", e);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
#[no_mangle]
|
|
959
|
+
pub extern "C" fn bloom_compile_material(source_ptr: *const u8) -> f64 {
|
|
960
|
+
let source = str_from_header(source_ptr);
|
|
961
|
+
match engine().renderer.compile_material(source) {
|
|
962
|
+
Ok(handle) => handle as f64,
|
|
963
|
+
Err(e) => {
|
|
964
|
+
eprintln!("[material] compile failed: {:?}", e);
|
|
965
|
+
0.0
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
#[no_mangle]
|
|
971
|
+
pub extern "C" fn bloom_compile_material_refractive(source_ptr: *const u8) -> f64 {
|
|
972
|
+
use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
|
|
973
|
+
let source = str_from_header(source_ptr);
|
|
974
|
+
match engine().renderer.compile_material_with_options(
|
|
975
|
+
source, FragmentProfile::Translucent, Bucket::Refractive, true, false,
|
|
976
|
+
) {
|
|
977
|
+
Ok(handle) => handle as f64,
|
|
978
|
+
Err(e) => { eprintln!("[refractive] compile failed: {:?}", e); 0.0 }
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
#[no_mangle]
|
|
983
|
+
pub extern "C" fn bloom_compile_material_transparent(source_ptr: *const u8) -> f64 {
|
|
984
|
+
use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
|
|
985
|
+
let source = str_from_header(source_ptr);
|
|
986
|
+
match engine().renderer.compile_material_with_options(
|
|
987
|
+
source, FragmentProfile::Translucent, Bucket::Transparent, false, false,
|
|
988
|
+
) {
|
|
989
|
+
Ok(handle) => handle as f64,
|
|
990
|
+
Err(e) => { eprintln!("[material] compile failed: {:?}", e); 0.0 }
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
#[no_mangle]
|
|
995
|
+
pub extern "C" fn bloom_compile_material_additive(source_ptr: *const u8) -> f64 {
|
|
996
|
+
use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
|
|
997
|
+
let source = str_from_header(source_ptr);
|
|
998
|
+
match engine().renderer.compile_material_with_options(
|
|
999
|
+
source, FragmentProfile::Translucent, Bucket::Additive, false, false,
|
|
1000
|
+
) {
|
|
1001
|
+
Ok(handle) => handle as f64,
|
|
1002
|
+
Err(e) => { eprintln!("[material] compile failed: {:?}", e); 0.0 }
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
#[no_mangle]
|
|
1007
|
+
pub extern "C" fn bloom_compile_material_cutout(source_ptr: *const u8) -> f64 {
|
|
1008
|
+
use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
|
|
1009
|
+
let source = str_from_header(source_ptr);
|
|
1010
|
+
match engine().renderer.compile_material_with_options(
|
|
1011
|
+
source, FragmentProfile::Opaque, Bucket::Cutout, false, false,
|
|
1012
|
+
) {
|
|
1013
|
+
Ok(handle) => handle as f64,
|
|
1014
|
+
Err(e) => { eprintln!("[material] compile failed: {:?}", e); 0.0 }
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
#[no_mangle]
|
|
1019
|
+
pub extern "C" fn bloom_compile_material_instanced(source_ptr: *const u8) -> f64 {
|
|
1020
|
+
let source = str_from_header(source_ptr);
|
|
1021
|
+
match engine().renderer.compile_material_instanced(source) {
|
|
1022
|
+
Ok(handle) => handle as f64,
|
|
1023
|
+
Err(e) => { eprintln!("[material] instanced compile failed: {:?}", e); 0.0 }
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
#[no_mangle]
|
|
1028
|
+
pub extern "C" fn bloom_create_instance_buffer(
|
|
1029
|
+
data_ptr: *const f64, instance_count: f64,
|
|
1030
|
+
) -> f64 {
|
|
1031
|
+
if data_ptr.is_null() || instance_count <= 0.0 { return 0.0; }
|
|
1032
|
+
let count = instance_count as u32;
|
|
1033
|
+
let slot_count = (count as usize) * 9;
|
|
1034
|
+
let raw_f64 = unsafe { std::slice::from_raw_parts(data_ptr, slot_count) };
|
|
1035
|
+
let raw_f32: Vec<f32> = raw_f64.iter().map(|&v| v as f32).collect();
|
|
1036
|
+
engine().renderer.create_instance_buffer(&raw_f32, count) as f64
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
#[no_mangle]
|
|
1040
|
+
pub extern "C" fn bloom_submit_material_draw_instanced(
|
|
1041
|
+
material: f64, mesh_handle: f64, mesh_idx: f64,
|
|
1042
|
+
instance_buffer: f64, instance_count: f64,
|
|
1043
|
+
) {
|
|
1044
|
+
let eng = engine();
|
|
1045
|
+
let handle_bits = mesh_handle.to_bits();
|
|
1046
|
+
if let Some(model) = eng.models.get(mesh_handle) {
|
|
1047
|
+
eng.renderer.cache_model_if_static(handle_bits, &model.meshes);
|
|
1048
|
+
}
|
|
1049
|
+
eng.renderer.submit_material_draw_instanced(
|
|
1050
|
+
material as u32,
|
|
1051
|
+
handle_bits,
|
|
1052
|
+
mesh_idx as usize,
|
|
1053
|
+
instance_buffer as u32,
|
|
1054
|
+
instance_count as u32,
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
#[no_mangle]
|
|
1059
|
+
pub extern "C" fn bloom_destroy_instance_buffer(handle: f64) {
|
|
1060
|
+
engine().renderer.destroy_instance_buffer(handle as u32);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
/// EN-011 — create a planar reflection probe. See macOS lib.rs for the
|
|
1064
|
+
/// full doc comment; this entry-point exists on every native platform
|
|
1065
|
+
/// so games can target the same FFI surface across iOS/tvOS/Windows/
|
|
1066
|
+
/// Linux/Android.
|
|
1067
|
+
#[no_mangle]
|
|
1068
|
+
pub extern "C" fn bloom_create_planar_reflection(
|
|
1069
|
+
plane_y: f64, nx: f64, ny: f64, nz: f64, resolution: f64,
|
|
1070
|
+
) -> f64 {
|
|
1071
|
+
engine().renderer.create_planar_reflection(
|
|
1072
|
+
plane_y as f32,
|
|
1073
|
+
[nx as f32, ny as f32, nz as f32],
|
|
1074
|
+
resolution as u32,
|
|
1075
|
+
) as f64
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/// EN-011 — link a material to a planar reflection probe. `probe = 0`
|
|
1079
|
+
/// reverts the binding to the engine's default 1×1 black texture.
|
|
1080
|
+
#[no_mangle]
|
|
1081
|
+
pub extern "C" fn bloom_set_material_reflection_probe(
|
|
1082
|
+
material: f64, probe: f64,
|
|
1083
|
+
) {
|
|
1084
|
+
engine().renderer.set_material_reflection_probe(material as u32, probe as u32);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/// EN-014 — create a texture array from concatenated RGBA8 byte data.
|
|
1088
|
+
/// See macOS lib.rs for the full doc comment; this entry-point exists
|
|
1089
|
+
/// on every native platform so a TS game targets the same FFI across
|
|
1090
|
+
/// iOS / tvOS / Windows / Linux / Android.
|
|
1091
|
+
#[no_mangle]
|
|
1092
|
+
pub extern "C" fn bloom_create_texture_array(
|
|
1093
|
+
data_ptr: *const u8,
|
|
1094
|
+
data_len: f64,
|
|
1095
|
+
width: f64,
|
|
1096
|
+
height: f64,
|
|
1097
|
+
layer_count: f64,
|
|
1098
|
+
) -> f64 {
|
|
1099
|
+
// EN-014 V2 — V1 forwards to _ex with default sRGB / no mips.
|
|
1100
|
+
bloom_create_texture_array_ex(data_ptr, data_len, width, height, layer_count, 0.0, 1.0)
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
/// EN-014 V2 — explicit format + mip control. See macOS lib.rs for docs.
|
|
1104
|
+
#[no_mangle]
|
|
1105
|
+
pub extern "C" fn bloom_create_texture_array_ex(
|
|
1106
|
+
data_ptr: *const u8,
|
|
1107
|
+
data_len: f64,
|
|
1108
|
+
width: f64,
|
|
1109
|
+
height: f64,
|
|
1110
|
+
layer_count: f64,
|
|
1111
|
+
format: f64,
|
|
1112
|
+
mip_levels: f64,
|
|
1113
|
+
) -> f64 {
|
|
1114
|
+
if data_ptr.is_null() || data_len <= 0.0 { return 0.0; }
|
|
1115
|
+
let w = width as u32;
|
|
1116
|
+
let h = height as u32;
|
|
1117
|
+
if w == 0 || h == 0 { return 0.0; }
|
|
1118
|
+
let layers_count = (layer_count as u32)
|
|
1119
|
+
.min(bloom_shared::renderer::material_system::MAX_TEXTURE_ARRAY_LAYERS);
|
|
1120
|
+
if layers_count == 0 { return 0.0; }
|
|
1121
|
+
let layer_size = (w as usize) * (h as usize) * 4;
|
|
1122
|
+
let total_bytes = (data_len as usize)
|
|
1123
|
+
.min(layers_count as usize * layer_size);
|
|
1124
|
+
let bytes = unsafe { std::slice::from_raw_parts(data_ptr, total_bytes) };
|
|
1125
|
+
let mut layers: Vec<(&[u8], u32, u32)> = Vec::with_capacity(layers_count as usize);
|
|
1126
|
+
for i in 0..(layers_count as usize) {
|
|
1127
|
+
let start = i * layer_size;
|
|
1128
|
+
let end = start + layer_size;
|
|
1129
|
+
if end > bytes.len() { break; }
|
|
1130
|
+
layers.push((&bytes[start..end], w, h));
|
|
1131
|
+
}
|
|
1132
|
+
engine().renderer.create_texture_array_ex(&layers, format as u32, mip_levels as u32) as f64
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/// EN-014 — link a texture-array handle to a material at one of three
|
|
1136
|
+
/// slots: 0 = albedo (binding 14), 1 = normal (binding 15),
|
|
1137
|
+
/// 2 = MR (binding 16). Pass `array = 0` to revert to the stub.
|
|
1138
|
+
#[no_mangle]
|
|
1139
|
+
pub extern "C" fn bloom_set_material_texture_array(
|
|
1140
|
+
material: f64, slot: f64, array: f64,
|
|
1141
|
+
) {
|
|
1142
|
+
engine().renderer.set_material_texture_array(
|
|
1143
|
+
material as u32, slot as u32, array as u32,
|
|
1144
|
+
);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/// EN-012 — set the shading model for a material (0=default lit,
|
|
1148
|
+
/// 1=foliage, 2=subsurface V2 stub).
|
|
1149
|
+
#[no_mangle]
|
|
1150
|
+
pub extern "C" fn bloom_set_material_shading_model(
|
|
1151
|
+
material: f64, model: f64,
|
|
1152
|
+
) {
|
|
1153
|
+
engine().renderer.set_material_shading_model(material as u32, model as u32);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/// EN-012 — set the foliage shading parameters for a material.
|
|
1157
|
+
/// Only takes effect when shading_model == 1 (foliage).
|
|
1158
|
+
#[no_mangle]
|
|
1159
|
+
pub extern "C" fn bloom_set_material_foliage(
|
|
1160
|
+
material: f64,
|
|
1161
|
+
trans_r: f64, trans_g: f64, trans_b: f64,
|
|
1162
|
+
trans_amount: f64, wrap_factor: f64,
|
|
1163
|
+
) {
|
|
1164
|
+
engine().renderer.set_material_foliage(
|
|
1165
|
+
material as u32,
|
|
1166
|
+
[trans_r as f32, trans_g as f32, trans_b as f32],
|
|
1167
|
+
trans_amount as f32, wrap_factor as f32,
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
#[no_mangle]
|
|
1172
|
+
pub extern "C" fn bloom_compile_material_from_file(
|
|
1173
|
+
path_ptr: *const u8,
|
|
1174
|
+
bucket_kind: f64,
|
|
1175
|
+
) -> f64 {
|
|
1176
|
+
use bloom_shared::renderer::material_pipeline::{FragmentProfile, Bucket};
|
|
1177
|
+
let path = str_from_header(path_ptr);
|
|
1178
|
+
let (profile, bucket, reads_scene) = match bucket_kind as u32 {
|
|
1179
|
+
0 => (FragmentProfile::Opaque, Bucket::Opaque, false),
|
|
1180
|
+
1 => (FragmentProfile::Translucent, Bucket::Transparent, false),
|
|
1181
|
+
2 => (FragmentProfile::Translucent, Bucket::Refractive, true),
|
|
1182
|
+
3 => (FragmentProfile::Translucent, Bucket::Additive, false),
|
|
1183
|
+
4 => (FragmentProfile::Opaque, Bucket::Cutout, false),
|
|
1184
|
+
_ => {
|
|
1185
|
+
eprintln!("[material] from_file: unknown bucket_kind {bucket_kind}");
|
|
1186
|
+
return 0.0;
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
match engine().renderer.compile_material_from_file(
|
|
1190
|
+
std::path::Path::new(path), profile, bucket, reads_scene,
|
|
1191
|
+
) {
|
|
1192
|
+
Ok(handle) => handle as f64,
|
|
1193
|
+
Err(e) => { eprintln!("[material] from_file failed: {e}"); 0.0 }
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/// EN-017 — compile + install a fullscreen post-pass material.
|
|
1198
|
+
/// See `bloom-macos::bloom_set_post_pass` for the full ABI.
|
|
1199
|
+
#[no_mangle]
|
|
1200
|
+
pub extern "C" fn bloom_set_post_pass(source_ptr: *const u8) -> f64 {
|
|
1201
|
+
let source = str_from_header(source_ptr);
|
|
1202
|
+
match engine().renderer.set_post_pass(source) {
|
|
1203
|
+
Ok(()) => 1.0,
|
|
1204
|
+
Err(e) => { eprintln!("[post_pass] compile failed: {:?}", e); 0.0 }
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/// EN-017 — uninstall the active post-pass.
|
|
1209
|
+
#[no_mangle]
|
|
1210
|
+
pub extern "C" fn bloom_clear_post_pass() {
|
|
1211
|
+
engine().renderer.clear_post_pass();
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
/// EN-017 V2 — append a post-pass to the stack.
|
|
1215
|
+
/// See `bloom-macos::bloom_add_post_pass` for the full ABI.
|
|
1216
|
+
#[no_mangle]
|
|
1217
|
+
pub extern "C" fn bloom_add_post_pass(source_ptr: *const u8) -> f64 {
|
|
1218
|
+
let source = str_from_header(source_ptr);
|
|
1219
|
+
match engine().renderer.add_post_pass(source) {
|
|
1220
|
+
Ok(h) => h as f64,
|
|
1221
|
+
Err(e) => { eprintln!("[post_pass] compile failed: {:?}", e); 0.0 }
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
/// EN-017 V2 — wipe the entire post-pass stack.
|
|
1226
|
+
#[no_mangle]
|
|
1227
|
+
pub extern "C" fn bloom_clear_all_post_passes() {
|
|
1228
|
+
engine().renderer.clear_all_post_passes();
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
#[no_mangle]
|
|
1232
|
+
pub extern "C" fn bloom_draw_material(
|
|
1233
|
+
material: f64,
|
|
1234
|
+
mesh_handle: f64,
|
|
1235
|
+
mesh_idx: f64,
|
|
1236
|
+
x: f64, y: f64, z: f64, scale: f64,
|
|
1237
|
+
r: f64, g: f64, b: f64, a: f64,
|
|
1238
|
+
) {
|
|
1239
|
+
let eng = engine();
|
|
1240
|
+
let handle_bits = mesh_handle.to_bits();
|
|
1241
|
+
if let Some(model) = eng.models.get(mesh_handle) {
|
|
1242
|
+
eng.renderer.cache_model_if_static(handle_bits, &model.meshes);
|
|
1243
|
+
}
|
|
1244
|
+
eng.renderer.submit_material_draw(
|
|
1245
|
+
material as u32,
|
|
1246
|
+
handle_bits,
|
|
1247
|
+
mesh_idx as usize,
|
|
1248
|
+
[x as f32, y as f32, z as f32],
|
|
1249
|
+
scale as f32,
|
|
1250
|
+
[(r / 255.0) as f32, (g / 255.0) as f32, (b / 255.0) as f32, (a / 255.0) as f32],
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
#[no_mangle]
|
|
1255
|
+
pub extern "C" fn bloom_load_model_animation(path_ptr: *const u8) -> f64 {
|
|
1256
|
+
let path = str_from_header(path_ptr);
|
|
1257
|
+
match std::fs::read(path) {
|
|
1258
|
+
Ok(data) => engine().models.load_model_animation(&data),
|
|
1259
|
+
Err(_) => 0.0,
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
#[no_mangle]
|
|
1264
|
+
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) {
|
|
1265
|
+
let eng = engine();
|
|
1266
|
+
eng.models.update_model_animation(handle, anim_index as usize, time as f32);
|
|
1267
|
+
if let Some(anim) = eng.models.get_animation(handle) {
|
|
1268
|
+
if !anim.joint_matrices.is_empty() {
|
|
1269
|
+
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);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// --- Music FFI ---
|
|
1275
|
+
|
|
1276
|
+
#[no_mangle]
|
|
1277
|
+
pub extern "C" fn bloom_load_music(path_ptr: *const u8) -> f64 {
|
|
1278
|
+
let path = str_from_header(path_ptr);
|
|
1279
|
+
match std::fs::read(path) {
|
|
1280
|
+
Ok(data) => {
|
|
1281
|
+
if let Some(s) = parse_ogg(&data) { engine().audio.load_music(s) }
|
|
1282
|
+
else if let Some(s) = parse_wav(&data) { engine().audio.load_music(s) }
|
|
1283
|
+
else if let Some(s) = parse_mp3(&data) { engine().audio.load_music(s) }
|
|
1284
|
+
else { 0.0 }
|
|
1285
|
+
}
|
|
1286
|
+
Err(_) => 0.0,
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
#[no_mangle]
|
|
1290
|
+
pub extern "C" fn bloom_play_music(handle: f64) { engine().audio.play_music(handle); }
|
|
1291
|
+
#[no_mangle]
|
|
1292
|
+
pub extern "C" fn bloom_stop_music(handle: f64) { engine().audio.stop_music(handle); }
|
|
1293
|
+
#[no_mangle]
|
|
1294
|
+
pub extern "C" fn bloom_update_music_stream(handle: f64) { engine().audio.update_music_stream(handle); }
|
|
1295
|
+
#[no_mangle]
|
|
1296
|
+
pub extern "C" fn bloom_set_music_volume(handle: f64, volume: f64) { engine().audio.set_music_volume(handle, volume as f32); }
|
|
1297
|
+
#[no_mangle]
|
|
1298
|
+
pub extern "C" fn bloom_is_music_playing(handle: f64) -> f64 { if engine().audio.is_music_playing(handle) { 1.0 } else { 0.0 } }
|
|
1299
|
+
|
|
1300
|
+
// --- Gamepad FFI ---
|
|
1301
|
+
|
|
1302
|
+
#[no_mangle]
|
|
1303
|
+
pub extern "C" fn bloom_is_gamepad_available() -> f64 { if engine().input.is_gamepad_available() { 1.0 } else { 0.0 } }
|
|
1304
|
+
#[no_mangle]
|
|
1305
|
+
pub extern "C" fn bloom_get_gamepad_axis(axis: f64) -> f64 { engine().input.get_gamepad_axis(axis as usize) as f64 }
|
|
1306
|
+
#[no_mangle]
|
|
1307
|
+
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 } }
|
|
1308
|
+
#[no_mangle]
|
|
1309
|
+
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 } }
|
|
1310
|
+
#[no_mangle]
|
|
1311
|
+
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 } }
|
|
1312
|
+
#[no_mangle]
|
|
1313
|
+
pub extern "C" fn bloom_get_gamepad_axis_count() -> f64 { engine().input.get_gamepad_axis_count() as f64 }
|
|
1314
|
+
|
|
1315
|
+
// --- Skeletal Animation Debug ---
|
|
1316
|
+
|
|
1317
|
+
#[no_mangle]
|
|
1318
|
+
pub extern "C" fn bloom_set_joint_test(_joint: f64, _angle: f64) {
|
|
1319
|
+
// No-op for now — skeletal animation testing
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
// --- Lighting ---
|
|
1323
|
+
|
|
1324
|
+
#[no_mangle]
|
|
1325
|
+
pub extern "C" fn bloom_set_ambient_light(r: f64, g: f64, b: f64, intensity: f64) {
|
|
1326
|
+
engine().renderer.set_ambient_light(r, g, b, intensity);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
#[no_mangle]
|
|
1330
|
+
pub extern "C" fn bloom_set_directional_light(dx: f64, dy: f64, dz: f64, r: f64, g: f64, b: f64, intensity: f64) {
|
|
1331
|
+
engine().renderer.set_directional_light(dx, dy, dz, r, g, b, intensity);
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
#[no_mangle]
|
|
1335
|
+
pub extern "C" fn bloom_set_procedural_sky(enabled: f64, rayleigh_density: f64, mie_density: f64, ground_albedo: f64) {
|
|
1336
|
+
engine().renderer.set_procedural_sky(
|
|
1337
|
+
enabled != 0.0,
|
|
1338
|
+
rayleigh_density as f32,
|
|
1339
|
+
mie_density as f32,
|
|
1340
|
+
ground_albedo as f32,
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
#[no_mangle]
|
|
1345
|
+
pub extern "C" fn bloom_set_sun_direction(dx: f64, dy: f64, dz: f64, intensity: f64) {
|
|
1346
|
+
engine().renderer.set_sun_direction(dx as f32, dy as f32, dz as f32, intensity as f32);
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// --- Utility FFI ---
|
|
1350
|
+
|
|
1351
|
+
#[no_mangle]
|
|
1352
|
+
pub extern "C" fn bloom_toggle_fullscreen() {
|
|
1353
|
+
#[cfg(target_os = "linux")]
|
|
1354
|
+
x11_impl::toggle_fullscreen();
|
|
1355
|
+
}
|
|
1356
|
+
#[no_mangle]
|
|
1357
|
+
pub extern "C" fn bloom_set_window_title(title_ptr: *const u8) { let _ = str_from_header(title_ptr); }
|
|
1358
|
+
#[no_mangle]
|
|
1359
|
+
pub extern "C" fn bloom_set_window_icon(path_ptr: *const u8) { let _ = str_from_header(path_ptr); }
|
|
1360
|
+
|
|
1361
|
+
#[no_mangle]
|
|
1362
|
+
pub extern "C" fn bloom_disable_cursor() {
|
|
1363
|
+
engine().input.cursor_disabled = true;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
#[no_mangle]
|
|
1367
|
+
pub extern "C" fn bloom_enable_cursor() {
|
|
1368
|
+
engine().input.cursor_disabled = false;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
#[no_mangle]
|
|
1372
|
+
pub extern "C" fn bloom_get_mouse_delta_x() -> f64 {
|
|
1373
|
+
engine().input.mouse_delta_x
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
#[no_mangle]
|
|
1377
|
+
pub extern "C" fn bloom_get_mouse_delta_y() -> f64 {
|
|
1378
|
+
engine().input.mouse_delta_y
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
// Accumulated scroll wheel delta since the last call. Reading consumes the
|
|
1382
|
+
// value (returns 0 on the next call until the user scrolls again). Used by
|
|
1383
|
+
// the editor's orbit camera and any scrollable UI panel.
|
|
1384
|
+
#[no_mangle]
|
|
1385
|
+
pub extern "C" fn bloom_get_mouse_wheel() -> f64 {
|
|
1386
|
+
engine().input.consume_mouse_wheel()
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
#[no_mangle]
|
|
1390
|
+
pub extern "C" fn bloom_get_char_pressed() -> f64 {
|
|
1391
|
+
engine().input.pop_char() as f64
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// Q2: Cursor shape
|
|
1395
|
+
#[no_mangle]
|
|
1396
|
+
pub extern "C" fn bloom_set_cursor_shape(shape: f64) {
|
|
1397
|
+
engine().input.cursor_shape = shape as u32;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
// E4: Clipboard (stub on this platform)
|
|
1401
|
+
#[no_mangle]
|
|
1402
|
+
pub extern "C" fn bloom_set_clipboard_text(_text_ptr: *const u8) {}
|
|
1403
|
+
#[no_mangle]
|
|
1404
|
+
pub extern "C" fn bloom_get_clipboard_text() -> *const u8 { std::ptr::null() }
|
|
1405
|
+
|
|
1406
|
+
// E5b: File dialogs (stub on this platform)
|
|
1407
|
+
#[no_mangle]
|
|
1408
|
+
pub extern "C" fn bloom_open_file_dialog(_filter_ptr: *const u8, _title_ptr: *const u8) -> *const u8 { std::ptr::null() }
|
|
1409
|
+
#[no_mangle]
|
|
1410
|
+
pub extern "C" fn bloom_save_file_dialog(_default_name_ptr: *const u8, _title_ptr: *const u8) -> *const u8 { std::ptr::null() }
|
|
1411
|
+
|
|
1412
|
+
// Model bounds accessors. Return the axis-aligned bounding box of a loaded
|
|
1413
|
+
// model in model-local coordinates. Editors use these to size gizmos, auto-
|
|
1414
|
+
// frame the camera on selection, and snap placed entities onto terrain.
|
|
1415
|
+
#[no_mangle]
|
|
1416
|
+
pub extern "C" fn bloom_get_model_bounds_min_x(model_handle: f64) -> f64 {
|
|
1417
|
+
engine().models.get_bounds(model_handle).0[0] as f64
|
|
1418
|
+
}
|
|
1419
|
+
#[no_mangle]
|
|
1420
|
+
pub extern "C" fn bloom_get_model_bounds_min_y(model_handle: f64) -> f64 {
|
|
1421
|
+
engine().models.get_bounds(model_handle).0[1] as f64
|
|
1422
|
+
}
|
|
1423
|
+
#[no_mangle]
|
|
1424
|
+
pub extern "C" fn bloom_get_model_bounds_min_z(model_handle: f64) -> f64 {
|
|
1425
|
+
engine().models.get_bounds(model_handle).0[2] as f64
|
|
1426
|
+
}
|
|
1427
|
+
#[no_mangle]
|
|
1428
|
+
pub extern "C" fn bloom_get_model_bounds_max_x(model_handle: f64) -> f64 {
|
|
1429
|
+
engine().models.get_bounds(model_handle).1[0] as f64
|
|
1430
|
+
}
|
|
1431
|
+
#[no_mangle]
|
|
1432
|
+
pub extern "C" fn bloom_get_model_bounds_max_y(model_handle: f64) -> f64 {
|
|
1433
|
+
engine().models.get_bounds(model_handle).1[1] as f64
|
|
1434
|
+
}
|
|
1435
|
+
#[no_mangle]
|
|
1436
|
+
pub extern "C" fn bloom_get_model_bounds_max_z(model_handle: f64) -> f64 {
|
|
1437
|
+
engine().models.get_bounds(model_handle).1[2] as f64
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
#[no_mangle]
|
|
1441
|
+
pub extern "C" fn bloom_write_file(path_ptr: *const u8, data_ptr: *const u8) -> f64 {
|
|
1442
|
+
let path = str_from_header(path_ptr);
|
|
1443
|
+
let data = str_from_header(data_ptr);
|
|
1444
|
+
match std::fs::write(path, data.as_bytes()) {
|
|
1445
|
+
Ok(_) => 1.0,
|
|
1446
|
+
Err(_) => 0.0,
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
#[no_mangle]
|
|
1451
|
+
pub extern "C" fn bloom_file_exists(path_ptr: *const u8) -> f64 {
|
|
1452
|
+
let path = str_from_header(path_ptr);
|
|
1453
|
+
if std::path::Path::new(path).exists() { 1.0 } else { 0.0 }
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
#[no_mangle]
|
|
1457
|
+
pub extern "C" fn bloom_read_file(path_ptr: *const u8) -> *const u8 {
|
|
1458
|
+
let path = str_from_header(path_ptr);
|
|
1459
|
+
match std::fs::read_to_string(path) {
|
|
1460
|
+
Ok(contents) => {
|
|
1461
|
+
// Return Perry-format string: StringHeader (length u32 + capacity u32 + refcount u32) followed by UTF-8 data
|
|
1462
|
+
let bytes = contents.as_bytes();
|
|
1463
|
+
let len = bytes.len();
|
|
1464
|
+
let total = 12 + len; // 12 bytes header (3 × u32) + data
|
|
1465
|
+
let layout = std::alloc::Layout::from_size_align(total, 4).unwrap();
|
|
1466
|
+
unsafe {
|
|
1467
|
+
let ptr = std::alloc::alloc(layout);
|
|
1468
|
+
if ptr.is_null() { return std::ptr::null(); }
|
|
1469
|
+
*(ptr as *mut u32) = len as u32; // length
|
|
1470
|
+
*(ptr.add(4) as *mut u32) = len as u32; // capacity
|
|
1471
|
+
*(ptr.add(8) as *mut u32) = 1; // refcount (unique)
|
|
1472
|
+
std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.add(12), len);
|
|
1473
|
+
ptr
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
Err(_) => std::ptr::null(),
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
#[no_mangle]
|
|
1481
|
+
pub extern "C" fn bloom_get_touch_x(index: f64) -> f64 { engine().input.get_touch_x(index as usize) }
|
|
1482
|
+
#[no_mangle]
|
|
1483
|
+
pub extern "C" fn bloom_get_touch_y(index: f64) -> f64 { engine().input.get_touch_y(index as usize) }
|
|
1484
|
+
#[no_mangle]
|
|
1485
|
+
pub extern "C" fn bloom_get_touch_count() -> f64 { engine().input.get_touch_count() as f64 }
|
|
1486
|
+
#[no_mangle]
|
|
1487
|
+
pub extern "C" fn bloom_get_time() -> f64 { engine().get_time() }
|
|
1488
|
+
|
|
1489
|
+
// Input injection + platform detection
|
|
1490
|
+
#[no_mangle]
|
|
1491
|
+
pub extern "C" fn bloom_inject_key_down(key: f64) {
|
|
1492
|
+
engine().input.set_key_down(key as usize);
|
|
1493
|
+
}
|
|
1494
|
+
#[no_mangle]
|
|
1495
|
+
pub extern "C" fn bloom_inject_key_up(key: f64) {
|
|
1496
|
+
engine().input.set_key_up(key as usize);
|
|
1497
|
+
}
|
|
1498
|
+
#[no_mangle]
|
|
1499
|
+
pub extern "C" fn bloom_inject_gamepad_axis(axis: f64, value: f64) {
|
|
1500
|
+
engine().input.set_gamepad_axis(axis as usize, value as f32);
|
|
1501
|
+
}
|
|
1502
|
+
#[no_mangle]
|
|
1503
|
+
pub extern "C" fn bloom_inject_gamepad_button_down(button: f64) {
|
|
1504
|
+
engine().input.set_gamepad_button_down(button as usize);
|
|
1505
|
+
}
|
|
1506
|
+
#[no_mangle]
|
|
1507
|
+
pub extern "C" fn bloom_inject_gamepad_button_up(button: f64) {
|
|
1508
|
+
engine().input.set_gamepad_button_up(button as usize);
|
|
1509
|
+
}
|
|
1510
|
+
#[no_mangle]
|
|
1511
|
+
pub extern "C" fn bloom_get_platform() -> f64 { 4.0 }
|
|
1512
|
+
#[no_mangle]
|
|
1513
|
+
pub extern "C" fn bloom_is_any_input_pressed() -> f64 {
|
|
1514
|
+
if engine().input.is_any_input_pressed() { 1.0 } else { 0.0 }
|
|
1515
|
+
}
|
|
1516
|
+
#[no_mangle]
|
|
1517
|
+
pub extern "C" fn bloom_get_crown_rotation() -> f64 {
|
|
1518
|
+
engine().input.consume_crown_rotation()
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
// ============================================================
|
|
1522
|
+
// Frame callbacks
|
|
1523
|
+
// ============================================================
|
|
1524
|
+
|
|
1525
|
+
#[no_mangle]
|
|
1526
|
+
pub extern "C" fn bloom_register_frame_callback(priority: f64, callback: extern "C" fn(f64)) -> f64 {
|
|
1527
|
+
engine().frame_callbacks.register(priority as i32, callback) as f64
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
#[no_mangle]
|
|
1531
|
+
pub extern "C" fn bloom_unregister_frame_callback(id: f64) {
|
|
1532
|
+
engine().frame_callbacks.unregister(id as u64);
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
#[no_mangle]
|
|
1536
|
+
pub extern "C" fn bloom_run_game(_callback: extern "C" fn(f64)) {
|
|
1537
|
+
// No-op on native. The TypeScript runGame() helper provides the while loop.
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
// ============================================================
|
|
1541
|
+
// Multiple lights
|
|
1542
|
+
// ============================================================
|
|
1543
|
+
|
|
1544
|
+
#[no_mangle]
|
|
1545
|
+
pub extern "C" fn bloom_add_directional_light(
|
|
1546
|
+
dx: f64, dy: f64, dz: f64,
|
|
1547
|
+
r: f64, g: f64, b: f64,
|
|
1548
|
+
intensity: f64,
|
|
1549
|
+
) {
|
|
1550
|
+
engine().renderer.add_directional_light(
|
|
1551
|
+
dx as f32, dy as f32, dz as f32,
|
|
1552
|
+
r as f32, g as f32, b as f32,
|
|
1553
|
+
intensity as f32,
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
#[no_mangle]
|
|
1558
|
+
pub extern "C" fn bloom_add_point_light(
|
|
1559
|
+
x: f64, y: f64, z: f64, range: f64,
|
|
1560
|
+
r: f64, g: f64, b: f64,
|
|
1561
|
+
intensity: f64,
|
|
1562
|
+
) {
|
|
1563
|
+
engine().renderer.add_point_light(
|
|
1564
|
+
x as f32, y as f32, z as f32, range as f32,
|
|
1565
|
+
r as f32, g as f32, b as f32,
|
|
1566
|
+
intensity as f32,
|
|
1567
|
+
);
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
// ============================================================
|
|
1571
|
+
// Scene graph (retained mode)
|
|
1572
|
+
// ============================================================
|
|
1573
|
+
|
|
1574
|
+
#[no_mangle]
|
|
1575
|
+
pub extern "C" fn bloom_scene_create_node() -> f64 {
|
|
1576
|
+
engine().scene.create_node()
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
#[no_mangle]
|
|
1580
|
+
pub extern "C" fn bloom_scene_destroy_node(handle: f64) {
|
|
1581
|
+
engine().scene.destroy_node(handle);
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
#[no_mangle]
|
|
1585
|
+
pub extern "C" fn bloom_scene_set_visible(handle: f64, visible: f64) {
|
|
1586
|
+
engine().scene.set_visible(handle, visible != 0.0);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
#[no_mangle]
|
|
1590
|
+
pub extern "C" fn bloom_scene_set_cast_shadow(handle: f64, cast: f64) {
|
|
1591
|
+
engine().scene.set_cast_shadow(handle, cast != 0.0);
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
#[no_mangle]
|
|
1595
|
+
pub extern "C" fn bloom_scene_set_receive_shadow(handle: f64, receive: f64) {
|
|
1596
|
+
engine().scene.set_receive_shadow(handle, receive != 0.0);
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
#[no_mangle]
|
|
1600
|
+
pub extern "C" fn bloom_scene_set_parent(handle: f64, parent: f64) {
|
|
1601
|
+
engine().scene.set_parent(handle, parent);
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
#[no_mangle]
|
|
1605
|
+
pub extern "C" fn bloom_scene_set_transform(handle: f64, mat_ptr: *const f64) {
|
|
1606
|
+
if mat_ptr.is_null() { return; }
|
|
1607
|
+
let slice = unsafe { std::slice::from_raw_parts(mat_ptr, 16) };
|
|
1608
|
+
let mut mat = [[0.0f32; 4]; 4];
|
|
1609
|
+
for col in 0..4 {
|
|
1610
|
+
for row in 0..4 {
|
|
1611
|
+
mat[col][row] = slice[col * 4 + row] as f32;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
engine().scene.set_transform(handle, mat);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
#[no_mangle]
|
|
1618
|
+
pub extern "C" fn bloom_scene_update_geometry(
|
|
1619
|
+
handle: f64,
|
|
1620
|
+
vert_ptr: *const f64,
|
|
1621
|
+
vert_count: f64,
|
|
1622
|
+
idx_ptr: *const f64,
|
|
1623
|
+
idx_count: f64,
|
|
1624
|
+
) {
|
|
1625
|
+
if vert_ptr.is_null() || idx_ptr.is_null() { return; }
|
|
1626
|
+
let nv = vert_count as usize;
|
|
1627
|
+
let ni = idx_count as usize;
|
|
1628
|
+
|
|
1629
|
+
let vert_floats = unsafe { std::slice::from_raw_parts(vert_ptr, nv * 12) };
|
|
1630
|
+
let idx_floats = unsafe { std::slice::from_raw_parts(idx_ptr, ni) };
|
|
1631
|
+
|
|
1632
|
+
let mut vertices = Vec::with_capacity(nv);
|
|
1633
|
+
for i in 0..nv {
|
|
1634
|
+
let base = i * 12;
|
|
1635
|
+
vertices.push(bloom_shared::renderer::Vertex3D {
|
|
1636
|
+
position: [vert_floats[base] as f32, vert_floats[base+1] as f32, vert_floats[base+2] as f32],
|
|
1637
|
+
normal: [vert_floats[base+3] as f32, vert_floats[base+4] as f32, vert_floats[base+5] as f32],
|
|
1638
|
+
color: [vert_floats[base+6] as f32, vert_floats[base+7] as f32, vert_floats[base+8] as f32, vert_floats[base+9] as f32],
|
|
1639
|
+
uv: [vert_floats[base+10] as f32, vert_floats[base+11] as f32],
|
|
1640
|
+
joints: [0.0; 4],
|
|
1641
|
+
weights: [0.0; 4],
|
|
1642
|
+
tangent: [0.0; 4],
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
let indices: Vec<u32> = idx_floats.iter().map(|&v| v as u32).collect();
|
|
1647
|
+
|
|
1648
|
+
engine().scene.update_geometry(handle, vertices, indices);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
#[no_mangle]
|
|
1652
|
+
pub extern "C" fn bloom_scene_set_material_color(handle: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
1653
|
+
engine().scene.set_material_color(handle, r as f32, g as f32, b as f32, a as f32);
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
#[no_mangle]
|
|
1657
|
+
pub extern "C" fn bloom_scene_set_material_pbr(handle: f64, roughness: f64, metalness: f64) {
|
|
1658
|
+
engine().scene.set_material_pbr(handle, roughness as f32, metalness as f32);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
#[no_mangle]
|
|
1662
|
+
pub extern "C" fn bloom_scene_set_material_texture(handle: f64, texture_idx: f64) {
|
|
1663
|
+
engine().scene.set_material_texture(handle, texture_idx as u32);
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
#[no_mangle]
|
|
1667
|
+
pub extern "C" fn bloom_scene_node_count() -> f64 {
|
|
1668
|
+
engine().scene.node_count() as f64
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
#[no_mangle]
|
|
1672
|
+
pub extern "C" fn bloom_scene_node_vertex_count(handle: f64) -> f64 {
|
|
1673
|
+
match engine().scene.nodes.get(handle) {
|
|
1674
|
+
Some(node) => node.vertices.len() as f64,
|
|
1675
|
+
None => -1.0,
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
#[no_mangle]
|
|
1680
|
+
pub extern "C" fn bloom_scene_node_index_count(handle: f64) -> f64 {
|
|
1681
|
+
match engine().scene.nodes.get(handle) {
|
|
1682
|
+
Some(node) => node.indices.len() as f64,
|
|
1683
|
+
None => -1.0,
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
// Q8: Set a water material on a scene node (translucent tint, low roughness).
|
|
1689
|
+
#[no_mangle]
|
|
1690
|
+
pub extern "C" fn bloom_scene_set_material_water(handle: f64, wave_amp: f64, wave_speed: f64, r: f64, g: f64, b: f64, a: f64) {
|
|
1691
|
+
engine().scene.set_material_water(handle, wave_amp as f32, wave_speed as f32, r as f32, g as f32, b as f32, a as f32);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// Q9: Generate a ribbon mesh along a Catmull-Rom spline.
|
|
1695
|
+
#[no_mangle]
|
|
1696
|
+
pub extern "C" fn bloom_gen_mesh_spline_ribbon(points_ptr: *const u8, point_count: f64, widths_ptr: *const u8, width_count: f64) -> f64 {
|
|
1697
|
+
let n = point_count as usize;
|
|
1698
|
+
let wn = width_count as usize;
|
|
1699
|
+
let points = unsafe { std::slice::from_raw_parts(points_ptr as *const f32, n * 3) };
|
|
1700
|
+
let widths = unsafe { std::slice::from_raw_parts(widths_ptr as *const f32, wn) };
|
|
1701
|
+
engine().models.gen_mesh_spline_ribbon(points, widths)
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
// Q1: Render texture FFI (stub — GPU implementation deferred).
|
|
1705
|
+
#[no_mangle]
|
|
1706
|
+
pub extern "C" fn bloom_load_render_texture(width: f64, height: f64) -> f64 {
|
|
1707
|
+
engine().textures.load_render_texture(width as u32, height as u32)
|
|
1708
|
+
}
|
|
1709
|
+
#[no_mangle]
|
|
1710
|
+
pub extern "C" fn bloom_unload_render_texture(handle: f64) {
|
|
1711
|
+
engine().textures.unload_render_texture(handle);
|
|
1712
|
+
}
|
|
1713
|
+
#[no_mangle]
|
|
1714
|
+
pub extern "C" fn bloom_begin_texture_mode(_handle: f64) {
|
|
1715
|
+
// Stub: no-op until GPU render-to-texture is wired.
|
|
1716
|
+
}
|
|
1717
|
+
#[no_mangle]
|
|
1718
|
+
pub extern "C" fn bloom_end_texture_mode() {
|
|
1719
|
+
// Stub: no-op.
|
|
1720
|
+
}
|
|
1721
|
+
#[no_mangle]
|
|
1722
|
+
pub extern "C" fn bloom_get_render_texture_texture(handle: f64) -> f64 {
|
|
1723
|
+
engine().textures.get_render_texture_texture(handle)
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// Scene graph QoL — Q4/Q5/Q6/Q7
|
|
1727
|
+
#[no_mangle]
|
|
1728
|
+
pub extern "C" fn bloom_scene_get_transform(handle: f64, index: f64) -> f64 {
|
|
1729
|
+
let mat = engine().scene.get_transform(handle);
|
|
1730
|
+
let i = index as usize;
|
|
1731
|
+
let col = i / 4;
|
|
1732
|
+
let row = i % 4;
|
|
1733
|
+
if col < 4 && row < 4 { mat[col][row] as f64 } else { 0.0 }
|
|
1734
|
+
}
|
|
1735
|
+
#[no_mangle]
|
|
1736
|
+
pub extern "C" fn bloom_scene_get_bounds_min_x(handle: f64) -> f64 { engine().scene.get_bounds(handle).0[0] as f64 }
|
|
1737
|
+
#[no_mangle]
|
|
1738
|
+
pub extern "C" fn bloom_scene_get_bounds_min_y(handle: f64) -> f64 { engine().scene.get_bounds(handle).0[1] as f64 }
|
|
1739
|
+
#[no_mangle]
|
|
1740
|
+
pub extern "C" fn bloom_scene_get_bounds_min_z(handle: f64) -> f64 { engine().scene.get_bounds(handle).0[2] as f64 }
|
|
1741
|
+
#[no_mangle]
|
|
1742
|
+
pub extern "C" fn bloom_scene_get_bounds_max_x(handle: f64) -> f64 { engine().scene.get_bounds(handle).1[0] as f64 }
|
|
1743
|
+
#[no_mangle]
|
|
1744
|
+
pub extern "C" fn bloom_scene_get_bounds_max_y(handle: f64) -> f64 { engine().scene.get_bounds(handle).1[1] as f64 }
|
|
1745
|
+
#[no_mangle]
|
|
1746
|
+
pub extern "C" fn bloom_scene_get_bounds_max_z(handle: f64) -> f64 { engine().scene.get_bounds(handle).1[2] as f64 }
|
|
1747
|
+
#[no_mangle]
|
|
1748
|
+
pub extern "C" fn bloom_scene_set_user_data(handle: f64, data: f64) { engine().scene.set_user_data(handle, data as i64); }
|
|
1749
|
+
#[no_mangle]
|
|
1750
|
+
pub extern "C" fn bloom_scene_get_user_data(handle: f64) -> f64 { engine().scene.get_user_data(handle) as f64 }
|
|
1751
|
+
// ============================================================
|
|
1752
|
+
// Geometry generation
|
|
1753
|
+
// ============================================================
|
|
1754
|
+
|
|
1755
|
+
#[no_mangle]
|
|
1756
|
+
pub extern "C" fn bloom_scene_extrude_polygon(
|
|
1757
|
+
handle: f64,
|
|
1758
|
+
polygon_ptr: *const f64,
|
|
1759
|
+
polygon_count: f64,
|
|
1760
|
+
depth: f64,
|
|
1761
|
+
) {
|
|
1762
|
+
if polygon_ptr.is_null() { return; }
|
|
1763
|
+
let n = polygon_count as usize;
|
|
1764
|
+
let polygon = unsafe { std::slice::from_raw_parts(polygon_ptr, n * 2) };
|
|
1765
|
+
|
|
1766
|
+
let geo = bloom_shared::geometry::extrude_polygon(polygon, &[], depth);
|
|
1767
|
+
engine().scene.update_geometry(handle, geo.vertices, geo.indices);
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
#[no_mangle]
|
|
1771
|
+
pub extern "C" fn bloom_scene_subtract_box(
|
|
1772
|
+
handle: f64,
|
|
1773
|
+
min_x: f64, min_y: f64, min_z: f64,
|
|
1774
|
+
max_x: f64, max_y: f64, max_z: f64,
|
|
1775
|
+
) {
|
|
1776
|
+
let eng = engine();
|
|
1777
|
+
if let Some(node) = eng.scene.nodes.get(handle) {
|
|
1778
|
+
let current = bloom_shared::geometry::GeometryData {
|
|
1779
|
+
vertices: node.vertices.clone(),
|
|
1780
|
+
indices: node.indices.clone(),
|
|
1781
|
+
};
|
|
1782
|
+
let result = bloom_shared::geometry::subtract_box(
|
|
1783
|
+
¤t,
|
|
1784
|
+
[min_x as f32, min_y as f32, min_z as f32],
|
|
1785
|
+
[max_x as f32, max_y as f32, max_z as f32],
|
|
1786
|
+
);
|
|
1787
|
+
eng.scene.update_geometry(handle, result.vertices, result.indices);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
// ============================================================
|
|
1792
|
+
// Shadow mapping
|
|
1793
|
+
// ============================================================
|
|
1794
|
+
|
|
1795
|
+
#[no_mangle]
|
|
1796
|
+
pub extern "C" fn bloom_enable_shadows() {
|
|
1797
|
+
engine().renderer.shadow_map.enable();
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
#[no_mangle]
|
|
1801
|
+
pub extern "C" fn bloom_disable_shadows() {
|
|
1802
|
+
engine().renderer.shadow_map.disable();
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
// ============================================================
|
|
1806
|
+
// Post-processing
|
|
1807
|
+
// ============================================================
|
|
1808
|
+
|
|
1809
|
+
#[no_mangle]
|
|
1810
|
+
pub extern "C" fn bloom_enable_postfx() {
|
|
1811
|
+
let eng = engine();
|
|
1812
|
+
let w = eng.renderer.width();
|
|
1813
|
+
let h = eng.renderer.height();
|
|
1814
|
+
let fmt = eng.renderer.surface_format();
|
|
1815
|
+
eng.postfx = Some(bloom_shared::postfx::PostFxPipeline::new(
|
|
1816
|
+
&eng.renderer.device, w, h, fmt,
|
|
1817
|
+
));
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
#[no_mangle]
|
|
1821
|
+
pub extern "C" fn bloom_disable_postfx() {
|
|
1822
|
+
engine().postfx = None;
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
#[no_mangle]
|
|
1826
|
+
pub extern "C" fn bloom_postfx_set_selected(handle: f64) {
|
|
1827
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
1828
|
+
if handle == 0.0 {
|
|
1829
|
+
pfx.set_selected(Vec::new());
|
|
1830
|
+
} else {
|
|
1831
|
+
pfx.set_selected(vec![handle]);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
#[no_mangle]
|
|
1837
|
+
pub extern "C" fn bloom_postfx_set_hovered(handle: f64) {
|
|
1838
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
1839
|
+
pfx.set_hovered(handle);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
#[no_mangle]
|
|
1844
|
+
pub extern "C" fn bloom_postfx_set_outline_color(r: f64, g: f64, b: f64, a: f64) {
|
|
1845
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
1846
|
+
pfx.outline_params.color_selected = [r as f32, g as f32, b as f32, a as f32];
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
#[no_mangle]
|
|
1851
|
+
pub extern "C" fn bloom_postfx_set_outline_thickness(thickness: f64) {
|
|
1852
|
+
if let Some(pfx) = &mut engine().postfx {
|
|
1853
|
+
pfx.outline_params.thickness[0] = thickness as f32;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
// ============================================================
|
|
1858
|
+
// 3D→2D Projection (for UI overlays positioned in 3D space)
|
|
1859
|
+
// ============================================================
|
|
1860
|
+
|
|
1861
|
+
static mut LAST_PROJECT: (f64, f64) = (0.0, 0.0);
|
|
1862
|
+
|
|
1863
|
+
#[no_mangle]
|
|
1864
|
+
pub extern "C" fn bloom_project_to_screen(wx: f64, wy: f64, wz: f64) -> f64 {
|
|
1865
|
+
let eng = engine();
|
|
1866
|
+
let vp = eng.renderer.vp_matrix();
|
|
1867
|
+
let w = eng.renderer.width() as f32;
|
|
1868
|
+
let h = eng.renderer.height() as f32;
|
|
1869
|
+
|
|
1870
|
+
let x = wx as f32;
|
|
1871
|
+
let y = wy as f32;
|
|
1872
|
+
let z = wz as f32;
|
|
1873
|
+
let clip_x = vp[0][0]*x + vp[1][0]*y + vp[2][0]*z + vp[3][0];
|
|
1874
|
+
let clip_y = vp[0][1]*x + vp[1][1]*y + vp[2][1]*z + vp[3][1];
|
|
1875
|
+
let clip_w = vp[0][3]*x + vp[1][3]*y + vp[2][3]*z + vp[3][3];
|
|
1876
|
+
|
|
1877
|
+
if clip_w <= 0.0 {
|
|
1878
|
+
unsafe { LAST_PROJECT = (-9999.0, -9999.0); }
|
|
1879
|
+
return -9999.0;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
let ndc_x = clip_x / clip_w;
|
|
1883
|
+
let ndc_y = clip_y / clip_w;
|
|
1884
|
+
let screen_x = ((ndc_x + 1.0) * 0.5 * w) as f64;
|
|
1885
|
+
let screen_y = ((1.0 - ndc_y) * 0.5 * h) as f64;
|
|
1886
|
+
|
|
1887
|
+
unsafe { LAST_PROJECT = (screen_x, screen_y); }
|
|
1888
|
+
screen_x
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
#[no_mangle]
|
|
1892
|
+
pub extern "C" fn bloom_project_screen_y() -> f64 {
|
|
1893
|
+
unsafe { LAST_PROJECT.1 }
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
#[no_mangle]
|
|
1897
|
+
pub extern "C" fn bloom_scene_attach_model(node_handle: f64, model_handle: f64, mesh_index: f64) {
|
|
1898
|
+
let eng = engine();
|
|
1899
|
+
let mi = mesh_index as usize;
|
|
1900
|
+
|
|
1901
|
+
let model_data = match eng.models.models.get(model_handle) {
|
|
1902
|
+
Some(md) => md,
|
|
1903
|
+
None => return,
|
|
1904
|
+
};
|
|
1905
|
+
if mi >= model_data.meshes.len() { return; }
|
|
1906
|
+
let mesh = &model_data.meshes[mi];
|
|
1907
|
+
|
|
1908
|
+
let vertices = mesh.vertices.clone();
|
|
1909
|
+
let indices = mesh.indices.clone();
|
|
1910
|
+
let base_color_tex = mesh.texture_idx;
|
|
1911
|
+
let normal_tex = mesh.normal_texture_idx;
|
|
1912
|
+
let mr_tex = mesh.metallic_roughness_texture_idx;
|
|
1913
|
+
let emissive_tex = mesh.emissive_texture_idx;
|
|
1914
|
+
let emissive_factor = mesh.emissive_factor;
|
|
1915
|
+
eng.scene.update_geometry(node_handle, vertices, indices);
|
|
1916
|
+
|
|
1917
|
+
if let Some(tex_idx) = base_color_tex {
|
|
1918
|
+
eng.scene.set_material_texture(node_handle, tex_idx);
|
|
1919
|
+
}
|
|
1920
|
+
if let Some(tex_idx) = normal_tex {
|
|
1921
|
+
eng.scene.set_material_normal_texture(node_handle, tex_idx);
|
|
1922
|
+
}
|
|
1923
|
+
if let Some(tex_idx) = mr_tex {
|
|
1924
|
+
eng.scene.set_material_metallic_roughness_texture(node_handle, tex_idx);
|
|
1925
|
+
}
|
|
1926
|
+
if let Some(tex_idx) = emissive_tex {
|
|
1927
|
+
eng.scene.set_material_emissive_texture(node_handle, tex_idx);
|
|
1928
|
+
}
|
|
1929
|
+
eng.scene.set_material_emissive_factor(
|
|
1930
|
+
node_handle,
|
|
1931
|
+
emissive_factor[0],
|
|
1932
|
+
emissive_factor[1],
|
|
1933
|
+
emissive_factor[2],
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
// ============================================================
|
|
1938
|
+
// Scene picking (raycasting)
|
|
1939
|
+
// ============================================================
|
|
1940
|
+
|
|
1941
|
+
static mut LAST_PICK: Option<bloom_shared::picking::PickResult> = None;
|
|
1942
|
+
|
|
1943
|
+
#[no_mangle]
|
|
1944
|
+
pub extern "C" fn bloom_scene_pick(screen_x: f64, screen_y: f64) -> f64 {
|
|
1945
|
+
let eng = engine();
|
|
1946
|
+
let inv_vp = eng.renderer.inverse_vp_matrix();
|
|
1947
|
+
let cam_pos = eng.renderer.camera_pos();
|
|
1948
|
+
let w = eng.renderer.width() as f32;
|
|
1949
|
+
let h = eng.renderer.height() as f32;
|
|
1950
|
+
|
|
1951
|
+
let (origin, direction) = bloom_shared::picking::screen_to_ray(
|
|
1952
|
+
screen_x as f32, screen_y as f32,
|
|
1953
|
+
w, h, &inv_vp, &cam_pos,
|
|
1954
|
+
);
|
|
1955
|
+
|
|
1956
|
+
let result = bloom_shared::picking::raycast_scene(&eng.scene, &origin, &direction);
|
|
1957
|
+
let hit = result.hit;
|
|
1958
|
+
unsafe { LAST_PICK = Some(result); }
|
|
1959
|
+
if hit { 1.0 } else { 0.0 }
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
#[no_mangle]
|
|
1963
|
+
pub extern "C" fn bloom_pick_hit_handle() -> f64 {
|
|
1964
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.handle).unwrap_or(0.0) }
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
#[no_mangle]
|
|
1968
|
+
pub extern "C" fn bloom_pick_hit_distance() -> f64 {
|
|
1969
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.distance as f64).unwrap_or(0.0) }
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
#[no_mangle]
|
|
1973
|
+
pub extern "C" fn bloom_pick_hit_x() -> f64 {
|
|
1974
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.point[0] as f64).unwrap_or(0.0) }
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
#[no_mangle]
|
|
1978
|
+
pub extern "C" fn bloom_pick_hit_y() -> f64 {
|
|
1979
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.point[1] as f64).unwrap_or(0.0) }
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
#[no_mangle]
|
|
1983
|
+
pub extern "C" fn bloom_pick_hit_z() -> f64 {
|
|
1984
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.point[2] as f64).unwrap_or(0.0) }
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
#[no_mangle]
|
|
1988
|
+
pub extern "C" fn bloom_pick_hit_normal_x() -> f64 {
|
|
1989
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.normal[0] as f64).unwrap_or(0.0) }
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
#[no_mangle]
|
|
1993
|
+
pub extern "C" fn bloom_pick_hit_normal_y() -> f64 {
|
|
1994
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.normal[1] as f64).unwrap_or(0.0) }
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
#[no_mangle]
|
|
1998
|
+
pub extern "C" fn bloom_pick_hit_normal_z() -> f64 {
|
|
1999
|
+
unsafe { LAST_PICK.as_ref().map(|r| r.normal[2] as f64).unwrap_or(0.0) }
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// ============================================================
|
|
2003
|
+
// Thread-safe staging (for async asset loading via Perry threads)
|
|
2004
|
+
// ============================================================
|
|
2005
|
+
|
|
2006
|
+
#[no_mangle]
|
|
2007
|
+
pub extern "C" fn bloom_stage_texture(path_ptr: *const u8) -> f64 {
|
|
2008
|
+
let path = str_from_header(path_ptr);
|
|
2009
|
+
match std::fs::read(path) {
|
|
2010
|
+
Ok(data) => bloom_shared::staging::decode_and_stage_texture(&data),
|
|
2011
|
+
Err(_) => 0.0,
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
#[no_mangle]
|
|
2016
|
+
pub extern "C" fn bloom_stage_model(path_ptr: *const u8) -> f64 {
|
|
2017
|
+
let path = str_from_header(path_ptr);
|
|
2018
|
+
let data = match std::fs::read(path) {
|
|
2019
|
+
Ok(d) => d,
|
|
2020
|
+
Err(_) => return 0.0,
|
|
2021
|
+
};
|
|
2022
|
+
match bloom_shared::models::load_gltf_staged(&data) {
|
|
2023
|
+
Some(staged) => bloom_shared::staging::stage_model(staged),
|
|
2024
|
+
None => 0.0,
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
#[no_mangle]
|
|
2029
|
+
pub extern "C" fn bloom_stage_sound(path_ptr: *const u8) -> f64 {
|
|
2030
|
+
let path = str_from_header(path_ptr);
|
|
2031
|
+
let data = match std::fs::read(path) {
|
|
2032
|
+
Ok(d) => d,
|
|
2033
|
+
Err(_) => return 0.0,
|
|
2034
|
+
};
|
|
2035
|
+
let sound_data = if path.ends_with(".ogg") || path.ends_with(".OGG") {
|
|
2036
|
+
parse_ogg(&data)
|
|
2037
|
+
} else if path.ends_with(".mp3") || path.ends_with(".MP3") {
|
|
2038
|
+
parse_mp3(&data)
|
|
2039
|
+
} else {
|
|
2040
|
+
parse_wav(&data)
|
|
2041
|
+
};
|
|
2042
|
+
match sound_data {
|
|
2043
|
+
Some(sd) => bloom_shared::staging::stage_sound(sd),
|
|
2044
|
+
None => 0.0,
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
#[no_mangle]
|
|
2049
|
+
pub extern "C" fn bloom_commit_texture(staging_handle: f64) -> f64 {
|
|
2050
|
+
let staged = match bloom_shared::staging::take_texture(staging_handle) {
|
|
2051
|
+
Some(s) => s,
|
|
2052
|
+
None => return 0.0,
|
|
2053
|
+
};
|
|
2054
|
+
let eng = engine();
|
|
2055
|
+
let bind_group_idx = eng.renderer.register_texture(staged.width, staged.height, &staged.data);
|
|
2056
|
+
eng.textures.textures.alloc(bloom_shared::textures::TextureData {
|
|
2057
|
+
bind_group_idx, width: staged.width, height: staged.height,
|
|
2058
|
+
})
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
#[no_mangle]
|
|
2062
|
+
pub extern "C" fn bloom_commit_model(staging_handle: f64) -> f64 {
|
|
2063
|
+
let staged = match bloom_shared::staging::take_model(staging_handle) {
|
|
2064
|
+
Some(s) => s,
|
|
2065
|
+
None => return 0.0,
|
|
2066
|
+
};
|
|
2067
|
+
let eng = engine();
|
|
2068
|
+
let mut tex_map: Vec<u32> = Vec::with_capacity(staged.textures.len());
|
|
2069
|
+
for tex in &staged.textures {
|
|
2070
|
+
tex_map.push(eng.renderer.register_texture(tex.width, tex.height, &tex.data));
|
|
2071
|
+
}
|
|
2072
|
+
let mut model = staged.model;
|
|
2073
|
+
for mesh in &mut model.meshes {
|
|
2074
|
+
if let Some(ref mut idx) = mesh.texture_idx {
|
|
2075
|
+
let staged_idx = *idx as usize;
|
|
2076
|
+
if staged_idx > 0 && staged_idx <= tex_map.len() {
|
|
2077
|
+
*idx = tex_map[staged_idx - 1];
|
|
2078
|
+
} else {
|
|
2079
|
+
mesh.texture_idx = None;
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
eng.models.models.alloc(model)
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
#[no_mangle]
|
|
2087
|
+
pub extern "C" fn bloom_commit_sound(staging_handle: f64) -> f64 {
|
|
2088
|
+
match bloom_shared::staging::take_sound(staging_handle) {
|
|
2089
|
+
Some(sd) => engine().audio.load_sound(sd),
|
|
2090
|
+
None => 0.0,
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
#[no_mangle]
|
|
2095
|
+
pub extern "C" fn bloom_commit_music(staging_handle: f64) -> f64 {
|
|
2096
|
+
match bloom_shared::staging::take_sound(staging_handle) {
|
|
2097
|
+
Some(sd) => engine().audio.load_music(sd),
|
|
2098
|
+
None => 0.0,
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
fn pollster_block_on<F: std::future::Future>(future: F) -> F::Output {
|
|
2103
|
+
use std::task::{Context, Poll, Wake, Waker};
|
|
2104
|
+
use std::pin::Pin;
|
|
2105
|
+
use std::sync::Arc;
|
|
2106
|
+
struct NoopWaker;
|
|
2107
|
+
impl Wake for NoopWaker { fn wake(self: Arc<Self>) {} }
|
|
2108
|
+
let waker = Waker::from(Arc::new(NoopWaker));
|
|
2109
|
+
let mut cx = Context::from_waker(&waker);
|
|
2110
|
+
let mut future = unsafe { Pin::new_unchecked(Box::new(future)) };
|
|
2111
|
+
loop {
|
|
2112
|
+
match future.as_mut().poll(&mut cx) {
|
|
2113
|
+
Poll::Ready(result) => return result,
|
|
2114
|
+
Poll::Pending => std::thread::yield_now(),
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
|
|
2121
|
+
// Q6: Multi-hit picking
|
|
2122
|
+
static mut LAST_PICK_ALL: Vec<bloom_shared::picking::PickResult> = Vec::new();
|
|
2123
|
+
|
|
2124
|
+
#[no_mangle]
|
|
2125
|
+
pub extern "C" fn bloom_scene_pick_all(screen_x: f64, screen_y: f64, max_results: f64) -> f64 {
|
|
2126
|
+
let eng = engine();
|
|
2127
|
+
let inv_vp = eng.renderer.inverse_vp_matrix();
|
|
2128
|
+
let cam_pos = eng.renderer.camera_pos();
|
|
2129
|
+
let w = eng.renderer.width() as f32;
|
|
2130
|
+
let h = eng.renderer.height() as f32;
|
|
2131
|
+
let (origin, direction) = bloom_shared::picking::screen_to_ray(
|
|
2132
|
+
screen_x as f32, screen_y as f32, w, h, &inv_vp, &cam_pos,
|
|
2133
|
+
);
|
|
2134
|
+
let results = bloom_shared::picking::raycast_scene_all(&eng.scene, &origin, &direction, max_results as usize);
|
|
2135
|
+
let count = results.len();
|
|
2136
|
+
unsafe { LAST_PICK_ALL = results; }
|
|
2137
|
+
count as f64
|
|
2138
|
+
}
|
|
2139
|
+
#[no_mangle]
|
|
2140
|
+
pub extern "C" fn bloom_pick_all_handle(index: f64) -> f64 {
|
|
2141
|
+
let i = index as usize;
|
|
2142
|
+
unsafe { LAST_PICK_ALL.get(i).map(|r| r.handle).unwrap_or(0.0) }
|
|
2143
|
+
}
|
|
2144
|
+
#[no_mangle]
|
|
2145
|
+
pub extern "C" fn bloom_pick_all_distance(index: f64) -> f64 {
|
|
2146
|
+
let i = index as usize;
|
|
2147
|
+
unsafe { LAST_PICK_ALL.get(i).map(|r| r.distance as f64).unwrap_or(0.0) }
|
|
2148
|
+
}
|
|
2149
|
+
// ============================================================
|
|
2150
|
+
|
|
2151
|
+
// ============================================================
|
|
2152
|
+
// Render quality toggles (individual + preset) — ticket 011
|
|
2153
|
+
// Mirror of the macOS FFI surface added in commit 95da6af; previously
|
|
2154
|
+
// macOS-only, now exposed on every native platform so non-macOS builds
|
|
2155
|
+
// don't fail at runtime (missing symbol) when the TS API invokes them.
|
|
2156
|
+
// ============================================================
|
|
2157
|
+
|
|
2158
|
+
#[no_mangle]
|
|
2159
|
+
pub extern "C" fn bloom_set_quality_preset(preset: f64) {
|
|
2160
|
+
engine().renderer.apply_quality_preset(preset as u32);
|
|
2161
|
+
}
|
|
2162
|
+
#[no_mangle]
|
|
2163
|
+
pub extern "C" fn bloom_set_shadows_enabled(on: f64) {
|
|
2164
|
+
engine().renderer.set_shadows_enabled(on != 0.0);
|
|
2165
|
+
}
|
|
2166
|
+
#[no_mangle]
|
|
2167
|
+
pub extern "C" fn bloom_set_shadows_always_fresh(on: f64) {
|
|
2168
|
+
engine().renderer.set_shadows_always_fresh(on != 0.0);
|
|
2169
|
+
}
|
|
2170
|
+
#[no_mangle]
|
|
2171
|
+
pub extern "C" fn bloom_set_bloom_enabled(on: f64) {
|
|
2172
|
+
engine().renderer.set_bloom_enabled(on != 0.0);
|
|
2173
|
+
}
|
|
2174
|
+
#[no_mangle]
|
|
2175
|
+
pub extern "C" fn bloom_set_ssao_enabled(on: f64) {
|
|
2176
|
+
engine().renderer.set_ssao_enabled(on != 0.0);
|
|
2177
|
+
}
|
|
2178
|
+
#[no_mangle]
|
|
2179
|
+
pub extern "C" fn bloom_set_ssao_intensity(value: f64) {
|
|
2180
|
+
engine().renderer.set_ssao_strength(value as f32);
|
|
2181
|
+
}
|
|
2182
|
+
#[no_mangle]
|
|
2183
|
+
pub extern "C" fn bloom_set_ssao_radius(world_radius: f64) {
|
|
2184
|
+
engine().renderer.set_ssao_radius(world_radius as f32);
|
|
2185
|
+
}
|
|
2186
|
+
#[no_mangle]
|
|
2187
|
+
pub extern "C" fn bloom_set_wind(dir_x: f64, dir_z: f64, amplitude: f64, frequency: f64) {
|
|
2188
|
+
engine().renderer.set_wind(dir_x as f32, dir_z as f32, amplitude as f32, frequency as f32);
|
|
2189
|
+
}
|
|
2190
|
+
#[no_mangle]
|
|
2191
|
+
pub extern "C" fn bloom_set_ssr_enabled(on: f64) {
|
|
2192
|
+
engine().renderer.set_ssr_enabled(on != 0.0);
|
|
2193
|
+
}
|
|
2194
|
+
#[no_mangle]
|
|
2195
|
+
pub extern "C" fn bloom_set_motion_blur_enabled(on: f64) {
|
|
2196
|
+
engine().renderer.set_motion_blur_enabled(on != 0.0);
|
|
2197
|
+
}
|
|
2198
|
+
#[no_mangle]
|
|
2199
|
+
pub extern "C" fn bloom_set_sss_enabled(on: f64) {
|
|
2200
|
+
engine().renderer.set_sss_enabled(on != 0.0);
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
// ============================================================
|
|
2204
|
+
// Profiler — CPU phase timings (always available) + GPU timestamps
|
|
2205
|
+
// (when the adapter supports TIMESTAMP_QUERY). Disabled by default.
|
|
2206
|
+
// ============================================================
|
|
2207
|
+
|
|
2208
|
+
#[no_mangle]
|
|
2209
|
+
pub extern "C" fn bloom_set_profiler_enabled(on: f64) {
|
|
2210
|
+
engine().profiler.set_enabled(on != 0.0);
|
|
2211
|
+
}
|
|
2212
|
+
#[no_mangle]
|
|
2213
|
+
pub extern "C" fn bloom_get_profiler_frame_cpu_us() -> f64 {
|
|
2214
|
+
engine().profiler.avg_frame_cpu_us()
|
|
2215
|
+
}
|
|
2216
|
+
#[no_mangle]
|
|
2217
|
+
pub extern "C" fn bloom_get_profiler_frame_gpu_us() -> f64 {
|
|
2218
|
+
engine().profiler.avg_frame_gpu_us()
|
|
2219
|
+
}
|
|
2220
|
+
#[no_mangle]
|
|
2221
|
+
pub extern "C" fn bloom_print_profiler_summary() {
|
|
2222
|
+
print!("{}", engine().profiler.summary());
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
// ============================================================
|
|
2226
|
+
// Physics (Jolt 5.x) — FFI surface generated from shared macro
|
|
2227
|
+
// ============================================================
|
|
2228
|
+
|
|
2229
|
+
#[cfg(feature = "jolt")]
|
|
2230
|
+
#[inline]
|
|
2231
|
+
fn bloom_jolt_ffi_physics() -> &'static mut bloom_shared::physics_jolt::JoltPhysics {
|
|
2232
|
+
&mut engine().jolt
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
#[cfg(feature = "jolt")]
|
|
2236
|
+
bloom_shared::define_physics_ffi!();
|