@aura3d/engine 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/README.md +331 -16
  2. package/dist/animation/AnimationClipEvents.d.ts +57 -0
  3. package/dist/animation/AnimationClipEvents.d.ts.map +1 -0
  4. package/dist/animation/AnimationClipEvents.js +171 -0
  5. package/dist/animation/AnimationClipEvents.js.map +1 -0
  6. package/dist/animation/AnimationClipRegistry.d.ts +76 -0
  7. package/dist/animation/AnimationClipRegistry.d.ts.map +1 -0
  8. package/dist/animation/AnimationClipRegistry.js +130 -0
  9. package/dist/animation/AnimationClipRegistry.js.map +1 -0
  10. package/dist/animation/AnimationController.d.ts +168 -0
  11. package/dist/animation/AnimationController.d.ts.map +1 -0
  12. package/dist/animation/AnimationController.js +619 -0
  13. package/dist/animation/AnimationController.js.map +1 -0
  14. package/dist/animation/HumanoidRetargeting.d.ts +76 -0
  15. package/dist/animation/HumanoidRetargeting.d.ts.map +1 -0
  16. package/dist/animation/HumanoidRetargeting.js +331 -0
  17. package/dist/animation/HumanoidRetargeting.js.map +1 -0
  18. package/dist/animation/browser-index.d.ts +18 -0
  19. package/dist/animation/browser-index.d.ts.map +1 -1
  20. package/dist/animation/browser-index.js +13 -0
  21. package/dist/animation/browser-index.js.map +1 -1
  22. package/dist/animation/index.d.ts +16 -1
  23. package/dist/animation/index.d.ts.map +1 -1
  24. package/dist/animation/index.js +11 -1
  25. package/dist/animation/index.js.map +1 -1
  26. package/dist/animation/threejs-compatibility/AnimationDiagnostics.d.ts.map +1 -1
  27. package/dist/animation/threejs-compatibility/AnimationDiagnostics.js +3 -5
  28. package/dist/animation/threejs-compatibility/AnimationDiagnostics.js.map +1 -1
  29. package/dist/assets/GLTFAnimationRuntime.js +1 -1
  30. package/dist/assets/GLTFLoader.js +1 -1
  31. package/dist/aura3d-cli/cli.js +194 -8
  32. package/dist/aura3d-cli/cli.js.map +1 -1
  33. package/dist/aura3d-cli/index.d.ts +280 -3
  34. package/dist/aura3d-cli/index.d.ts.map +1 -1
  35. package/dist/aura3d-cli/index.js +886 -4
  36. package/dist/aura3d-cli/index.js.map +1 -1
  37. package/dist/aura3d-cli/pull-bridge.d.ts +95 -0
  38. package/dist/aura3d-cli/pull-bridge.d.ts.map +1 -0
  39. package/dist/aura3d-cli/pull-bridge.js +247 -0
  40. package/dist/aura3d-cli/pull-bridge.js.map +1 -0
  41. package/dist/create-aura3d/index.d.ts +1 -1
  42. package/dist/create-aura3d/index.d.ts.map +1 -1
  43. package/dist/create-aura3d/index.js +9 -2
  44. package/dist/create-aura3d/index.js.map +1 -1
  45. package/dist/editor-runtime/ProjectSerializer.d.ts +74 -1
  46. package/dist/editor-runtime/ProjectSerializer.d.ts.map +1 -1
  47. package/dist/editor-runtime/ProjectSerializer.js +123 -6
  48. package/dist/editor-runtime/ProjectSerializer.js.map +1 -1
  49. package/dist/editor-runtime/TimelineModel.d.ts +18 -0
  50. package/dist/editor-runtime/TimelineModel.d.ts.map +1 -1
  51. package/dist/editor-runtime/TimelineModel.js +67 -3
  52. package/dist/editor-runtime/TimelineModel.js.map +1 -1
  53. package/dist/editor-runtime/TimelineRuntimeBridge.d.ts +98 -0
  54. package/dist/editor-runtime/TimelineRuntimeBridge.d.ts.map +1 -0
  55. package/dist/editor-runtime/TimelineRuntimeBridge.js +186 -0
  56. package/dist/editor-runtime/TimelineRuntimeBridge.js.map +1 -0
  57. package/dist/editor-runtime/index.d.ts +3 -1
  58. package/dist/editor-runtime/index.d.ts.map +1 -1
  59. package/dist/editor-runtime/index.js +1 -0
  60. package/dist/editor-runtime/index.js.map +1 -1
  61. package/dist/engine/agent-api/AnimationController.d.ts +607 -0
  62. package/dist/engine/agent-api/AnimationController.d.ts.map +1 -0
  63. package/dist/engine/agent-api/AnimationController.js +2192 -0
  64. package/dist/engine/agent-api/AnimationController.js.map +1 -0
  65. package/dist/engine/agent-api/AssetEvidence.d.ts +88 -0
  66. package/dist/engine/agent-api/AssetEvidence.d.ts.map +1 -0
  67. package/dist/engine/agent-api/AssetEvidence.js +157 -0
  68. package/dist/engine/agent-api/AssetEvidence.js.map +1 -0
  69. package/dist/engine/agent-api/AuraAppHandle.d.ts +55 -0
  70. package/dist/engine/agent-api/AuraAppHandle.d.ts.map +1 -0
  71. package/dist/engine/agent-api/AuraAppHandle.js +15 -0
  72. package/dist/engine/agent-api/AuraAppHandle.js.map +1 -0
  73. package/dist/engine/agent-api/AuraVoiceBridge.d.ts +96 -0
  74. package/dist/engine/agent-api/AuraVoiceBridge.d.ts.map +1 -0
  75. package/dist/engine/agent-api/AuraVoiceBridge.js +370 -0
  76. package/dist/engine/agent-api/AuraVoiceBridge.js.map +1 -0
  77. package/dist/engine/agent-api/CartoonDirector.d.ts +95 -0
  78. package/dist/engine/agent-api/CartoonDirector.d.ts.map +1 -0
  79. package/dist/engine/agent-api/CartoonDirector.js +342 -0
  80. package/dist/engine/agent-api/CartoonDirector.js.map +1 -0
  81. package/dist/engine/agent-api/CartoonPerformance.d.ts +149 -0
  82. package/dist/engine/agent-api/CartoonPerformance.d.ts.map +1 -0
  83. package/dist/engine/agent-api/CartoonPerformance.js +317 -0
  84. package/dist/engine/agent-api/CartoonPerformance.js.map +1 -0
  85. package/dist/engine/agent-api/CartoonRenderQueue.d.ts +132 -0
  86. package/dist/engine/agent-api/CartoonRenderQueue.d.ts.map +1 -0
  87. package/dist/engine/agent-api/CartoonRenderQueue.js +385 -0
  88. package/dist/engine/agent-api/CartoonRenderQueue.js.map +1 -0
  89. package/dist/engine/agent-api/CharacterAssembly.d.ts +126 -0
  90. package/dist/engine/agent-api/CharacterAssembly.d.ts.map +1 -0
  91. package/dist/engine/agent-api/CharacterAssembly.js +280 -0
  92. package/dist/engine/agent-api/CharacterAssembly.js.map +1 -0
  93. package/dist/engine/agent-api/DialoguePerformance.d.ts +150 -0
  94. package/dist/engine/agent-api/DialoguePerformance.d.ts.map +1 -0
  95. package/dist/engine/agent-api/DialoguePerformance.js +335 -0
  96. package/dist/engine/agent-api/DialoguePerformance.js.map +1 -0
  97. package/dist/engine/agent-api/FrameLoop.d.ts +70 -0
  98. package/dist/engine/agent-api/FrameLoop.d.ts.map +1 -0
  99. package/dist/engine/agent-api/FrameLoop.js +165 -0
  100. package/dist/engine/agent-api/FrameLoop.js.map +1 -0
  101. package/dist/engine/agent-api/GameAssetValidation.d.ts +279 -0
  102. package/dist/engine/agent-api/GameAssetValidation.d.ts.map +1 -0
  103. package/dist/engine/agent-api/GameAssetValidation.js +719 -0
  104. package/dist/engine/agent-api/GameAssetValidation.js.map +1 -0
  105. package/dist/engine/agent-api/GameEvidence.d.ts +148 -0
  106. package/dist/engine/agent-api/GameEvidence.d.ts.map +1 -0
  107. package/dist/engine/agent-api/GameEvidence.js +269 -0
  108. package/dist/engine/agent-api/GameEvidence.js.map +1 -0
  109. package/dist/engine/agent-api/GameRuntime.d.ts +931 -0
  110. package/dist/engine/agent-api/GameRuntime.d.ts.map +1 -0
  111. package/dist/engine/agent-api/GameRuntime.js +2229 -0
  112. package/dist/engine/agent-api/GameRuntime.js.map +1 -0
  113. package/dist/engine/agent-api/GameSceneBridge.d.ts +54 -0
  114. package/dist/engine/agent-api/GameSceneBridge.d.ts.map +1 -0
  115. package/dist/engine/agent-api/GameSceneBridge.js +110 -0
  116. package/dist/engine/agent-api/GameSceneBridge.js.map +1 -0
  117. package/dist/engine/agent-api/PromptAnimationContract.d.ts +278 -0
  118. package/dist/engine/agent-api/PromptAnimationContract.d.ts.map +1 -0
  119. package/dist/engine/agent-api/PromptAnimationContract.js +238 -0
  120. package/dist/engine/agent-api/PromptAnimationContract.js.map +1 -0
  121. package/dist/engine/agent-api/PromptAnimationEvidence.d.ts +183 -0
  122. package/dist/engine/agent-api/PromptAnimationEvidence.d.ts.map +1 -0
  123. package/dist/engine/agent-api/PromptAnimationEvidence.js +454 -0
  124. package/dist/engine/agent-api/PromptAnimationEvidence.js.map +1 -0
  125. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts +100 -0
  126. package/dist/engine/agent-api/RuntimeNodeHandle.d.ts.map +1 -0
  127. package/dist/engine/agent-api/RuntimeNodeHandle.js +36 -0
  128. package/dist/engine/agent-api/RuntimeNodeHandle.js.map +1 -0
  129. package/dist/engine/agent-api/ShotTimeline.d.ts +179 -0
  130. package/dist/engine/agent-api/ShotTimeline.d.ts.map +1 -0
  131. package/dist/engine/agent-api/ShotTimeline.js +264 -0
  132. package/dist/engine/agent-api/ShotTimeline.js.map +1 -0
  133. package/dist/engine/agent-api/VisemeController.d.ts +89 -0
  134. package/dist/engine/agent-api/VisemeController.d.ts.map +1 -0
  135. package/dist/engine/agent-api/VisemeController.js +207 -0
  136. package/dist/engine/agent-api/VisemeController.js.map +1 -0
  137. package/dist/engine/agent-api/game-kits/fighting.d.ts +123 -0
  138. package/dist/engine/agent-api/game-kits/fighting.d.ts.map +1 -0
  139. package/dist/engine/agent-api/game-kits/fighting.js +483 -0
  140. package/dist/engine/agent-api/game-kits/fighting.js.map +1 -0
  141. package/dist/engine/agent-api/game-kits/index.d.ts +15 -0
  142. package/dist/engine/agent-api/game-kits/index.d.ts.map +1 -0
  143. package/dist/engine/agent-api/game-kits/index.js +6 -0
  144. package/dist/engine/agent-api/game-kits/index.js.map +1 -0
  145. package/dist/engine/agent-api/humanoid-walk-runtime.d.ts +18 -81
  146. package/dist/engine/agent-api/humanoid-walk-runtime.d.ts.map +1 -1
  147. package/dist/engine/agent-api/humanoid-walk-runtime.js +4 -279
  148. package/dist/engine/agent-api/humanoid-walk-runtime.js.map +1 -1
  149. package/dist/engine/agent-api/index.d.ts +490 -4
  150. package/dist/engine/agent-api/index.d.ts.map +1 -1
  151. package/dist/engine/agent-api/index.js +759 -1802
  152. package/dist/engine/agent-api/index.js.map +1 -1
  153. package/dist/engine/agent-api/particle-fountain-runtime.d.ts +5 -80
  154. package/dist/engine/agent-api/particle-fountain-runtime.d.ts.map +1 -1
  155. package/dist/engine/agent-api/particle-fountain-runtime.js +7 -291
  156. package/dist/engine/agent-api/particle-fountain-runtime.js.map +1 -1
  157. package/dist/engine/agent-api/product-viewer-runtime.d.ts +17 -107
  158. package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
  159. package/dist/engine/agent-api/product-viewer-runtime.js +4 -330
  160. package/dist/engine/agent-api/product-viewer-runtime.js.map +1 -1
  161. package/dist/index.d.ts +1 -0
  162. package/dist/index.js +1 -0
  163. package/dist/physics/CollisionVolumes.d.ts +57 -0
  164. package/dist/physics/CollisionVolumes.d.ts.map +1 -0
  165. package/dist/physics/CollisionVolumes.js +159 -0
  166. package/dist/physics/CollisionVolumes.js.map +1 -0
  167. package/dist/physics/HitboxWorld.d.ts +229 -0
  168. package/dist/physics/HitboxWorld.d.ts.map +1 -0
  169. package/dist/physics/HitboxWorld.js +640 -0
  170. package/dist/physics/HitboxWorld.js.map +1 -0
  171. package/dist/physics/KinematicBody.d.ts +157 -0
  172. package/dist/physics/KinematicBody.d.ts.map +1 -0
  173. package/dist/physics/KinematicBody.js +405 -0
  174. package/dist/physics/KinematicBody.js.map +1 -0
  175. package/dist/physics/KinematicWorld.d.ts +58 -0
  176. package/dist/physics/KinematicWorld.d.ts.map +1 -0
  177. package/dist/physics/KinematicWorld.js +246 -0
  178. package/dist/physics/KinematicWorld.js.map +1 -0
  179. package/dist/physics/index.d.ts +4 -0
  180. package/dist/physics/index.d.ts.map +1 -1
  181. package/dist/physics/index.js +4 -0
  182. package/dist/physics/index.js.map +1 -1
  183. package/dist/rendering/ForwardPass.js +2 -2
  184. package/dist/rendering/ShaderLibrary.js +2 -2
  185. package/dist/rendering/SkinnedLitMaterial.js +3 -3
  186. package/dist/rendering/SkinnedUnlitMaterial.js +3 -3
  187. package/dist/scene/Renderable.js +2 -2
  188. package/dist/scripting/VisualGraph.d.ts +2 -1
  189. package/dist/scripting/VisualGraph.d.ts.map +1 -1
  190. package/dist/scripting/VisualGraph.js +118 -1
  191. package/dist/scripting/VisualGraph.js.map +1 -1
  192. package/dist/scripting/VisualGraphContext.d.ts +123 -0
  193. package/dist/scripting/VisualGraphContext.d.ts.map +1 -0
  194. package/dist/scripting/VisualGraphContext.js +2 -0
  195. package/dist/scripting/VisualGraphContext.js.map +1 -0
  196. package/dist/scripting/VisualGraphExecutor.d.ts +6 -1
  197. package/dist/scripting/VisualGraphExecutor.d.ts.map +1 -1
  198. package/dist/scripting/VisualGraphExecutor.js +364 -7
  199. package/dist/scripting/VisualGraphExecutor.js.map +1 -1
  200. package/dist/scripting/VisualNodeCatalog.d.ts +1 -1
  201. package/dist/scripting/VisualNodeCatalog.d.ts.map +1 -1
  202. package/dist/scripting/VisualNodeCatalog.js +61 -1
  203. package/dist/scripting/VisualNodeCatalog.js.map +1 -1
  204. package/dist/scripting/index.d.ts +1 -0
  205. package/dist/scripting/index.d.ts.map +1 -1
  206. package/dist/scripting/index.js.map +1 -1
  207. package/package.json +193 -121
  208. package/templates/product-viewer/src/main.ts +1 -0
  209. package/dist/three-compat/ThreeApiInventory.d.ts +0 -18
  210. package/dist/three-compat/ThreeApiInventory.d.ts.map +0 -1
  211. package/dist/three-compat/ThreeApiInventory.js +0 -99
  212. package/dist/three-compat/ThreeApiInventory.js.map +0 -1
  213. package/dist/three-compat/ThreeCompatibilityMatrix.d.ts +0 -30
  214. package/dist/three-compat/ThreeCompatibilityMatrix.d.ts.map +0 -1
  215. package/dist/three-compat/ThreeCompatibilityMatrix.js +0 -69
  216. package/dist/three-compat/ThreeCompatibilityMatrix.js.map +0 -1
  217. package/dist/three-compat/animation/index.d.ts +0 -3
  218. package/dist/three-compat/animation/index.d.ts.map +0 -1
  219. package/dist/three-compat/animation/index.js +0 -2
  220. package/dist/three-compat/animation/index.js.map +0 -1
  221. package/dist/three-compat/cameras/index.d.ts +0 -24
  222. package/dist/three-compat/cameras/index.d.ts.map +0 -1
  223. package/dist/three-compat/cameras/index.js +0 -44
  224. package/dist/three-compat/cameras/index.js.map +0 -1
  225. package/dist/three-compat/controls/index.d.ts +0 -3
  226. package/dist/three-compat/controls/index.d.ts.map +0 -1
  227. package/dist/three-compat/controls/index.js +0 -2
  228. package/dist/three-compat/controls/index.js.map +0 -1
  229. package/dist/three-compat/core/Object3DCompat.d.ts +0 -62
  230. package/dist/three-compat/core/Object3DCompat.d.ts.map +0 -1
  231. package/dist/three-compat/core/Object3DCompat.js +0 -112
  232. package/dist/three-compat/core/Object3DCompat.js.map +0 -1
  233. package/dist/three-compat/core/RaycasterCompat.d.ts +0 -18
  234. package/dist/three-compat/core/RaycasterCompat.d.ts.map +0 -1
  235. package/dist/three-compat/core/RaycasterCompat.js +0 -28
  236. package/dist/three-compat/core/RaycasterCompat.js.map +0 -1
  237. package/dist/three-compat/core/SceneCompat.d.ts +0 -8
  238. package/dist/three-compat/core/SceneCompat.d.ts.map +0 -1
  239. package/dist/three-compat/core/SceneCompat.js +0 -8
  240. package/dist/three-compat/core/SceneCompat.js.map +0 -1
  241. package/dist/three-compat/geometries/index.d.ts +0 -67
  242. package/dist/three-compat/geometries/index.d.ts.map +0 -1
  243. package/dist/three-compat/geometries/index.js +0 -114
  244. package/dist/three-compat/geometries/index.js.map +0 -1
  245. package/dist/three-compat/helpers/index.d.ts +0 -40
  246. package/dist/three-compat/helpers/index.d.ts.map +0 -1
  247. package/dist/three-compat/helpers/index.js +0 -129
  248. package/dist/three-compat/helpers/index.js.map +0 -1
  249. package/dist/three-compat/index.d.ts +0 -32
  250. package/dist/three-compat/index.d.ts.map +0 -1
  251. package/dist/three-compat/index.js +0 -22
  252. package/dist/three-compat/index.js.map +0 -1
  253. package/dist/three-compat/lights/index.d.ts +0 -35
  254. package/dist/three-compat/lights/index.d.ts.map +0 -1
  255. package/dist/three-compat/lights/index.js +0 -39
  256. package/dist/three-compat/lights/index.js.map +0 -1
  257. package/dist/three-compat/loaders/index.d.ts +0 -54
  258. package/dist/three-compat/loaders/index.d.ts.map +0 -1
  259. package/dist/three-compat/loaders/index.js +0 -79
  260. package/dist/three-compat/loaders/index.js.map +0 -1
  261. package/dist/three-compat/materials/index.d.ts +0 -70
  262. package/dist/three-compat/materials/index.d.ts.map +0 -1
  263. package/dist/three-compat/materials/index.js +0 -85
  264. package/dist/three-compat/materials/index.js.map +0 -1
  265. package/dist/three-compat/math/index.d.ts +0 -34
  266. package/dist/three-compat/math/index.d.ts.map +0 -1
  267. package/dist/three-compat/math/index.js +0 -90
  268. package/dist/three-compat/math/index.js.map +0 -1
  269. package/dist/three-compat/migration/CompatibilityWarnings.d.ts +0 -6
  270. package/dist/three-compat/migration/CompatibilityWarnings.d.ts.map +0 -1
  271. package/dist/three-compat/migration/CompatibilityWarnings.js +0 -8
  272. package/dist/three-compat/migration/CompatibilityWarnings.js.map +0 -1
  273. package/dist/three-compat/migration/ImportMap.d.ts +0 -2
  274. package/dist/three-compat/migration/ImportMap.d.ts.map +0 -1
  275. package/dist/three-compat/migration/ImportMap.js +0 -10
  276. package/dist/three-compat/migration/ImportMap.js.map +0 -1
  277. package/dist/three-compat/migration/ThreeToA3DAdapter.d.ts +0 -8
  278. package/dist/three-compat/migration/ThreeToA3DAdapter.d.ts.map +0 -1
  279. package/dist/three-compat/migration/ThreeToA3DAdapter.js +0 -20
  280. package/dist/three-compat/migration/ThreeToA3DAdapter.js.map +0 -1
  281. package/dist/three-compat/postprocessing/index.d.ts +0 -2
  282. package/dist/three-compat/postprocessing/index.d.ts.map +0 -1
  283. package/dist/three-compat/postprocessing/index.js +0 -2
  284. package/dist/three-compat/postprocessing/index.js.map +0 -1
  285. package/dist/three-compat/render-targets/index.d.ts +0 -17
  286. package/dist/three-compat/render-targets/index.d.ts.map +0 -1
  287. package/dist/three-compat/render-targets/index.js +0 -29
  288. package/dist/three-compat/render-targets/index.js.map +0 -1
  289. package/dist/three-compat/shaders/index.d.ts +0 -3
  290. package/dist/three-compat/shaders/index.d.ts.map +0 -1
  291. package/dist/three-compat/shaders/index.js +0 -3
  292. package/dist/three-compat/shaders/index.js.map +0 -1
  293. package/dist/three-compat/textures/index.d.ts +0 -19
  294. package/dist/three-compat/textures/index.d.ts.map +0 -1
  295. package/dist/three-compat/textures/index.js +0 -24
  296. package/dist/three-compat/textures/index.js.map +0 -1
