@carbonenginejs/runtime-utils 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +23 -23
  3. package/README.md +69 -69
  4. package/THIRD-PARTY-NOTICES.md +64 -64
  5. package/docs/README.md +74 -73
  6. package/docs/architecture.md +101 -101
  7. package/docs/concepts/foundation-consolidation.md +85 -85
  8. package/docs/concepts/model-lifecycle.md +111 -0
  9. package/docs/const-kb.md +85 -87
  10. package/docs/core-types/DECORATOR-TODOS.md +25 -25
  11. package/docs/core-types/README.md +229 -168
  12. package/docs/reference/api.md +105 -102
  13. package/docs/reference/classes/README.md +135 -135
  14. package/package.json +139 -139
  15. package/src/arrays.js +5 -5
  16. package/src/audio/audioFormats.js +34 -34
  17. package/src/audio/index.js +1 -1
  18. package/src/box3.js +331 -331
  19. package/src/bytes.js +56 -56
  20. package/src/compression.js +56 -56
  21. package/src/constants/index.js +7 -7
  22. package/src/constants/trinity.js +13 -13
  23. package/src/constants.js +15 -15
  24. package/src/curve.js +79 -79
  25. package/src/d3d/dxgiFormats.js +46 -46
  26. package/src/d3d/index.js +2 -2
  27. package/src/d3d/primitiveTopology.js +11 -11
  28. package/src/document/CjsCarbonDocument.js +212 -212
  29. package/src/document/CjsClassRegistry.js +373 -373
  30. package/src/document/CjsDocumentDehydrator.js +142 -142
  31. package/src/document/CjsDocumentHydrator.js +156 -156
  32. package/src/document/CjsStructRegistry.js +348 -348
  33. package/src/document/hydrationAdapter.js +129 -129
  34. package/src/document/index.js +6 -6
  35. package/src/errors/CjsError.js +286 -286
  36. package/src/errors/index.js +5 -5
  37. package/src/geometry/box.js +22 -22
  38. package/src/geometry/cylinder.js +22 -22
  39. package/src/geometry/helpers/earcut.js +1 -1
  40. package/src/geometry/helpers/misc.js +3 -3
  41. package/src/geometry/index.js +8 -8
  42. package/src/geometry/json.js +67 -67
  43. package/src/geometry/lathe.js +44 -44
  44. package/src/geometry/plane.js +14 -14
  45. package/src/geometry/shape.js +4 -4
  46. package/src/geometry/sphere.js +24 -24
  47. package/src/geometry/torus.js +14 -14
  48. package/src/graphics/colorSpaces.js +22 -22
  49. package/src/graphics/index.js +4 -4
  50. package/src/graphics/pixelFormats.js +158 -158
  51. package/src/graphics/textureDimensions.js +22 -22
  52. package/src/graphics/trinityEnums.js +87 -87
  53. package/src/index.js +62 -62
  54. package/src/is.js +108 -46
  55. package/src/json.js +23 -23
  56. package/src/lifecycle/CjsLifecycleState.js +77 -77
  57. package/src/lifecycle/index.js +1 -1
  58. package/src/lne3.js +70 -70
  59. package/src/lookup.js +48 -48
  60. package/src/mat3.js +51 -51
  61. package/src/mat4.js +699 -699
  62. package/src/math/index.js +25 -25
  63. package/src/math/scalar.js +63 -63
  64. package/src/media/index.js +1 -1
  65. package/src/media/mediaTypes.js +50 -50
  66. package/src/mesh.js +424 -424
  67. package/src/model/CjsEventEmitter.js +333 -333
  68. package/src/model/CjsModel.js +1589 -1544
  69. package/src/model/CjsModelState.js +72 -72
  70. package/src/model/index.js +4 -4
  71. package/src/model/sourceRecordUtils.js +54 -54
  72. package/src/noise.js +310 -310
  73. package/src/num.js +827 -827
  74. package/src/object.js +39 -39
  75. package/src/path.js +53 -53
  76. package/src/pln.js +125 -125
  77. package/src/pool.js +9 -9
  78. package/src/quat.js +144 -144
  79. package/src/ray3.js +188 -188
  80. package/src/renderContext/formats.js +145 -145
  81. package/src/renderContext/index.js +5 -5
  82. package/src/renderContext/presentation.js +125 -125
  83. package/src/renderContext/resources.js +27 -27
  84. package/src/renderContext/upscaling.js +22 -22
  85. package/src/renderContext/window.js +20 -20
  86. package/src/runtime/CjsRuntimeState.js +50 -50
  87. package/src/schema/CjsSchema.js +555 -318
  88. package/src/schema/index.js +4 -4
  89. package/src/shader/index.js +1 -1
  90. package/src/shader/shaderStages.js +37 -37
  91. package/src/sph3.js +181 -181
  92. package/src/tangent.js +288 -288
  93. package/src/text.js +40 -40
  94. package/src/tri3.js +98 -98
  95. package/src/types/carbonTypes.js +635 -635
  96. package/src/types/index.js +2 -2
  97. package/src/utils.js +58 -58
  98. package/src/validation.js +46 -46
  99. package/src/vec2.js +229 -229
  100. package/src/vec3.js +1188 -1172
  101. package/src/vec4.js +347 -347
  102. package/src/vertex.js +108 -108
  103. package/src/webgpu/index.js +1 -1
  104. package/src/webgpu/textureFormats.js +121 -121
@@ -1,635 +1,635 @@
1
- export const CARBON_META = Symbol.for("carbonenginejs.type");
2
- export const CARBON_RAW_STRUCT_TYPE = Symbol.for("carbonenginejs.rawStructType");
3
-
4
- export const CARBON_TYPE = Object.freeze({
5
- UNKNOWN: "unknown",
6
- BOOLEAN: "boolean",
7
- STRING: "string",
8
- PATH: "path",
9
- EXPRESSION: "expression",
10
- ENUM: "enum",
11
- FLOAT32: "float32",
12
- FLOAT64: "float64",
13
- INT8: "int8",
14
- UINT8: "uint8",
15
- INT16: "int16",
16
- UINT16: "uint16",
17
- INT32: "int32",
18
- UINT32: "uint32",
19
- INT64: "int64",
20
- UINT64: "uint64",
21
- VECTOR2: "vector2",
22
- VECTOR3: "vector3",
23
- VECTOR4: "vector4",
24
- COLOR: "color",
25
- QUATERNION: "quaternion",
26
- MATRIX3: "matrix3",
27
- MATRIX4: "matrix4",
28
- ARRAY: "array",
29
- MAP: "map",
30
- SET: "set",
31
- MODEL: "model",
32
- OBJECT_REF: "objectRef",
33
- STRUCT: "struct",
34
- RAW_STRUCT: "rawStruct",
35
- TYPED_ARRAY: "typedArray"
36
- });
37
-
38
- const FLOAT32_VECTOR_DEFINITIONS = Object.freeze({
39
- [CARBON_TYPE.VECTOR2]: Object.freeze({ kind: CARBON_TYPE.VECTOR2, js: "vec2", scalar: CARBON_TYPE.FLOAT32, length: 2, default: [0, 0] }),
40
- [CARBON_TYPE.VECTOR3]: Object.freeze({ kind: CARBON_TYPE.VECTOR3, js: "vec3", scalar: CARBON_TYPE.FLOAT32, length: 3, default: [0, 0, 0] }),
41
- [CARBON_TYPE.VECTOR4]: Object.freeze({ kind: CARBON_TYPE.VECTOR4, js: "vec4", scalar: CARBON_TYPE.FLOAT32, length: 4, default: [0, 0, 0, 0] }),
42
- [CARBON_TYPE.COLOR]: Object.freeze({ kind: CARBON_TYPE.COLOR, js: "vec4", semantic: CARBON_TYPE.COLOR, scalar: CARBON_TYPE.FLOAT32, length: 4, default: [0, 0, 0, 0] }),
43
- [CARBON_TYPE.QUATERNION]: Object.freeze({ kind: CARBON_TYPE.QUATERNION, js: "quat", scalar: CARBON_TYPE.FLOAT32, length: 4, default: [0, 0, 0, 1] }),
44
- [CARBON_TYPE.MATRIX3]: Object.freeze({ kind: CARBON_TYPE.MATRIX3, js: "mat3", scalar: CARBON_TYPE.FLOAT32, length: 9, default: [1, 0, 0, 0, 1, 0, 0, 0, 1] }),
45
- [CARBON_TYPE.MATRIX4]: Object.freeze({ kind: CARBON_TYPE.MATRIX4, js: "mat4", scalar: CARBON_TYPE.FLOAT32, length: 16, default: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] })
46
- });
47
-
48
- const TYPE_DEFINITIONS = Object.freeze({
49
- [CARBON_TYPE.UNKNOWN]: Object.freeze({ kind: CARBON_TYPE.UNKNOWN, js: "*" }),
50
- [CARBON_TYPE.BOOLEAN]: Object.freeze({ kind: CARBON_TYPE.BOOLEAN, js: "boolean" }),
51
- [CARBON_TYPE.STRING]: Object.freeze({ kind: CARBON_TYPE.STRING, js: "string" }),
52
- [CARBON_TYPE.PATH]: Object.freeze({ kind: CARBON_TYPE.PATH, js: "string" }),
53
- [CARBON_TYPE.EXPRESSION]: Object.freeze({ kind: CARBON_TYPE.EXPRESSION, js: "string", semantic: CARBON_TYPE.EXPRESSION }),
54
- [CARBON_TYPE.ENUM]: Object.freeze({ kind: CARBON_TYPE.ENUM, js: "number|string|null" }),
55
- [CARBON_TYPE.FLOAT32]: Object.freeze({ kind: CARBON_TYPE.FLOAT32, js: "number", bits: 32, signed: true, floating: true }),
56
- [CARBON_TYPE.FLOAT64]: Object.freeze({ kind: CARBON_TYPE.FLOAT64, js: "number", bits: 64, signed: true, floating: true }),
57
- [CARBON_TYPE.INT8]: Object.freeze({ kind: CARBON_TYPE.INT8, js: "number", bits: 8, signed: true, integer: true }),
58
- [CARBON_TYPE.UINT8]: Object.freeze({ kind: CARBON_TYPE.UINT8, js: "number", bits: 8, signed: false, integer: true }),
59
- [CARBON_TYPE.INT16]: Object.freeze({ kind: CARBON_TYPE.INT16, js: "number", bits: 16, signed: true, integer: true }),
60
- [CARBON_TYPE.UINT16]: Object.freeze({ kind: CARBON_TYPE.UINT16, js: "number", bits: 16, signed: false, integer: true }),
61
- [CARBON_TYPE.INT32]: Object.freeze({ kind: CARBON_TYPE.INT32, js: "number", bits: 32, signed: true, integer: true }),
62
- [CARBON_TYPE.UINT32]: Object.freeze({ kind: CARBON_TYPE.UINT32, js: "number", bits: 32, signed: false, integer: true }),
63
- [CARBON_TYPE.INT64]: Object.freeze({ kind: CARBON_TYPE.INT64, js: "bigint", bits: 64, signed: true, integer: true }),
64
- [CARBON_TYPE.UINT64]: Object.freeze({ kind: CARBON_TYPE.UINT64, js: "bigint", bits: 64, signed: false, integer: true }),
65
- [CARBON_TYPE.ARRAY]: Object.freeze({ kind: CARBON_TYPE.ARRAY, js: "Array" }),
66
- [CARBON_TYPE.MAP]: Object.freeze({ kind: CARBON_TYPE.MAP, js: "Map" }),
67
- [CARBON_TYPE.SET]: Object.freeze({ kind: CARBON_TYPE.SET, js: "Set" }),
68
- [CARBON_TYPE.MODEL]: Object.freeze({ kind: CARBON_TYPE.MODEL, js: "object|null" }),
69
- [CARBON_TYPE.OBJECT_REF]: Object.freeze({ kind: CARBON_TYPE.OBJECT_REF, js: "object|null" }),
70
- [CARBON_TYPE.STRUCT]: Object.freeze({ kind: CARBON_TYPE.STRUCT, js: "object" }),
71
- [CARBON_TYPE.RAW_STRUCT]: Object.freeze({ kind: CARBON_TYPE.RAW_STRUCT, js: "object" }),
72
- [CARBON_TYPE.TYPED_ARRAY]: Object.freeze({ kind: CARBON_TYPE.TYPED_ARRAY, js: "TypedArray" }),
73
- ...FLOAT32_VECTOR_DEFINITIONS
74
- });
75
-
76
- const TYPE_ALIASES = Object.freeze({
77
- bool: CARBON_TYPE.BOOLEAN,
78
- float: CARBON_TYPE.FLOAT32,
79
- double: CARBON_TYPE.FLOAT64,
80
- vec2: CARBON_TYPE.VECTOR2,
81
- vec3: CARBON_TYPE.VECTOR3,
82
- vec4: CARBON_TYPE.VECTOR4,
83
- quat: CARBON_TYPE.QUATERNION,
84
- mat3: CARBON_TYPE.MATRIX3,
85
- mat4: CARBON_TYPE.MATRIX4
86
- });
87
-
88
- const TYPED_ARRAY_CTORS = Object.freeze({
89
- Int8Array,
90
- Uint8Array,
91
- Uint8ClampedArray,
92
- Int16Array,
93
- Uint16Array,
94
- Int32Array,
95
- Uint32Array,
96
- Float32Array,
97
- Float64Array,
98
- BigInt64Array,
99
- BigUint64Array
100
- });
101
-
102
- const num = Object.freeze({
103
- int8,
104
- uint8,
105
- int16,
106
- uint16,
107
- int32,
108
- uint32,
109
- int64,
110
- uint64,
111
- float32,
112
- float64
113
- });
114
-
115
- const CARBON_MATH_KINDS = new Set(Object.keys(FLOAT32_VECTOR_DEFINITIONS));
116
-
117
- export function createCarbonMathValue(type, value = undefined)
118
- {
119
- const descriptor = normalizeCarbonTypeDescriptor(type);
120
- const values = normalizeMathValues(value, descriptor.length, descriptor.default);
121
-
122
- // Carbon math values are plain Float32Arrays. Their descriptors remain
123
- // independent of the gl-matrix-backed math helpers. Defaults already
124
- // encode identity/zero, matching gl-matrix's create() output.
125
- return CARBON_MATH_KINDS.has(descriptor.kind) ? Float32Array.from(values) : values;
126
- }
127
-
128
- /**
129
- * Coerce a math value INTO an existing Float32Array target, in place, with no
130
- * allocation. Returns `true`/`false` (whether any element changed) when the fast
131
- * path applies — a math kind, `target` a compatible Float32Array, and `value`
132
- * array-like. Returns `null` when it does not apply (non-math kind, incompatible
133
- * or absent target, or a null/undefined value) so the caller falls back to a
134
- * normal allocating assignment.
135
- */
136
- export function coerceCarbonMathInto(target, value, type)
137
- {
138
- const descriptor = normalizeCarbonTypeDescriptor(type);
139
- if (!CARBON_MATH_KINDS.has(descriptor.kind)) return null;
140
- if (!(target instanceof Float32Array) || target.length !== descriptor.length) return null;
141
-
142
- const source = ArrayBuffer.isView(value) || Array.isArray(value) ? value : null;
143
- if (!source) return null;
144
-
145
- const defaults = descriptor.default;
146
- let changed = false;
147
- for (let i = 0; i < descriptor.length; i++)
148
- {
149
- const next = num.float32(i < source.length ? source[i] : defaults[i]);
150
- if (target[i] !== next)
151
- {
152
- target[i] = next;
153
- changed = true;
154
- }
155
- }
156
- return changed;
157
- }
158
-
159
- export function getCarbonTypeDefinition(type)
160
- {
161
- const descriptor = normalizeCarbonTypeDescriptor(type);
162
- return TYPE_DEFINITIONS[descriptor.kind] || TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
163
- }
164
-
165
- export function normalizeCarbonTypeDescriptor(type)
166
- {
167
- if (!type) return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
168
- if (typeof type === "string") return carbonTypeDefinitionForKind(type);
169
- if (type.kind) return mergeCarbonTypeDefinition(type);
170
- if (type.jsType) return normalizeCarbonTypeDescriptor(type.jsType);
171
- if (type.cppType) return inferCarbonTypeFromCpp(type.cppType, type.name);
172
- if (type.pythonType) return inferCarbonTypeFromPython(type.pythonType);
173
- return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
174
- }
175
-
176
- export function inferCarbonTypeFromCpp(cppType, propertyName = "")
177
- {
178
- const original = String(cppType || "").trim();
179
- const type = normalizeCppType(original);
180
- const named = normalizeCppTypeName(original);
181
-
182
- if (!type) return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
183
- if (type.includes("std::vector") || /(?:Vector|List)$/.test(named)) return containerDescriptor(CARBON_TYPE.ARRAY, original);
184
- if (type.includes("std::map") || /(?:Map)$/.test(named)) return containerDescriptor(CARBON_TYPE.MAP, original);
185
- if (type.includes("std::set") || /(?:Set)$/.test(named)) return containerDescriptor(CARBON_TYPE.SET, original);
186
- if (/\*$/.test(type) || /^P(?:I)?[A-Z]\w+$/.test(named) || /(?:Ptr|Ref)$/.test(named)) return objectRefDescriptor(original);
187
-
188
- switch (named)
189
- {
190
- case "bool":
191
- return TYPE_DEFINITIONS[CARBON_TYPE.BOOLEAN];
192
- case "char":
193
- case "int8_t":
194
- return TYPE_DEFINITIONS[CARBON_TYPE.INT8];
195
- case "uint8_t":
196
- case "byte":
197
- return TYPE_DEFINITIONS[CARBON_TYPE.UINT8];
198
- case "int16_t":
199
- case "short":
200
- return TYPE_DEFINITIONS[CARBON_TYPE.INT16];
201
- case "uint16_t":
202
- case "ushort":
203
- return TYPE_DEFINITIONS[CARBON_TYPE.UINT16];
204
- case "int":
205
- case "int32_t":
206
- case "long":
207
- return TYPE_DEFINITIONS[CARBON_TYPE.INT32];
208
- case "uint":
209
- case "uint32_t":
210
- case "ulong":
211
- return TYPE_DEFINITIONS[CARBON_TYPE.UINT32];
212
- case "int64_t":
213
- case "longlong":
214
- return TYPE_DEFINITIONS[CARBON_TYPE.INT64];
215
- case "uint64_t":
216
- case "size_t":
217
- case "ulonglong":
218
- return TYPE_DEFINITIONS[CARBON_TYPE.UINT64];
219
- case "float":
220
- return TYPE_DEFINITIONS[CARBON_TYPE.FLOAT32];
221
- case "double":
222
- return TYPE_DEFINITIONS[CARBON_TYPE.FLOAT64];
223
- case "std::string":
224
- case "std::wstring":
225
- case "BlueSharedString":
226
- return isExpressionLike(propertyName) ? TYPE_DEFINITIONS[CARBON_TYPE.EXPRESSION] : TYPE_DEFINITIONS[CARBON_TYPE.STRING];
227
- case "Vector2":
228
- return TYPE_DEFINITIONS[CARBON_TYPE.VECTOR2];
229
- case "Vector3":
230
- return TYPE_DEFINITIONS[CARBON_TYPE.VECTOR3];
231
- case "Vector4":
232
- return isRotationLike(propertyName) ? TYPE_DEFINITIONS[CARBON_TYPE.QUATERNION] : TYPE_DEFINITIONS[CARBON_TYPE.VECTOR4];
233
- case "Color":
234
- case "ColorRGBA":
235
- return TYPE_DEFINITIONS[CARBON_TYPE.COLOR];
236
- case "Quaternion":
237
- return TYPE_DEFINITIONS[CARBON_TYPE.QUATERNION];
238
- case "Matrix3":
239
- case "Mat3":
240
- return TYPE_DEFINITIONS[CARBON_TYPE.MATRIX3];
241
- case "Matrix":
242
- case "Matrix4":
243
- case "Mat4":
244
- case "TriMatrix":
245
- return TYPE_DEFINITIONS[CARBON_TYPE.MATRIX4];
246
- default:
247
- break;
248
- }
249
-
250
- if (/::[A-Za-z_]\w*(?:Type|Usage|Mode|Enum)$/.test(type)) return TYPE_DEFINITIONS[CARBON_TYPE.ENUM];
251
- if (type.includes("::")) return rawStructDescriptor(original);
252
- if (/^[A-Z]\w*(?:Type|Usage|Mode|Enum)?$/.test(named)) return TYPE_DEFINITIONS[CARBON_TYPE.ENUM];
253
- return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
254
- }
255
-
256
- export function inferCarbonTypeFromPython(pythonType)
257
- {
258
- const type = String(pythonType || "").trim().toLowerCase();
259
- if (!type) return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
260
- if (type === "bool" || type === "boolean") return TYPE_DEFINITIONS[CARBON_TYPE.BOOLEAN];
261
- if (type === "str" || type === "unicode" || type === "bytes") return TYPE_DEFINITIONS[CARBON_TYPE.STRING];
262
- if (type === "float") return TYPE_DEFINITIONS[CARBON_TYPE.FLOAT64];
263
- if (type === "int" || type === "long") return TYPE_DEFINITIONS[CARBON_TYPE.INT64];
264
- if (type === "list" || type === "tuple") return TYPE_DEFINITIONS[CARBON_TYPE.ARRAY];
265
- if (type === "dict") return TYPE_DEFINITIONS[CARBON_TYPE.MAP];
266
- if (type === "set") return TYPE_DEFINITIONS[CARBON_TYPE.SET];
267
- if (type === "none" || type === "nonetype") return objectRefDescriptor("NoneType");
268
- return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
269
- }
270
-
271
- export function defaultValueForCarbonField(field)
272
- {
273
- if (field && field.default && field.default.kind !== "expression")
274
- {
275
- return normalizeCarbonValue(field.default.json, field);
276
- }
277
- return defaultCarbonValue(field);
278
- }
279
-
280
- export function defaultCarbonValue(type)
281
- {
282
- const descriptor = normalizeCarbonTypeDescriptor(type);
283
- switch (descriptor.kind)
284
- {
285
- case CARBON_TYPE.BOOLEAN:
286
- return false;
287
- case CARBON_TYPE.STRING:
288
- case CARBON_TYPE.PATH:
289
- case CARBON_TYPE.EXPRESSION:
290
- return "";
291
- case CARBON_TYPE.FLOAT32:
292
- return num.float32(0);
293
- case CARBON_TYPE.FLOAT64:
294
- return num.float64(0);
295
- case CARBON_TYPE.INT8:
296
- return num.int8(0);
297
- case CARBON_TYPE.UINT8:
298
- return num.uint8(0);
299
- case CARBON_TYPE.INT16:
300
- return num.int16(0);
301
- case CARBON_TYPE.UINT16:
302
- return num.uint16(0);
303
- case CARBON_TYPE.INT32:
304
- return num.int32(0);
305
- case CARBON_TYPE.UINT32:
306
- return num.uint32(0);
307
- case CARBON_TYPE.INT64:
308
- return num.int64(0);
309
- case CARBON_TYPE.UINT64:
310
- return num.uint64(0);
311
- case CARBON_TYPE.VECTOR2:
312
- case CARBON_TYPE.VECTOR3:
313
- case CARBON_TYPE.VECTOR4:
314
- case CARBON_TYPE.COLOR:
315
- case CARBON_TYPE.QUATERNION:
316
- case CARBON_TYPE.MATRIX3:
317
- case CARBON_TYPE.MATRIX4:
318
- return createCarbonMathValue(descriptor);
319
- case CARBON_TYPE.ARRAY:
320
- return [];
321
- case CARBON_TYPE.MAP:
322
- return new Map();
323
- case CARBON_TYPE.SET:
324
- return new Set();
325
- case CARBON_TYPE.ENUM:
326
- case CARBON_TYPE.MODEL:
327
- case CARBON_TYPE.OBJECT_REF:
328
- case CARBON_TYPE.STRUCT:
329
- case CARBON_TYPE.RAW_STRUCT:
330
- case CARBON_TYPE.UNKNOWN:
331
- default:
332
- return null;
333
- }
334
- }
335
-
336
- export function normalizeCarbonValue(value, type)
337
- {
338
- const descriptor = normalizeCarbonTypeDescriptor(type);
339
- if (value === undefined) return defaultCarbonValue(descriptor);
340
- if (value === null) return null;
341
-
342
- switch (descriptor.kind)
343
- {
344
- case CARBON_TYPE.BOOLEAN:
345
- return Boolean(value);
346
- case CARBON_TYPE.STRING:
347
- case CARBON_TYPE.PATH:
348
- case CARBON_TYPE.EXPRESSION:
349
- return String(value);
350
- case CARBON_TYPE.FLOAT32:
351
- return num.float32(value);
352
- case CARBON_TYPE.FLOAT64:
353
- return num.float64(value);
354
- case CARBON_TYPE.INT8:
355
- return num.int8(value);
356
- case CARBON_TYPE.UINT8:
357
- return num.uint8(value);
358
- case CARBON_TYPE.INT16:
359
- return num.int16(value);
360
- case CARBON_TYPE.UINT16:
361
- return num.uint16(value);
362
- case CARBON_TYPE.INT32:
363
- return num.int32(value);
364
- case CARBON_TYPE.UINT32:
365
- return num.uint32(value);
366
- case CARBON_TYPE.INT64:
367
- return num.int64(value);
368
- case CARBON_TYPE.UINT64:
369
- return num.uint64(value);
370
- case CARBON_TYPE.VECTOR2:
371
- case CARBON_TYPE.VECTOR3:
372
- case CARBON_TYPE.VECTOR4:
373
- case CARBON_TYPE.COLOR:
374
- case CARBON_TYPE.QUATERNION:
375
- case CARBON_TYPE.MATRIX3:
376
- case CARBON_TYPE.MATRIX4:
377
- return createCarbonMathValue(descriptor, value);
378
- case CARBON_TYPE.ARRAY:
379
- return Array.isArray(value) ? value.map(cloneCarbonValue) : [cloneCarbonValue(value)];
380
- case CARBON_TYPE.MAP:
381
- return value instanceof Map ? cloneCarbonValue(value) : new Map(Object.entries(value || {}));
382
- case CARBON_TYPE.SET:
383
- return value instanceof Set ? new Set(value) : new Set(Array.isArray(value) ? value : [value]);
384
- default:
385
- return cloneCarbonValue(value);
386
- }
387
- }
388
-
389
- export function cloneCarbonValue(value)
390
- {
391
- if (ArrayBuffer.isView(value)) return new value.constructor(value);
392
- if (typeof value === "bigint") return value;
393
- if (isSourceShapedObject(value)) return value;
394
- if (value instanceof Map) return new Map(Array.from(value.entries()).map(([key, item]) => [key, cloneCarbonValue(item)]));
395
- if (value instanceof Set) return new Set(Array.from(value.values()).map(cloneCarbonValue));
396
- if (Array.isArray(value)) return value.map(cloneCarbonValue);
397
- if (value && typeof value === "object")
398
- {
399
- const result = Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneCarbonValue(item)]));
400
- if (isCarbonRawStruct(value)) return createCarbonRawStruct(getCarbonRawStructType(value), result);
401
- return result;
402
- }
403
- return value;
404
- }
405
-
406
- export function exportCarbonValue(value)
407
- {
408
- if (ArrayBuffer.isView(value)) return Array.from(value, item => typeof item === "bigint" ? item.toString() : item);
409
- if (typeof value === "bigint") return value.toString();
410
- if (value instanceof Map) return Object.fromEntries(Array.from(value.entries()).map(([key, item]) => [key, exportCarbonValue(item)]));
411
- if (value instanceof Set) return Array.from(value.values()).map(exportCarbonValue);
412
- if (Array.isArray(value)) return value.map(exportCarbonValue);
413
- if (value && typeof value === "object")
414
- {
415
- const result = Object.fromEntries(
416
- Object.entries(value)
417
- .filter(([key]) => !key.startsWith("_"))
418
- .map(([key, item]) => [key, exportCarbonValue(item)])
419
- );
420
- if (isCarbonRawStruct(value)) result.$type = getCarbonRawStructType(value);
421
- return result;
422
- }
423
- return value;
424
- }
425
-
426
- export function createCarbonRawStruct(typeName, values = {})
427
- {
428
- const result = { ...values };
429
- Object.defineProperty(result, CARBON_META, {
430
- value: CARBON_TYPE.RAW_STRUCT,
431
- enumerable: false,
432
- configurable: true
433
- });
434
- Object.defineProperty(result, CARBON_RAW_STRUCT_TYPE, {
435
- value: typeName || null,
436
- enumerable: false,
437
- configurable: true
438
- });
439
- return result;
440
- }
441
-
442
- export function isCarbonRawStruct(value)
443
- {
444
- return Boolean(value && typeof value === "object" && value[CARBON_META] === CARBON_TYPE.RAW_STRUCT);
445
- }
446
-
447
- export function getCarbonRawStructType(value)
448
- {
449
- return isCarbonRawStruct(value) ? value[CARBON_RAW_STRUCT_TYPE] : null;
450
- }
451
-
452
- export function carbonValueToJsExpression(value)
453
- {
454
- if (ArrayBuffer.isView(value))
455
- {
456
- const values = Array.from(value, item => typeof item === "bigint" ? `${item}n` : formatJsNumber(item));
457
- return `new ${value.constructor.name}([${values.join(", ")}])`;
458
- }
459
- if (typeof value === "bigint") return `${value}n`;
460
- if (value instanceof Map) return "new Map()";
461
- if (value instanceof Set) return "new Set()";
462
- if (Array.isArray(value)) return `[${value.map(item => carbonValueToJsExpression(item)).join(", ")}]`;
463
- if (value && typeof value === "object") return JSON.stringify(exportCarbonValue(value), null, 4);
464
- return JSON.stringify(value);
465
- }
466
-
467
- export function typedArrayConstructor(name)
468
- {
469
- return TYPED_ARRAY_CTORS[name] || null;
470
- }
471
-
472
- function carbonTypeDefinitionForKind(kind)
473
- {
474
- const normalized = TYPE_ALIASES[kind] || kind;
475
- return TYPE_DEFINITIONS[normalized] || Object.freeze({ kind: normalized, js: "*" });
476
- }
477
-
478
- function mergeCarbonTypeDefinition(type)
479
- {
480
- const definition = carbonTypeDefinitionForKind(type.kind);
481
- return Object.freeze({ ...definition, ...type, kind: definition.kind });
482
- }
483
-
484
- function uint8(value)
485
- {
486
- return Number(value) & 0xff;
487
- }
488
-
489
- function int8(value)
490
- {
491
- const result = uint8(value);
492
- return result > 0x7f ? result - 0x100 : result;
493
- }
494
-
495
- function uint16(value)
496
- {
497
- return Number(value) & 0xffff;
498
- }
499
-
500
- function int16(value)
501
- {
502
- const result = uint16(value);
503
- return result > 0x7fff ? result - 0x10000 : result;
504
- }
505
-
506
- function uint32(value)
507
- {
508
- return Number(value) >>> 0;
509
- }
510
-
511
- function int32(value)
512
- {
513
- return Number(value) | 0;
514
- }
515
-
516
- function uint64(value)
517
- {
518
- return toBigInt(value, false);
519
- }
520
-
521
- function int64(value)
522
- {
523
- return toBigInt(value, true);
524
- }
525
-
526
- function float32(value)
527
- {
528
- const result = Number(value);
529
- return Number.isFinite(result) ? result : 0;
530
- }
531
-
532
- function float64(value)
533
- {
534
- const result = Number(value);
535
- return Number.isFinite(result) ? result : 0;
536
- }
537
-
538
- function toBigInt(value, signed)
539
- {
540
- let result = 0n;
541
- if (typeof value === "bigint") result = value;
542
- else if (typeof value === "number" && Number.isFinite(value)) result = BigInt(Math.trunc(value));
543
- else if (typeof value === "string" && value.trim()) result = BigInt(value.trim());
544
-
545
- // Clamp unsigned negatives but FALL THROUGH so safe-range values export
546
- // as ordinary numbers (an early BigInt return here leaked '0' strings
547
- // into values interchange - fixed 2026-07-23).
548
- if (!signed && result < 0n) result = 0n;
549
-
550
- // Safe-range 64-bit values stay ordinary numbers so a JSON round trip
551
- // (GetValues → SetValues) reproduces the exported representation; BigInt
552
- // is reserved for magnitudes JSON numbers cannot hold.
553
- if (result >= MIN_SAFE_BIGINT && result <= MAX_SAFE_BIGINT) return Number(result);
554
- return result;
555
- }
556
-
557
- const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
558
-
559
- const MIN_SAFE_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
560
-
561
- function containerDescriptor(kind, cppType)
562
- {
563
- const elementCppType = extractTemplateArgument(cppType);
564
- return Object.freeze({
565
- kind,
566
- js: kind === CARBON_TYPE.MAP ? "Map" : kind === CARBON_TYPE.SET ? "Set" : "Array",
567
- cppType,
568
- elementType: elementCppType ? inferCarbonTypeFromCpp(elementCppType) : undefined
569
- });
570
- }
571
-
572
- function objectRefDescriptor(cppType)
573
- {
574
- return Object.freeze({ ...TYPE_DEFINITIONS[CARBON_TYPE.OBJECT_REF], cppType });
575
- }
576
-
577
- function rawStructDescriptor(cppType)
578
- {
579
- return Object.freeze({ ...TYPE_DEFINITIONS[CARBON_TYPE.RAW_STRUCT], cppType });
580
- }
581
-
582
- function extractTemplateArgument(cppType)
583
- {
584
- const match = String(cppType || "").match(/<(.+)>/);
585
- return match ? match[1].trim() : null;
586
- }
587
-
588
- function normalizeCppType(cppType)
589
- {
590
- return String(cppType || "")
591
- .replace(/\bconst\b/g, "")
592
- .replace(/&/g, "")
593
- .replace(/\s+/g, " ")
594
- .trim();
595
- }
596
-
597
- function normalizeCppTypeName(cppType)
598
- {
599
- return normalizeCppType(cppType)
600
- .replace(/\s*\*+$/, "")
601
- .replace(/\bstd::basic_string\s*<[^>]+>/g, "std::string")
602
- .trim();
603
- }
604
-
605
- function isRotationLike(name)
606
- {
607
- return /(?:^|[^A-Za-z0-9])(?:rotation|quat|quaternion)|(?:rotation|quat|quaternion)/i.test(String(name || ""));
608
- }
609
-
610
- function isExpressionLike(name)
611
- {
612
- return /(?:^|[^A-Za-z0-9])expression(?:$|[^A-Za-z0-9])|expression/i.test(String(name || ""));
613
- }
614
-
615
- function normalizeMathValues(value, length, defaults)
616
- {
617
- const result = Array.isArray(defaults) ? defaults.slice() : new Array(length).fill(0);
618
- const source = ArrayBuffer.isView(value) || Array.isArray(value) ? value : [];
619
- for (let i = 0; i < result.length && i < source.length; i++)
620
- {
621
- result[i] = num.float32(source[i]);
622
- }
623
- return result;
624
- }
625
-
626
- function formatJsNumber(value)
627
- {
628
- if (Object.is(value, -0)) return "-0";
629
- return Number.isFinite(value) ? String(value) : "0";
630
- }
631
-
632
- function isSourceShapedObject(value)
633
- {
634
- return Boolean(value && typeof value === "object" && typeof value._sourceClassName === "string");
635
- }
1
+ export const CARBON_META = Symbol.for("carbonenginejs.type");
2
+ export const CARBON_RAW_STRUCT_TYPE = Symbol.for("carbonenginejs.rawStructType");
3
+
4
+ export const CARBON_TYPE = Object.freeze({
5
+ UNKNOWN: "unknown",
6
+ BOOLEAN: "boolean",
7
+ STRING: "string",
8
+ PATH: "path",
9
+ EXPRESSION: "expression",
10
+ ENUM: "enum",
11
+ FLOAT32: "float32",
12
+ FLOAT64: "float64",
13
+ INT8: "int8",
14
+ UINT8: "uint8",
15
+ INT16: "int16",
16
+ UINT16: "uint16",
17
+ INT32: "int32",
18
+ UINT32: "uint32",
19
+ INT64: "int64",
20
+ UINT64: "uint64",
21
+ VECTOR2: "vector2",
22
+ VECTOR3: "vector3",
23
+ VECTOR4: "vector4",
24
+ COLOR: "color",
25
+ QUATERNION: "quaternion",
26
+ MATRIX3: "matrix3",
27
+ MATRIX4: "matrix4",
28
+ ARRAY: "array",
29
+ MAP: "map",
30
+ SET: "set",
31
+ MODEL: "model",
32
+ OBJECT_REF: "objectRef",
33
+ STRUCT: "struct",
34
+ RAW_STRUCT: "rawStruct",
35
+ TYPED_ARRAY: "typedArray"
36
+ });
37
+
38
+ const FLOAT32_VECTOR_DEFINITIONS = Object.freeze({
39
+ [CARBON_TYPE.VECTOR2]: Object.freeze({ kind: CARBON_TYPE.VECTOR2, js: "vec2", scalar: CARBON_TYPE.FLOAT32, length: 2, default: [0, 0] }),
40
+ [CARBON_TYPE.VECTOR3]: Object.freeze({ kind: CARBON_TYPE.VECTOR3, js: "vec3", scalar: CARBON_TYPE.FLOAT32, length: 3, default: [0, 0, 0] }),
41
+ [CARBON_TYPE.VECTOR4]: Object.freeze({ kind: CARBON_TYPE.VECTOR4, js: "vec4", scalar: CARBON_TYPE.FLOAT32, length: 4, default: [0, 0, 0, 0] }),
42
+ [CARBON_TYPE.COLOR]: Object.freeze({ kind: CARBON_TYPE.COLOR, js: "vec4", semantic: CARBON_TYPE.COLOR, scalar: CARBON_TYPE.FLOAT32, length: 4, default: [0, 0, 0, 0] }),
43
+ [CARBON_TYPE.QUATERNION]: Object.freeze({ kind: CARBON_TYPE.QUATERNION, js: "quat", scalar: CARBON_TYPE.FLOAT32, length: 4, default: [0, 0, 0, 1] }),
44
+ [CARBON_TYPE.MATRIX3]: Object.freeze({ kind: CARBON_TYPE.MATRIX3, js: "mat3", scalar: CARBON_TYPE.FLOAT32, length: 9, default: [1, 0, 0, 0, 1, 0, 0, 0, 1] }),
45
+ [CARBON_TYPE.MATRIX4]: Object.freeze({ kind: CARBON_TYPE.MATRIX4, js: "mat4", scalar: CARBON_TYPE.FLOAT32, length: 16, default: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] })
46
+ });
47
+
48
+ const TYPE_DEFINITIONS = Object.freeze({
49
+ [CARBON_TYPE.UNKNOWN]: Object.freeze({ kind: CARBON_TYPE.UNKNOWN, js: "*" }),
50
+ [CARBON_TYPE.BOOLEAN]: Object.freeze({ kind: CARBON_TYPE.BOOLEAN, js: "boolean" }),
51
+ [CARBON_TYPE.STRING]: Object.freeze({ kind: CARBON_TYPE.STRING, js: "string" }),
52
+ [CARBON_TYPE.PATH]: Object.freeze({ kind: CARBON_TYPE.PATH, js: "string" }),
53
+ [CARBON_TYPE.EXPRESSION]: Object.freeze({ kind: CARBON_TYPE.EXPRESSION, js: "string", semantic: CARBON_TYPE.EXPRESSION }),
54
+ [CARBON_TYPE.ENUM]: Object.freeze({ kind: CARBON_TYPE.ENUM, js: "number|string|null" }),
55
+ [CARBON_TYPE.FLOAT32]: Object.freeze({ kind: CARBON_TYPE.FLOAT32, js: "number", bits: 32, signed: true, floating: true }),
56
+ [CARBON_TYPE.FLOAT64]: Object.freeze({ kind: CARBON_TYPE.FLOAT64, js: "number", bits: 64, signed: true, floating: true }),
57
+ [CARBON_TYPE.INT8]: Object.freeze({ kind: CARBON_TYPE.INT8, js: "number", bits: 8, signed: true, integer: true }),
58
+ [CARBON_TYPE.UINT8]: Object.freeze({ kind: CARBON_TYPE.UINT8, js: "number", bits: 8, signed: false, integer: true }),
59
+ [CARBON_TYPE.INT16]: Object.freeze({ kind: CARBON_TYPE.INT16, js: "number", bits: 16, signed: true, integer: true }),
60
+ [CARBON_TYPE.UINT16]: Object.freeze({ kind: CARBON_TYPE.UINT16, js: "number", bits: 16, signed: false, integer: true }),
61
+ [CARBON_TYPE.INT32]: Object.freeze({ kind: CARBON_TYPE.INT32, js: "number", bits: 32, signed: true, integer: true }),
62
+ [CARBON_TYPE.UINT32]: Object.freeze({ kind: CARBON_TYPE.UINT32, js: "number", bits: 32, signed: false, integer: true }),
63
+ [CARBON_TYPE.INT64]: Object.freeze({ kind: CARBON_TYPE.INT64, js: "bigint", bits: 64, signed: true, integer: true }),
64
+ [CARBON_TYPE.UINT64]: Object.freeze({ kind: CARBON_TYPE.UINT64, js: "bigint", bits: 64, signed: false, integer: true }),
65
+ [CARBON_TYPE.ARRAY]: Object.freeze({ kind: CARBON_TYPE.ARRAY, js: "Array" }),
66
+ [CARBON_TYPE.MAP]: Object.freeze({ kind: CARBON_TYPE.MAP, js: "Map" }),
67
+ [CARBON_TYPE.SET]: Object.freeze({ kind: CARBON_TYPE.SET, js: "Set" }),
68
+ [CARBON_TYPE.MODEL]: Object.freeze({ kind: CARBON_TYPE.MODEL, js: "object|null" }),
69
+ [CARBON_TYPE.OBJECT_REF]: Object.freeze({ kind: CARBON_TYPE.OBJECT_REF, js: "object|null" }),
70
+ [CARBON_TYPE.STRUCT]: Object.freeze({ kind: CARBON_TYPE.STRUCT, js: "object" }),
71
+ [CARBON_TYPE.RAW_STRUCT]: Object.freeze({ kind: CARBON_TYPE.RAW_STRUCT, js: "object" }),
72
+ [CARBON_TYPE.TYPED_ARRAY]: Object.freeze({ kind: CARBON_TYPE.TYPED_ARRAY, js: "TypedArray" }),
73
+ ...FLOAT32_VECTOR_DEFINITIONS
74
+ });
75
+
76
+ const TYPE_ALIASES = Object.freeze({
77
+ bool: CARBON_TYPE.BOOLEAN,
78
+ float: CARBON_TYPE.FLOAT32,
79
+ double: CARBON_TYPE.FLOAT64,
80
+ vec2: CARBON_TYPE.VECTOR2,
81
+ vec3: CARBON_TYPE.VECTOR3,
82
+ vec4: CARBON_TYPE.VECTOR4,
83
+ quat: CARBON_TYPE.QUATERNION,
84
+ mat3: CARBON_TYPE.MATRIX3,
85
+ mat4: CARBON_TYPE.MATRIX4
86
+ });
87
+
88
+ const TYPED_ARRAY_CTORS = Object.freeze({
89
+ Int8Array,
90
+ Uint8Array,
91
+ Uint8ClampedArray,
92
+ Int16Array,
93
+ Uint16Array,
94
+ Int32Array,
95
+ Uint32Array,
96
+ Float32Array,
97
+ Float64Array,
98
+ BigInt64Array,
99
+ BigUint64Array
100
+ });
101
+
102
+ const num = Object.freeze({
103
+ int8,
104
+ uint8,
105
+ int16,
106
+ uint16,
107
+ int32,
108
+ uint32,
109
+ int64,
110
+ uint64,
111
+ float32,
112
+ float64
113
+ });
114
+
115
+ const CARBON_MATH_KINDS = new Set(Object.keys(FLOAT32_VECTOR_DEFINITIONS));
116
+
117
+ export function createCarbonMathValue(type, value = undefined)
118
+ {
119
+ const descriptor = normalizeCarbonTypeDescriptor(type);
120
+ const values = normalizeMathValues(value, descriptor.length, descriptor.default);
121
+
122
+ // Carbon math values are plain Float32Arrays. Their descriptors remain
123
+ // independent of the gl-matrix-backed math helpers. Defaults already
124
+ // encode identity/zero, matching gl-matrix's create() output.
125
+ return CARBON_MATH_KINDS.has(descriptor.kind) ? Float32Array.from(values) : values;
126
+ }
127
+
128
+ /**
129
+ * Coerce a math value INTO an existing Float32Array target, in place, with no
130
+ * allocation. Returns `true`/`false` (whether any element changed) when the fast
131
+ * path applies — a math kind, `target` a compatible Float32Array, and `value`
132
+ * array-like. Returns `null` when it does not apply (non-math kind, incompatible
133
+ * or absent target, or a null/undefined value) so the caller falls back to a
134
+ * normal allocating assignment.
135
+ */
136
+ export function coerceCarbonMathInto(target, value, type)
137
+ {
138
+ const descriptor = normalizeCarbonTypeDescriptor(type);
139
+ if (!CARBON_MATH_KINDS.has(descriptor.kind)) return null;
140
+ if (!(target instanceof Float32Array) || target.length !== descriptor.length) return null;
141
+
142
+ const source = ArrayBuffer.isView(value) || Array.isArray(value) ? value : null;
143
+ if (!source) return null;
144
+
145
+ const defaults = descriptor.default;
146
+ let changed = false;
147
+ for (let i = 0; i < descriptor.length; i++)
148
+ {
149
+ const next = num.float32(i < source.length ? source[i] : defaults[i]);
150
+ if (target[i] !== next)
151
+ {
152
+ target[i] = next;
153
+ changed = true;
154
+ }
155
+ }
156
+ return changed;
157
+ }
158
+
159
+ export function getCarbonTypeDefinition(type)
160
+ {
161
+ const descriptor = normalizeCarbonTypeDescriptor(type);
162
+ return TYPE_DEFINITIONS[descriptor.kind] || TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
163
+ }
164
+
165
+ export function normalizeCarbonTypeDescriptor(type)
166
+ {
167
+ if (!type) return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
168
+ if (typeof type === "string") return carbonTypeDefinitionForKind(type);
169
+ if (type.kind) return mergeCarbonTypeDefinition(type);
170
+ if (type.jsType) return normalizeCarbonTypeDescriptor(type.jsType);
171
+ if (type.cppType) return inferCarbonTypeFromCpp(type.cppType, type.name);
172
+ if (type.pythonType) return inferCarbonTypeFromPython(type.pythonType);
173
+ return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
174
+ }
175
+
176
+ export function inferCarbonTypeFromCpp(cppType, propertyName = "")
177
+ {
178
+ const original = String(cppType || "").trim();
179
+ const type = normalizeCppType(original);
180
+ const named = normalizeCppTypeName(original);
181
+
182
+ if (!type) return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
183
+ if (type.includes("std::vector") || /(?:Vector|List)$/.test(named)) return containerDescriptor(CARBON_TYPE.ARRAY, original);
184
+ if (type.includes("std::map") || /(?:Map)$/.test(named)) return containerDescriptor(CARBON_TYPE.MAP, original);
185
+ if (type.includes("std::set") || /(?:Set)$/.test(named)) return containerDescriptor(CARBON_TYPE.SET, original);
186
+ if (/\*$/.test(type) || /^P(?:I)?[A-Z]\w+$/.test(named) || /(?:Ptr|Ref)$/.test(named)) return objectRefDescriptor(original);
187
+
188
+ switch (named)
189
+ {
190
+ case "bool":
191
+ return TYPE_DEFINITIONS[CARBON_TYPE.BOOLEAN];
192
+ case "char":
193
+ case "int8_t":
194
+ return TYPE_DEFINITIONS[CARBON_TYPE.INT8];
195
+ case "uint8_t":
196
+ case "byte":
197
+ return TYPE_DEFINITIONS[CARBON_TYPE.UINT8];
198
+ case "int16_t":
199
+ case "short":
200
+ return TYPE_DEFINITIONS[CARBON_TYPE.INT16];
201
+ case "uint16_t":
202
+ case "ushort":
203
+ return TYPE_DEFINITIONS[CARBON_TYPE.UINT16];
204
+ case "int":
205
+ case "int32_t":
206
+ case "long":
207
+ return TYPE_DEFINITIONS[CARBON_TYPE.INT32];
208
+ case "uint":
209
+ case "uint32_t":
210
+ case "ulong":
211
+ return TYPE_DEFINITIONS[CARBON_TYPE.UINT32];
212
+ case "int64_t":
213
+ case "longlong":
214
+ return TYPE_DEFINITIONS[CARBON_TYPE.INT64];
215
+ case "uint64_t":
216
+ case "size_t":
217
+ case "ulonglong":
218
+ return TYPE_DEFINITIONS[CARBON_TYPE.UINT64];
219
+ case "float":
220
+ return TYPE_DEFINITIONS[CARBON_TYPE.FLOAT32];
221
+ case "double":
222
+ return TYPE_DEFINITIONS[CARBON_TYPE.FLOAT64];
223
+ case "std::string":
224
+ case "std::wstring":
225
+ case "BlueSharedString":
226
+ return isExpressionLike(propertyName) ? TYPE_DEFINITIONS[CARBON_TYPE.EXPRESSION] : TYPE_DEFINITIONS[CARBON_TYPE.STRING];
227
+ case "Vector2":
228
+ return TYPE_DEFINITIONS[CARBON_TYPE.VECTOR2];
229
+ case "Vector3":
230
+ return TYPE_DEFINITIONS[CARBON_TYPE.VECTOR3];
231
+ case "Vector4":
232
+ return isRotationLike(propertyName) ? TYPE_DEFINITIONS[CARBON_TYPE.QUATERNION] : TYPE_DEFINITIONS[CARBON_TYPE.VECTOR4];
233
+ case "Color":
234
+ case "ColorRGBA":
235
+ return TYPE_DEFINITIONS[CARBON_TYPE.COLOR];
236
+ case "Quaternion":
237
+ return TYPE_DEFINITIONS[CARBON_TYPE.QUATERNION];
238
+ case "Matrix3":
239
+ case "Mat3":
240
+ return TYPE_DEFINITIONS[CARBON_TYPE.MATRIX3];
241
+ case "Matrix":
242
+ case "Matrix4":
243
+ case "Mat4":
244
+ case "TriMatrix":
245
+ return TYPE_DEFINITIONS[CARBON_TYPE.MATRIX4];
246
+ default:
247
+ break;
248
+ }
249
+
250
+ if (/::[A-Za-z_]\w*(?:Type|Usage|Mode|Enum)$/.test(type)) return TYPE_DEFINITIONS[CARBON_TYPE.ENUM];
251
+ if (type.includes("::")) return rawStructDescriptor(original);
252
+ if (/^[A-Z]\w*(?:Type|Usage|Mode|Enum)?$/.test(named)) return TYPE_DEFINITIONS[CARBON_TYPE.ENUM];
253
+ return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
254
+ }
255
+
256
+ export function inferCarbonTypeFromPython(pythonType)
257
+ {
258
+ const type = String(pythonType || "").trim().toLowerCase();
259
+ if (!type) return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
260
+ if (type === "bool" || type === "boolean") return TYPE_DEFINITIONS[CARBON_TYPE.BOOLEAN];
261
+ if (type === "str" || type === "unicode" || type === "bytes") return TYPE_DEFINITIONS[CARBON_TYPE.STRING];
262
+ if (type === "float") return TYPE_DEFINITIONS[CARBON_TYPE.FLOAT64];
263
+ if (type === "int" || type === "long") return TYPE_DEFINITIONS[CARBON_TYPE.INT64];
264
+ if (type === "list" || type === "tuple") return TYPE_DEFINITIONS[CARBON_TYPE.ARRAY];
265
+ if (type === "dict") return TYPE_DEFINITIONS[CARBON_TYPE.MAP];
266
+ if (type === "set") return TYPE_DEFINITIONS[CARBON_TYPE.SET];
267
+ if (type === "none" || type === "nonetype") return objectRefDescriptor("NoneType");
268
+ return TYPE_DEFINITIONS[CARBON_TYPE.UNKNOWN];
269
+ }
270
+
271
+ export function defaultValueForCarbonField(field)
272
+ {
273
+ if (field && field.default && field.default.kind !== "expression")
274
+ {
275
+ return normalizeCarbonValue(field.default.json, field);
276
+ }
277
+ return defaultCarbonValue(field);
278
+ }
279
+
280
+ export function defaultCarbonValue(type)
281
+ {
282
+ const descriptor = normalizeCarbonTypeDescriptor(type);
283
+ switch (descriptor.kind)
284
+ {
285
+ case CARBON_TYPE.BOOLEAN:
286
+ return false;
287
+ case CARBON_TYPE.STRING:
288
+ case CARBON_TYPE.PATH:
289
+ case CARBON_TYPE.EXPRESSION:
290
+ return "";
291
+ case CARBON_TYPE.FLOAT32:
292
+ return num.float32(0);
293
+ case CARBON_TYPE.FLOAT64:
294
+ return num.float64(0);
295
+ case CARBON_TYPE.INT8:
296
+ return num.int8(0);
297
+ case CARBON_TYPE.UINT8:
298
+ return num.uint8(0);
299
+ case CARBON_TYPE.INT16:
300
+ return num.int16(0);
301
+ case CARBON_TYPE.UINT16:
302
+ return num.uint16(0);
303
+ case CARBON_TYPE.INT32:
304
+ return num.int32(0);
305
+ case CARBON_TYPE.UINT32:
306
+ return num.uint32(0);
307
+ case CARBON_TYPE.INT64:
308
+ return num.int64(0);
309
+ case CARBON_TYPE.UINT64:
310
+ return num.uint64(0);
311
+ case CARBON_TYPE.VECTOR2:
312
+ case CARBON_TYPE.VECTOR3:
313
+ case CARBON_TYPE.VECTOR4:
314
+ case CARBON_TYPE.COLOR:
315
+ case CARBON_TYPE.QUATERNION:
316
+ case CARBON_TYPE.MATRIX3:
317
+ case CARBON_TYPE.MATRIX4:
318
+ return createCarbonMathValue(descriptor);
319
+ case CARBON_TYPE.ARRAY:
320
+ return [];
321
+ case CARBON_TYPE.MAP:
322
+ return new Map();
323
+ case CARBON_TYPE.SET:
324
+ return new Set();
325
+ case CARBON_TYPE.ENUM:
326
+ case CARBON_TYPE.MODEL:
327
+ case CARBON_TYPE.OBJECT_REF:
328
+ case CARBON_TYPE.STRUCT:
329
+ case CARBON_TYPE.RAW_STRUCT:
330
+ case CARBON_TYPE.UNKNOWN:
331
+ default:
332
+ return null;
333
+ }
334
+ }
335
+
336
+ export function normalizeCarbonValue(value, type)
337
+ {
338
+ const descriptor = normalizeCarbonTypeDescriptor(type);
339
+ if (value === undefined) return defaultCarbonValue(descriptor);
340
+ if (value === null) return null;
341
+
342
+ switch (descriptor.kind)
343
+ {
344
+ case CARBON_TYPE.BOOLEAN:
345
+ return Boolean(value);
346
+ case CARBON_TYPE.STRING:
347
+ case CARBON_TYPE.PATH:
348
+ case CARBON_TYPE.EXPRESSION:
349
+ return String(value);
350
+ case CARBON_TYPE.FLOAT32:
351
+ return num.float32(value);
352
+ case CARBON_TYPE.FLOAT64:
353
+ return num.float64(value);
354
+ case CARBON_TYPE.INT8:
355
+ return num.int8(value);
356
+ case CARBON_TYPE.UINT8:
357
+ return num.uint8(value);
358
+ case CARBON_TYPE.INT16:
359
+ return num.int16(value);
360
+ case CARBON_TYPE.UINT16:
361
+ return num.uint16(value);
362
+ case CARBON_TYPE.INT32:
363
+ return num.int32(value);
364
+ case CARBON_TYPE.UINT32:
365
+ return num.uint32(value);
366
+ case CARBON_TYPE.INT64:
367
+ return num.int64(value);
368
+ case CARBON_TYPE.UINT64:
369
+ return num.uint64(value);
370
+ case CARBON_TYPE.VECTOR2:
371
+ case CARBON_TYPE.VECTOR3:
372
+ case CARBON_TYPE.VECTOR4:
373
+ case CARBON_TYPE.COLOR:
374
+ case CARBON_TYPE.QUATERNION:
375
+ case CARBON_TYPE.MATRIX3:
376
+ case CARBON_TYPE.MATRIX4:
377
+ return createCarbonMathValue(descriptor, value);
378
+ case CARBON_TYPE.ARRAY:
379
+ return Array.isArray(value) ? value.map(cloneCarbonValue) : [cloneCarbonValue(value)];
380
+ case CARBON_TYPE.MAP:
381
+ return value instanceof Map ? cloneCarbonValue(value) : new Map(Object.entries(value || {}));
382
+ case CARBON_TYPE.SET:
383
+ return value instanceof Set ? new Set(value) : new Set(Array.isArray(value) ? value : [value]);
384
+ default:
385
+ return cloneCarbonValue(value);
386
+ }
387
+ }
388
+
389
+ export function cloneCarbonValue(value)
390
+ {
391
+ if (ArrayBuffer.isView(value)) return new value.constructor(value);
392
+ if (typeof value === "bigint") return value;
393
+ if (isSourceShapedObject(value)) return value;
394
+ if (value instanceof Map) return new Map(Array.from(value.entries()).map(([key, item]) => [key, cloneCarbonValue(item)]));
395
+ if (value instanceof Set) return new Set(Array.from(value.values()).map(cloneCarbonValue));
396
+ if (Array.isArray(value)) return value.map(cloneCarbonValue);
397
+ if (value && typeof value === "object")
398
+ {
399
+ const result = Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneCarbonValue(item)]));
400
+ if (isCarbonRawStruct(value)) return createCarbonRawStruct(getCarbonRawStructType(value), result);
401
+ return result;
402
+ }
403
+ return value;
404
+ }
405
+
406
+ export function exportCarbonValue(value)
407
+ {
408
+ if (ArrayBuffer.isView(value)) return Array.from(value, item => typeof item === "bigint" ? item.toString() : item);
409
+ if (typeof value === "bigint") return value.toString();
410
+ if (value instanceof Map) return Object.fromEntries(Array.from(value.entries()).map(([key, item]) => [key, exportCarbonValue(item)]));
411
+ if (value instanceof Set) return Array.from(value.values()).map(exportCarbonValue);
412
+ if (Array.isArray(value)) return value.map(exportCarbonValue);
413
+ if (value && typeof value === "object")
414
+ {
415
+ const result = Object.fromEntries(
416
+ Object.entries(value)
417
+ .filter(([key]) => !key.startsWith("_"))
418
+ .map(([key, item]) => [key, exportCarbonValue(item)])
419
+ );
420
+ if (isCarbonRawStruct(value)) result.$type = getCarbonRawStructType(value);
421
+ return result;
422
+ }
423
+ return value;
424
+ }
425
+
426
+ export function createCarbonRawStruct(typeName, values = {})
427
+ {
428
+ const result = { ...values };
429
+ Object.defineProperty(result, CARBON_META, {
430
+ value: CARBON_TYPE.RAW_STRUCT,
431
+ enumerable: false,
432
+ configurable: true
433
+ });
434
+ Object.defineProperty(result, CARBON_RAW_STRUCT_TYPE, {
435
+ value: typeName || null,
436
+ enumerable: false,
437
+ configurable: true
438
+ });
439
+ return result;
440
+ }
441
+
442
+ export function isCarbonRawStruct(value)
443
+ {
444
+ return Boolean(value && typeof value === "object" && value[CARBON_META] === CARBON_TYPE.RAW_STRUCT);
445
+ }
446
+
447
+ export function getCarbonRawStructType(value)
448
+ {
449
+ return isCarbonRawStruct(value) ? value[CARBON_RAW_STRUCT_TYPE] : null;
450
+ }
451
+
452
+ export function carbonValueToJsExpression(value)
453
+ {
454
+ if (ArrayBuffer.isView(value))
455
+ {
456
+ const values = Array.from(value, item => typeof item === "bigint" ? `${item}n` : formatJsNumber(item));
457
+ return `new ${value.constructor.name}([${values.join(", ")}])`;
458
+ }
459
+ if (typeof value === "bigint") return `${value}n`;
460
+ if (value instanceof Map) return "new Map()";
461
+ if (value instanceof Set) return "new Set()";
462
+ if (Array.isArray(value)) return `[${value.map(item => carbonValueToJsExpression(item)).join(", ")}]`;
463
+ if (value && typeof value === "object") return JSON.stringify(exportCarbonValue(value), null, 4);
464
+ return JSON.stringify(value);
465
+ }
466
+
467
+ export function typedArrayConstructor(name)
468
+ {
469
+ return TYPED_ARRAY_CTORS[name] || null;
470
+ }
471
+
472
+ function carbonTypeDefinitionForKind(kind)
473
+ {
474
+ const normalized = TYPE_ALIASES[kind] || kind;
475
+ return TYPE_DEFINITIONS[normalized] || Object.freeze({ kind: normalized, js: "*" });
476
+ }
477
+
478
+ function mergeCarbonTypeDefinition(type)
479
+ {
480
+ const definition = carbonTypeDefinitionForKind(type.kind);
481
+ return Object.freeze({ ...definition, ...type, kind: definition.kind });
482
+ }
483
+
484
+ function uint8(value)
485
+ {
486
+ return Number(value) & 0xff;
487
+ }
488
+
489
+ function int8(value)
490
+ {
491
+ const result = uint8(value);
492
+ return result > 0x7f ? result - 0x100 : result;
493
+ }
494
+
495
+ function uint16(value)
496
+ {
497
+ return Number(value) & 0xffff;
498
+ }
499
+
500
+ function int16(value)
501
+ {
502
+ const result = uint16(value);
503
+ return result > 0x7fff ? result - 0x10000 : result;
504
+ }
505
+
506
+ function uint32(value)
507
+ {
508
+ return Number(value) >>> 0;
509
+ }
510
+
511
+ function int32(value)
512
+ {
513
+ return Number(value) | 0;
514
+ }
515
+
516
+ function uint64(value)
517
+ {
518
+ return toBigInt(value, false);
519
+ }
520
+
521
+ function int64(value)
522
+ {
523
+ return toBigInt(value, true);
524
+ }
525
+
526
+ function float32(value)
527
+ {
528
+ const result = Number(value);
529
+ return Number.isFinite(result) ? result : 0;
530
+ }
531
+
532
+ function float64(value)
533
+ {
534
+ const result = Number(value);
535
+ return Number.isFinite(result) ? result : 0;
536
+ }
537
+
538
+ function toBigInt(value, signed)
539
+ {
540
+ let result = 0n;
541
+ if (typeof value === "bigint") result = value;
542
+ else if (typeof value === "number" && Number.isFinite(value)) result = BigInt(Math.trunc(value));
543
+ else if (typeof value === "string" && value.trim()) result = BigInt(value.trim());
544
+
545
+ // Clamp unsigned negatives but FALL THROUGH so safe-range values export
546
+ // as ordinary numbers (an early BigInt return here leaked '0' strings
547
+ // into values interchange - fixed 2026-07-23).
548
+ if (!signed && result < 0n) result = 0n;
549
+
550
+ // Safe-range 64-bit values stay ordinary numbers so a JSON round trip
551
+ // (GetValues → SetValues) reproduces the exported representation; BigInt
552
+ // is reserved for magnitudes JSON numbers cannot hold.
553
+ if (result >= MIN_SAFE_BIGINT && result <= MAX_SAFE_BIGINT) return Number(result);
554
+ return result;
555
+ }
556
+
557
+ const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
558
+
559
+ const MIN_SAFE_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
560
+
561
+ function containerDescriptor(kind, cppType)
562
+ {
563
+ const elementCppType = extractTemplateArgument(cppType);
564
+ return Object.freeze({
565
+ kind,
566
+ js: kind === CARBON_TYPE.MAP ? "Map" : kind === CARBON_TYPE.SET ? "Set" : "Array",
567
+ cppType,
568
+ elementType: elementCppType ? inferCarbonTypeFromCpp(elementCppType) : undefined
569
+ });
570
+ }
571
+
572
+ function objectRefDescriptor(cppType)
573
+ {
574
+ return Object.freeze({ ...TYPE_DEFINITIONS[CARBON_TYPE.OBJECT_REF], cppType });
575
+ }
576
+
577
+ function rawStructDescriptor(cppType)
578
+ {
579
+ return Object.freeze({ ...TYPE_DEFINITIONS[CARBON_TYPE.RAW_STRUCT], cppType });
580
+ }
581
+
582
+ function extractTemplateArgument(cppType)
583
+ {
584
+ const match = String(cppType || "").match(/<(.+)>/);
585
+ return match ? match[1].trim() : null;
586
+ }
587
+
588
+ function normalizeCppType(cppType)
589
+ {
590
+ return String(cppType || "")
591
+ .replace(/\bconst\b/g, "")
592
+ .replace(/&/g, "")
593
+ .replace(/\s+/g, " ")
594
+ .trim();
595
+ }
596
+
597
+ function normalizeCppTypeName(cppType)
598
+ {
599
+ return normalizeCppType(cppType)
600
+ .replace(/\s*\*+$/, "")
601
+ .replace(/\bstd::basic_string\s*<[^>]+>/g, "std::string")
602
+ .trim();
603
+ }
604
+
605
+ function isRotationLike(name)
606
+ {
607
+ return /(?:^|[^A-Za-z0-9])(?:rotation|quat|quaternion)|(?:rotation|quat|quaternion)/i.test(String(name || ""));
608
+ }
609
+
610
+ function isExpressionLike(name)
611
+ {
612
+ return /(?:^|[^A-Za-z0-9])expression(?:$|[^A-Za-z0-9])|expression/i.test(String(name || ""));
613
+ }
614
+
615
+ function normalizeMathValues(value, length, defaults)
616
+ {
617
+ const result = Array.isArray(defaults) ? defaults.slice() : new Array(length).fill(0);
618
+ const source = ArrayBuffer.isView(value) || Array.isArray(value) ? value : [];
619
+ for (let i = 0; i < result.length && i < source.length; i++)
620
+ {
621
+ result[i] = num.float32(source[i]);
622
+ }
623
+ return result;
624
+ }
625
+
626
+ function formatJsNumber(value)
627
+ {
628
+ if (Object.is(value, -0)) return "-0";
629
+ return Number.isFinite(value) ? String(value) : "0";
630
+ }
631
+
632
+ function isSourceShapedObject(value)
633
+ {
634
+ return Boolean(value && typeof value === "object" && typeof value._sourceClassName === "string");
635
+ }