@@ -0,0 +1,719 @@
1
+ export const gameAssetValidationContractVersion = "aura-game-asset-validation/1.0.5";
2
+ export const fightingGameAnimationRoles = [
3
+ "idle",
4
+ "walk-forward",
5
+ "walk-back",
6
+ "jump",
7
+ "land",
8
+ "dash",
9
+ "guard",
10
+ "light",
11
+ "heavy",
12
+ "special",
13
+ "hit",
14
+ "stun",
15
+ "knockdown",
16
+ "win",
17
+ "lose"
18
+ ];
19
+ export const quaterniusGameReadyFighterValidationContract = {
20
+ kind: "aura3d-quaternius-game-ready-fighter-validation-contract",
21
+ contractId: gameAssetValidationContractVersion,
22
+ sourceFamily: "quaternius",
23
+ intendedUse: "fighter",
24
+ requiredChecks: [
25
+ "typed Aura model asset reference",
26
+ "Quaternius-derived provenance",
27
+ "GLB or glTF model format",
28
+ "browser-sized payload",
29
+ "humanoid skeleton and retargetable rig metadata",
30
+ "grounded pivot and fighting-game bounds",
31
+ "forward-facing orientation before runtime mirroring",
32
+ "readable visible materials",
33
+ "texture dimension budget",
34
+ "thumbnail or first-frame capture path",
35
+ "named fighting animation clips with non-empty tracks",
36
+ "clip events for attack active frames when events are required"
37
+ ],
38
+ requiredAnimationRoles: fightingGameAnimationRoles,
39
+ evidenceBoundary: "This is a source validation contract. A Quaternius-derived fighter is not evidence-ready until validate-game output, typed asset metadata, and retained runtime/browser evidence are archived."
40
+ };
41
+ export function defineGameAssetReadinessManifest(manifest) {
42
+ return manifest;
43
+ }
44
+ export function createGameAssetReadinessManifest(asset, options = {}) {
45
+ const metadata = asset.metadata;
46
+ const file = {
47
+ url: options.file?.url ?? asset.url,
48
+ format: options.file?.format ?? asset.format,
49
+ sizeBytes: options.file?.sizeBytes ?? asset.sizeBytes,
50
+ hash: options.file?.hash ?? asset.hash
51
+ };
52
+ const provenance = options.provenance ?? provenanceFromAsset(asset);
53
+ const thumbnail = options.thumbnail ?? (metadata?.thumbnailUrl ? { url: metadata.thumbnailUrl } : undefined);
54
+ return {
55
+ kind: "aura-game-asset-readiness-manifest",
56
+ contractId: gameAssetValidationContractVersion,
57
+ asset,
58
+ displayName: options.displayName,
59
+ file,
60
+ provenance,
61
+ thumbnail,
62
+ bounds: normalizeGameAssetBounds(options.bounds ?? asset.bounds, "asset-metadata"),
63
+ orientation: options.orientation,
64
+ skeleton: options.skeleton,
65
+ animations: normalizeAnimationClips(options.animations ?? metadata?.animations),
66
+ morphTargets: options.morphTargets,
67
+ materials: normalizeMaterials(options.materials ?? metadata?.materials),
68
+ textures: normalizeTextures(options.textures ?? metadata?.textures),
69
+ intendedUse: options.intendedUse,
70
+ notes: options.notes,
71
+ generatedAt: options.generatedAt
72
+ };
73
+ }
74
+ export function validateGameAssetReadiness(manifest, policy = {}) {
75
+ const checks = [];
76
+ const issues = [];
77
+ const assetId = manifest.asset.id;
78
+ pushCheck(checkTypedAsset(manifest), checks, issues);
79
+ pushCheck(checkModelFormat(manifest), checks, issues);
80
+ pushCheck(checkFileSize(manifest, policy), checks, issues);
81
+ for (const check of evaluateGameAssetBounds(manifest, policy.bounds, policy.requireBounds))
82
+ pushCheck(check, checks, issues);
83
+ for (const check of evaluateGameAssetOrientation(manifest, policy.orientation, policy.requireOrientation)) {
84
+ pushCheck(check, checks, issues);
85
+ }
86
+ for (const check of evaluateGameAssetAnimationClips(manifest, policy.animation))
87
+ pushCheck(check, checks, issues);
88
+ pushCheck(checkSkeleton(manifest, policy.requireSkeleton), checks, issues);
89
+ pushCheck(checkMaterials(manifest, policy.requireReadableMaterials), checks, issues);
90
+ for (const check of checkTextures(manifest, policy.maxTextureDimension))
91
+ pushCheck(check, checks, issues);
92
+ pushCheck(checkThumbnail(manifest, policy.requireThumbnail), checks, issues);
93
+ pushCheck(checkProvenance(manifest, policy.requireProvenance), checks, issues);
94
+ pushCheck(checkIntendedUse(manifest, policy.requireIntendedUse), checks, issues);
95
+ const errors = issues.filter((issue) => issue.severity === "error").length;
96
+ const warnings = issues.filter((issue) => issue.severity === "warning").length;
97
+ return {
98
+ kind: "aura-game-asset-validation-report",
99
+ contractId: gameAssetValidationContractVersion,
100
+ asset: manifest.asset,
101
+ assetId,
102
+ manifest,
103
+ ready: errors === 0,
104
+ summary: {
105
+ status: errors > 0 ? "fail" : warnings > 0 ? "warn" : "pass",
106
+ checks: checks.length,
107
+ errors,
108
+ warnings,
109
+ animationClips: manifest.animations?.length ?? 0,
110
+ materials: manifest.materials?.length ?? 0,
111
+ textures: manifest.textures?.length ?? 0
112
+ },
113
+ checks,
114
+ issues
115
+ };
116
+ }
117
+ export function createQuaterniusGameReadyFighterValidationPolicy(overrides = {}) {
118
+ return {
119
+ maxFileSizeBytes: overrides.maxFileSizeBytes ?? 50 * 1024 * 1024,
120
+ requireFileSize: overrides.requireFileSize ?? true,
121
+ requireBounds: overrides.requireBounds ?? true,
122
+ requireOrientation: overrides.requireOrientation ?? true,
123
+ requireSkeleton: overrides.requireSkeleton ?? true,
124
+ requireThumbnail: overrides.requireThumbnail ?? true,
125
+ requireProvenance: overrides.requireProvenance ?? true,
126
+ requireIntendedUse: overrides.requireIntendedUse ?? true,
127
+ requireReadableMaterials: overrides.requireReadableMaterials ?? true,
128
+ maxTextureDimension: overrides.maxTextureDimension ?? 4096,
129
+ bounds: {
130
+ minWidth: 0.2,
131
+ maxWidth: 4,
132
+ minHeight: 0.6,
133
+ maxHeight: 4,
134
+ minDepth: 0.1,
135
+ maxDepth: 4,
136
+ maxDimension: 4,
137
+ maxOriginOffset: 0.5,
138
+ requireGroundedPivot: true,
139
+ groundTolerance: 0.08,
140
+ ...overrides.bounds
141
+ },
142
+ orientation: {
143
+ upAxis: "y",
144
+ forwardAxis: "z",
145
+ pivot: ["feet", "grounded"],
146
+ minUnitScale: 0.001,
147
+ maxUnitScale: 1000,
148
+ ...overrides.orientation
149
+ },
150
+ animation: {
151
+ requireNonEmptyClips: true,
152
+ minimumDuration: 1 / 30,
153
+ requiredClips: fightingGameAnimationRoles,
154
+ ...overrides.animation
155
+ }
156
+ };
157
+ }
158
+ export function validateQuaterniusGameReadyFighterAsset(manifest, policy = {}) {
159
+ const base = validateGameAssetReadiness(manifest, createQuaterniusGameReadyFighterValidationPolicy(policy));
160
+ const quaterniusCheck = checkQuaterniusProvenance(manifest);
161
+ const checks = [...base.checks, quaterniusCheck];
162
+ const issues = [...base.issues];
163
+ if (quaterniusCheck.status === "fail") {
164
+ issues.push(createGameAssetValidationIssue("error", quaterniusCheck.id, quaterniusCheck.message, { assetId: quaterniusCheck.assetId }));
165
+ }
166
+ else if (quaterniusCheck.status === "warn" || quaterniusCheck.status === "missing") {
167
+ issues.push(createGameAssetValidationIssue("warning", quaterniusCheck.id, quaterniusCheck.message, { assetId: quaterniusCheck.assetId }));
168
+ }
169
+ const errors = issues.filter((issue) => issue.severity === "error").length;
170
+ const warnings = issues.filter((issue) => issue.severity === "warning").length;
171
+ return {
172
+ ...base,
173
+ ready: errors === 0,
174
+ summary: {
175
+ ...base.summary,
176
+ status: errors > 0 ? "fail" : warnings > 0 ? "warn" : "pass",
177
+ checks: checks.length,
178
+ errors,
179
+ warnings
180
+ },
181
+ checks,
182
+ issues
183
+ };
184
+ }
185
+ export function evaluateGameAssetBounds(manifest, policy = {}, required = false) {
186
+ const bounds = manifest.bounds;
187
+ if (!bounds) {
188
+ return [
189
+ {
190
+ id: "bounds",
191
+ status: required ? "fail" : "missing",
192
+ assetId: manifest.asset.id,
193
+ message: required
194
+ ? "Asset bounds are required for game readiness."
195
+ : "Asset bounds are missing; scale, pivot, and camera framing cannot be proven."
196
+ }
197
+ ];
198
+ }
199
+ const checks = [];
200
+ const [width, height, depth] = bounds.size;
201
+ const maxDimension = Math.max(width, height, depth);
202
+ const originOffset = Math.hypot(bounds.center[0], bounds.center[2]);
203
+ const groundTolerance = policy.groundTolerance ?? 0.08;
204
+ const minY = bounds.min?.[1];
205
+ checks.push(rangeCheck("bounds.width", width, policy.minWidth, policy.maxWidth, manifest.asset.id, "width"));
206
+ checks.push(rangeCheck("bounds.height", height, policy.minHeight, policy.maxHeight, manifest.asset.id, "height"));
207
+ checks.push(rangeCheck("bounds.depth", depth, policy.minDepth, policy.maxDepth, manifest.asset.id, "depth"));
208
+ if (policy.maxDimension !== undefined) {
209
+ checks.push(maxCheck("bounds.max-dimension", maxDimension, policy.maxDimension, manifest.asset.id, "largest asset dimension"));
210
+ }
211
+ if (policy.maxOriginOffset !== undefined) {
212
+ checks.push(maxCheck("bounds.origin-offset", originOffset, policy.maxOriginOffset, manifest.asset.id, "horizontal origin offset"));
213
+ }
214
+ if (policy.requireGroundedPivot) {
215
+ checks.push({
216
+ id: "bounds.grounded-pivot",
217
+ status: minY === undefined ? "missing" : Math.abs(minY) <= groundTolerance ? "pass" : "fail",
218
+ assetId: manifest.asset.id,
219
+ message: minY === undefined
220
+ ? "Bounds min.y is missing, so grounded pivot cannot be proven."
221
+ : Math.abs(minY) <= groundTolerance
222
+ ? "Asset pivot is close to the ground plane."
223
+ : `Asset appears offset from the ground plane by ${round(minY)}m.`,
224
+ metrics: minY === undefined ? undefined : { minY: round(minY), tolerance: groundTolerance }
225
+ });
226
+ }
227
+ return checks;
228
+ }
229
+ export function evaluateGameAssetOrientation(manifest, policy = {}, required = false) {
230
+ const orientation = manifest.orientation;
231
+ if (!orientation) {
232
+ return [
233
+ {
234
+ id: "orientation",
235
+ status: required ? "fail" : "missing",
236
+ assetId: manifest.asset.id,
237
+ message: required
238
+ ? "Asset orientation is required for game readiness."
239
+ : "Asset orientation is missing; facing direction and up axis cannot be proven."
240
+ }
241
+ ];
242
+ }
243
+ const checks = [];
244
+ const expectedUp = policy.upAxis ?? "y";
245
+ const expectedForward = toAxisList(policy.forwardAxis ?? ["z", "-z"]);
246
+ const expectedPivots = toPivotList(policy.pivot ?? ["feet", "grounded", "center"]);
247
+ checks.push({
248
+ id: "orientation.up-axis",
249
+ status: orientation.upAxis === expectedUp ? "pass" : "fail",
250
+ assetId: manifest.asset.id,
251
+ message: orientation.upAxis === expectedUp
252
+ ? `Asset up axis is ${expectedUp}.`
253
+ : `Asset up axis is ${orientation.upAxis}; expected ${expectedUp}.`
254
+ });
255
+ checks.push({
256
+ id: "orientation.forward-axis",
257
+ status: expectedForward.includes(orientation.forwardAxis) ? "pass" : "fail",
258
+ assetId: manifest.asset.id,
259
+ message: expectedForward.includes(orientation.forwardAxis)
260
+ ? `Asset forward axis is ${orientation.forwardAxis}.`
261
+ : `Asset forward axis is ${orientation.forwardAxis}; expected one of ${expectedForward.join(", ")}.`
262
+ });
263
+ if (orientation.pivot) {
264
+ checks.push({
265
+ id: "orientation.pivot",
266
+ status: expectedPivots.includes(orientation.pivot) ? "pass" : "fail",
267
+ assetId: manifest.asset.id,
268
+ message: expectedPivots.includes(orientation.pivot)
269
+ ? `Asset pivot is ${orientation.pivot}.`
270
+ : `Asset pivot is ${orientation.pivot}; expected one of ${expectedPivots.join(", ")}.`
271
+ });
272
+ }
273
+ if (orientation.unitScale !== undefined) {
274
+ const minScale = policy.minUnitScale ?? 0.001;
275
+ const maxScale = policy.maxUnitScale ?? 1000;
276
+ checks.push(rangeCheck("orientation.unit-scale", orientation.unitScale, minScale, maxScale, manifest.asset.id, "unit scale"));
277
+ }
278
+ return checks;
279
+ }
280
+ export function evaluateGameAssetAnimationClips(manifest, policy = {}) {
281
+ const clips = manifest.animations ?? [];
282
+ const checks = [];
283
+ const minimumDuration = policy.minimumDuration ?? 1 / 30;
284
+ const requireNonEmpty = policy.requireNonEmptyClips ?? true;
285
+ if (requireNonEmpty) {
286
+ checks.push({
287
+ id: "animation.clips-present",
288
+ status: clips.length > 0 ? "pass" : "missing",
289
+ assetId: manifest.asset.id,
290
+ message: clips.length > 0 ? `Asset declares ${clips.length} animation clips.` : "Asset declares no animation clips."
291
+ });
292
+ }
293
+ for (const clip of clips) {
294
+ const duration = clip.duration ?? 0;
295
+ checks.push({
296
+ id: `animation.clip.${clip.name}.duration`,
297
+ status: duration > 0 && duration >= minimumDuration ? "pass" : "fail",
298
+ assetId: manifest.asset.id,
299
+ message: duration > 0 && duration >= minimumDuration
300
+ ? `Animation clip "${clip.name}" has duration ${round(duration)}s.`
301
+ : `Animation clip "${clip.name}" is empty or shorter than ${round(minimumDuration)}s.`,
302
+ metrics: { duration: round(duration), minimumDuration: round(minimumDuration) }
303
+ });
304
+ }
305
+ for (const requirement of policy.requiredClips ?? []) {
306
+ const required = normalizeClipRequirement(requirement);
307
+ const clip = findClip(clips, required);
308
+ const label = required.role ?? required.name ?? "clip";
309
+ if (!clip) {
310
+ checks.push({
311
+ id: `animation.required.${label}`,
312
+ status: "fail",
313
+ assetId: manifest.asset.id,
314
+ message: `Missing required animation clip "${label}".`
315
+ });
316
+ continue;
317
+ }
318
+ checks.push({
319
+ id: `animation.required.${label}`,
320
+ status: "pass",
321
+ assetId: manifest.asset.id,
322
+ message: `Required animation clip "${label}" is present as "${clip.name}".`
323
+ });
324
+ if (required.minimumDuration !== undefined) {
325
+ const duration = clip.duration ?? 0;
326
+ checks.push({
327
+ id: `animation.required.${label}.duration`,
328
+ status: duration >= required.minimumDuration ? "pass" : "fail",
329
+ assetId: manifest.asset.id,
330
+ message: duration >= required.minimumDuration
331
+ ? `Required clip "${label}" meets duration policy.`
332
+ : `Required clip "${label}" is ${round(duration)}s; expected at least ${round(required.minimumDuration)}s.`
333
+ });
334
+ }
335
+ for (const eventName of required.requireEvents ?? []) {
336
+ const hasEvent = Boolean(clip.events?.some((event) => event.name === eventName));
337
+ checks.push({
338
+ id: `animation.required.${label}.event.${eventName}`,
339
+ status: hasEvent ? "pass" : "fail",
340
+ assetId: manifest.asset.id,
341
+ message: hasEvent
342
+ ? `Required clip "${label}" has event "${eventName}".`
343
+ : `Required clip "${label}" is missing event "${eventName}".`
344
+ });
345
+ }
346
+ }
347
+ return checks;
348
+ }
349
+ export function createGameAssetValidationIssue(severity, code, message, details = {}) {
350
+ return {
351
+ severity,
352
+ code,
353
+ message,
354
+ ...details
355
+ };
356
+ }
357
+ export function isAuraGameModelAssetRef(value) {
358
+ const candidate = value;
359
+ return Boolean(candidate && candidate.kind === "aura-asset-ref" && candidate.type === "model" && candidate.id);
360
+ }
361
+ export function gameAssetBoundsFromSize(size, source = "manual") {
362
+ return normalizeGameAssetBounds(size, source) ?? {
363
+ center: [0, 0, 0],
364
+ size: [0, 0, 0],
365
+ min: [0, 0, 0],
366
+ max: [0, 0, 0],
367
+ radius: 0,
368
+ source
369
+ };
370
+ }
371
+ function checkTypedAsset(manifest) {
372
+ const asset = manifest.asset;
373
+ const valid = isAuraGameModelAssetRef(asset);
374
+ return {
375
+ id: "asset.typed-ref",
376
+ status: valid ? "pass" : "fail",
377
+ assetId: asset.id,
378
+ message: valid
379
+ ? `Asset "${asset.id}" is a typed Aura model asset reference.`
380
+ : "Asset must be a typed Aura model asset reference, for example model(assets.fighter)."
381
+ };
382
+ }
383
+ function checkModelFormat(manifest) {
384
+ const format = normalizeModelFormat(manifest.file.format);
385
+ const supported = format === "glb" || format === "gltf";
386
+ return {
387
+ id: "asset.format",
388
+ status: supported ? "pass" : "fail",
389
+ assetId: manifest.asset.id,
390
+ message: supported
391
+ ? `Asset format "${format}" is supported.`
392
+ : `Asset format "${manifest.file.format}" is not supported for game readiness; export GLB or glTF.`
393
+ };
394
+ }
395
+ function checkFileSize(manifest, policy) {
396
+ const sizeBytes = manifest.file.sizeBytes;
397
+ if (sizeBytes === undefined) {
398
+ return {
399
+ id: "asset.file-size",
400
+ status: policy.requireFileSize ? "fail" : "missing",
401
+ assetId: manifest.asset.id,
402
+ message: policy.requireFileSize
403
+ ? "Asset file size is required."
404
+ : "Asset file size is missing; download budget cannot be proven."
405
+ };
406
+ }
407
+ const maxFileSizeBytes = policy.maxFileSizeBytes;
408
+ if (maxFileSizeBytes === undefined) {
409
+ return {
410
+ id: "asset.file-size",
411
+ status: "pass",
412
+ assetId: manifest.asset.id,
413
+ message: `Asset file size is ${sizeBytes} bytes.`,
414
+ metrics: { sizeBytes }
415
+ };
416
+ }
417
+ return {
418
+ id: "asset.file-size",
419
+ status: sizeBytes <= maxFileSizeBytes ? "pass" : "fail",
420
+ assetId: manifest.asset.id,
421
+ message: sizeBytes <= maxFileSizeBytes
422
+ ? `Asset file size is within budget (${sizeBytes}/${maxFileSizeBytes} bytes).`
423
+ : `Asset file size exceeds budget (${sizeBytes}/${maxFileSizeBytes} bytes).`,
424
+ metrics: { sizeBytes, maxFileSizeBytes }
425
+ };
426
+ }
427
+ function checkSkeleton(manifest, required = false) {
428
+ const skeleton = manifest.skeleton;
429
+ if (!skeleton) {
430
+ return {
431
+ id: "skeleton",
432
+ status: required ? "fail" : "missing",
433
+ assetId: manifest.asset.id,
434
+ message: required ? "Skeleton readiness is required." : "Skeleton readiness is not declared."
435
+ };
436
+ }
437
+ const missingRequiredBones = skeleton.missingRequiredBones ?? [];
438
+ return {
439
+ id: "skeleton",
440
+ status: skeleton.present && missingRequiredBones.length === 0 ? "pass" : "fail",
441
+ assetId: manifest.asset.id,
442
+ message: skeleton.present && missingRequiredBones.length === 0
443
+ ? `Skeleton is present${skeleton.joints ? ` with ${skeleton.joints} joints` : ""}.`
444
+ : `Skeleton is not ready${missingRequiredBones.length ? `; missing ${missingRequiredBones.join(", ")}` : ""}.`
445
+ };
446
+ }
447
+ function checkMaterials(manifest, requireReadable = false) {
448
+ const materials = manifest.materials ?? [];
449
+ if (materials.length === 0) {
450
+ return {
451
+ id: "materials",
452
+ status: requireReadable ? "fail" : "missing",
453
+ assetId: manifest.asset.id,
454
+ message: requireReadable ? "Material summary is required." : "Material summary is missing."
455
+ };
456
+ }
457
+ const invisible = materials.filter((material) => material.visible === false || material.opacity === 0);
458
+ const unreadable = materials.filter((material) => material.readable === false);
459
+ return {
460
+ id: "materials",
461
+ status: invisible.length === 0 && unreadable.length === 0 ? "pass" : "fail",
462
+ assetId: manifest.asset.id,
463
+ message: invisible.length === 0 && unreadable.length === 0
464
+ ? `Asset declares ${materials.length} readable materials.`
465
+ : `Asset has material issues: ${[...invisible.map((material) => `${material.name} invisible`), ...unreadable.map((material) => `${material.name} unreadable`)].join(", ")}.`
466
+ };
467
+ }
468
+ function checkTextures(manifest, maxTextureDimension) {
469
+ const textures = manifest.textures ?? [];
470
+ if (textures.length === 0) {
471
+ return [
472
+ {
473
+ id: "textures",
474
+ status: "missing",
475
+ assetId: manifest.asset.id,
476
+ message: "Texture summary is missing."
477
+ }
478
+ ];
479
+ }
480
+ const checks = [
481
+ {
482
+ id: "textures",
483
+ status: "pass",
484
+ assetId: manifest.asset.id,
485
+ message: `Asset declares ${textures.length} textures.`
486
+ }
487
+ ];
488
+ if (maxTextureDimension !== undefined) {
489
+ for (const texture of textures) {
490
+ const width = texture.width ?? 0;
491
+ const height = texture.height ?? 0;
492
+ const dimension = Math.max(width, height);
493
+ checks.push({
494
+ id: `textures.${texture.name}.dimension`,
495
+ status: dimension === 0 ? "missing" : dimension <= maxTextureDimension ? "pass" : "fail",
496
+ assetId: manifest.asset.id,
497
+ message: dimension === 0
498
+ ? `Texture "${texture.name}" dimensions are missing.`
499
+ : dimension <= maxTextureDimension
500
+ ? `Texture "${texture.name}" is within dimension budget.`
501
+ : `Texture "${texture.name}" exceeds ${maxTextureDimension}px.`
502
+ });
503
+ }
504
+ }
505
+ return checks;
506
+ }
507
+ function checkThumbnail(manifest, required = false) {
508
+ const thumbnail = manifest.thumbnail;
509
+ return {
510
+ id: "thumbnail",
511
+ status: thumbnail?.url || thumbnail?.path ? "pass" : required ? "fail" : "missing",
512
+ assetId: manifest.asset.id,
513
+ message: thumbnail?.url || thumbnail?.path
514
+ ? "Asset thumbnail is declared."
515
+ : required
516
+ ? "Asset thumbnail is required."
517
+ : "Asset thumbnail is missing."
518
+ };
519
+ }
520
+ function checkProvenance(manifest, required = false) {
521
+ const provenance = manifest.provenance;
522
+ const hasLicense = Boolean(provenance?.license || provenance?.licenseUrl);
523
+ const approved = provenance?.approvalStatus === "approved";
524
+ const ready = Boolean(provenance && hasLicense && provenance.commercialUse !== false && provenance.approvalStatus !== "rejected");
525
+ return {
526
+ id: "provenance",
527
+ status: ready ? (approved ? "pass" : "warn") : required ? "fail" : "missing",
528
+ assetId: manifest.asset.id,
529
+ message: ready
530
+ ? approved
531
+ ? "Asset provenance is approved."
532
+ : "Asset provenance is present but not marked approved."
533
+ : required
534
+ ? "Asset provenance, license, and commercial-use status are required."
535
+ : "Asset provenance is missing or incomplete."
536
+ };
537
+ }
538
+ function checkIntendedUse(manifest, required = false) {
539
+ const intendedUse = manifest.intendedUse;
540
+ return {
541
+ id: "intended-use",
542
+ status: intendedUse ? "pass" : required ? "fail" : "missing",
543
+ assetId: manifest.asset.id,
544
+ message: intendedUse ? `Asset intended use is "${intendedUse.kind}".` : "Asset intended route/game usage is missing."
545
+ };
546
+ }
547
+ function checkQuaterniusProvenance(manifest) {
548
+ const provenance = manifest.provenance;
549
+ const source = [
550
+ provenance?.title,
551
+ provenance?.creator,
552
+ provenance?.sourceName,
553
+ provenance?.sourceUrl,
554
+ provenance?.attribution,
555
+ ...(provenance?.notes ?? [])
556
+ ]
557
+ .filter((value) => typeof value === "string")
558
+ .join(" ");
559
+ const quaternius = /quaternius/i.test(source);
560
+ return {
561
+ id: "quaternius.source-family",
562
+ status: quaternius ? "pass" : "fail",
563
+ assetId: manifest.asset.id,
564
+ message: quaternius
565
+ ? "Asset provenance identifies a Quaternius-derived source."
566
+ : "Quaternius-derived fighter validation requires provenance that identifies Quaternius as the source family."
567
+ };
568
+ }
569
+ function pushCheck(check, checks, issues) {
570
+ checks.push(check);
571
+ if (check.status === "fail") {
572
+ issues.push(createGameAssetValidationIssue("error", check.id, check.message, { assetId: check.assetId }));
573
+ }
574
+ if (check.status === "warn" || check.status === "missing") {
575
+ issues.push(createGameAssetValidationIssue("warning", check.id, check.message, { assetId: check.assetId }));
576
+ }
577
+ }
578
+ function normalizeGameAssetBounds(bounds, source) {
579
+ if (!bounds)
580
+ return undefined;
581
+ if (Array.isArray(bounds)) {
582
+ const size = [safeNumber(bounds[0]), safeNumber(bounds[1]), safeNumber(bounds[2])];
583
+ const center = [0, size[1] / 2, 0];
584
+ const half = [size[0] / 2, size[1] / 2, size[2] / 2];
585
+ return {
586
+ center,
587
+ size,
588
+ min: [-half[0], 0, -half[2]],
589
+ max: [half[0], size[1], half[2]],
590
+ radius: Math.hypot(half[0], half[1], half[2]),
591
+ source
592
+ };
593
+ }
594
+ return bounds;
595
+ }
596
+ function provenanceFromAsset(asset) {
597
+ if (!asset.metadata?.license && !asset.hash)
598
+ return undefined;
599
+ return {
600
+ license: asset.metadata?.license,
601
+ fileHash: asset.hash,
602
+ approvalStatus: asset.optional ? "needs-review" : "draft"
603
+ };
604
+ }
605
+ function normalizeAnimationClips(clips) {
606
+ if (!clips)
607
+ return undefined;
608
+ return clips.map((clip) => (typeof clip === "string" ? { name: clip } : clip));
609
+ }
610
+ function normalizeMaterials(materials) {
611
+ if (!materials)
612
+ return undefined;
613
+ return materials.map((material) => (typeof material === "string" ? { name: material, visible: true, readable: true } : material));
614
+ }
615
+ function normalizeTextures(textures) {
616
+ if (!textures)
617
+ return undefined;
618
+ return textures.map((texture) => (typeof texture === "string" ? { name: texture } : texture));
619
+ }
620
+ function normalizeModelFormat(format) {
621
+ const normalized = format.toLowerCase().replace(/^\./, "");
622
+ if (normalized.includes("gltf-binary"))
623
+ return "glb";
624
+ if (normalized.includes("gltf+json"))
625
+ return "gltf";
626
+ return normalized;
627
+ }
628
+ function rangeCheck(id, value, min, max, assetId, label) {
629
+ const aboveMin = min === undefined || value >= min;
630
+ const belowMax = max === undefined || value <= max;
631
+ return {
632
+ id,
633
+ status: aboveMin && belowMax ? "pass" : "fail",
634
+ assetId,
635
+ message: aboveMin && belowMax
636
+ ? `Asset ${label} is ${round(value)}m.`
637
+ : `Asset ${label} is ${round(value)}m; expected ${min ?? "-inf"} to ${max ?? "+inf"}m.`,
638
+ metrics: { value: round(value), ...(min !== undefined ? { min } : {}), ...(max !== undefined ? { max } : {}) }
639
+ };
640
+ }
641
+ function maxCheck(id, value, max, assetId, label) {
642
+ return {
643
+ id,
644
+ status: value <= max ? "pass" : "fail",
645
+ assetId,
646
+ message: value <= max ? `Asset ${label} is within budget.` : `Asset ${label} is ${round(value)}; expected at most ${max}.`,
647
+ metrics: { value: round(value), max }
648
+ };
649
+ }
650
+ function normalizeClipRequirement(requirement) {
651
+ if (typeof requirement !== "string")
652
+ return requirement;
653
+ return isAnimationRole(requirement) ? { role: requirement } : { name: requirement };
654
+ }
655
+ function findClip(clips, requirement) {
656
+ const requiredRole = requirement.role;
657
+ const requiredName = requirement.name?.toLowerCase();
658
+ return clips.find((clip) => {
659
+ if (requiredRole && clip.role === requiredRole)
660
+ return true;
661
+ if (requiredName && clip.name.toLowerCase() === requiredName)
662
+ return true;
663
+ if (requiredRole && clip.name.toLowerCase().includes(requiredRole))
664
+ return true;
665
+ return false;
666
+ });
667
+ }
668
+ function isAnimationRole(value) {
669
+ return [
670
+ "idle",
671
+ "walk",
672
+ "walk-forward",
673
+ "walk-back",
674
+ "run",
675
+ "jump",
676
+ "land",
677
+ "dash",
678
+ "guard",
679
+ "light",
680
+ "heavy",
681
+ "special",
682
+ "super",
683
+ "hit",
684
+ "stun",
685
+ "knockdown",
686
+ "win",
687
+ "lose",
688
+ "speak",
689
+ "emote"
690
+ ].includes(value);
691
+ }
692
+ function toAxisList(axis) {
693
+ return Array.isArray(axis) ? [...axis] : [axis];
694
+ }
695
+ function toPivotList(pivot) {
696
+ return Array.isArray(pivot) ? [...pivot] : [pivot];
697
+ }
698
+ function safeNumber(value) {
699
+ return Number.isFinite(value) ? value : 0;
700
+ }
701
+ function round(value) {
702
+ return Number(value.toFixed(4));
703
+ }
704
+ export const gameAssetValidation = {
705
+ contractVersion: gameAssetValidationContractVersion,
706
+ defineManifest: defineGameAssetReadinessManifest,
707
+ createManifest: createGameAssetReadinessManifest,
708
+ validate: validateGameAssetReadiness,
709
+ quaterniusGameReadyFighter: quaterniusGameReadyFighterValidationContract,
710
+ createQuaterniusGameReadyFighterPolicy: createQuaterniusGameReadyFighterValidationPolicy,
711
+ validateQuaterniusGameReadyFighter: validateQuaterniusGameReadyFighterAsset,
712
+ evaluateBounds: evaluateGameAssetBounds,
713
+ evaluateOrientation: evaluateGameAssetOrientation,
714
+ evaluateAnimationClips: evaluateGameAssetAnimationClips,
715
+ boundsFromSize: gameAssetBoundsFromSize,
716
+ isModelAssetRef: isAuraGameModelAssetRef,
717
+ fightingAnimationRoles: fightingGameAnimationRoles
718
+ };
719
+ //# sourceMappingURL=GameAssetValidation.js.map