(firstElement)
| 3472 | // structBody: everything inside the { ... } of a WGSL struct definition |
| 3473 | // stride: how many bytes are reserved for this struct in the buffer |
| 3474 | _inferStructSchema(firstElement) { |
| 3475 | const entries = Object.entries(firstElement); |
| 3476 | |
| 3477 | if (!p5.disableFriendlyErrors) { |
| 3478 | for (const [name, value] of entries) { |
| 3479 | if ( |
| 3480 | value !== null && |
| 3481 | typeof value === 'object' && |
| 3482 | !Array.isArray(value) && |
| 3483 | // Duck typing instead of instanceof to avoid importing a separate |
| 3484 | // copy of the Color/Vector classes |
| 3485 | !value?.isVector && |
| 3486 | !value?.isColor |
| 3487 | ) { |
| 3488 | p5._friendlyError( |
| 3489 | `The "${name}" property in your storage data contains a nested object. ` + |
| 3490 | `Make sure you only use properties with numbers, arrays of numbers, or p5.Vector.`, |
| 3491 | 'createStorage' |
| 3492 | ); |
| 3493 | } |
| 3494 | } |
| 3495 | } |
| 3496 | |
| 3497 | const fieldLines = entries.map(([name, value]) => |
| 3498 | ` ${name}: ${this._jsValueToWgslType(value)},` |
| 3499 | ).join('\n'); |
| 3500 | const structBody = `{\n${fieldLines}\n}`; |
| 3501 | const elements = this._parseStruct(`struct _Tmp ${structBody}`, '_Tmp'); |
| 3502 | |
| 3503 | let maxEnd = 0; |
| 3504 | let maxAlign = 1; |
| 3505 | const fields = entries.map(([name, value]) => { |
| 3506 | const el = elements[name]; |
| 3507 | maxEnd = Math.max(maxEnd, el.offsetEnd); |
| 3508 | // Alignment for scalars/vectors: <=4 -> 4, <=8 -> 8, else 16 |
| 3509 | const align = el.size <= 4 ? 4 : el.size <= 8 ? 8 : 16; |
| 3510 | maxAlign = Math.max(maxAlign, align); |
| 3511 | // Track original JS type for reconstruction during readback |
| 3512 | const kind = value?.isVector ? 'vector' |
| 3513 | : value?.isColor ? 'color' |
| 3514 | : undefined; |
| 3515 | return { |
| 3516 | name, |
| 3517 | baseType: el.baseType, |
| 3518 | size: el.size, |
| 3519 | offset: el.offset, |
| 3520 | packInPlace: el.packInPlace ?? false, |
| 3521 | dim: el.size / 4, |
| 3522 | kind, |
| 3523 | }; |
| 3524 | }); |
| 3525 | |
| 3526 | const stride = Math.ceil(maxEnd / maxAlign) * maxAlign; |
| 3527 | return { fields, stride, structBody }; |
| 3528 | } |
| 3529 | |
| 3530 | // Packs an array of plain objects into a Float32Array using the given struct schema. |
| 3531 | // Reuses _packField so layout rules match uniform packing exactly. |
no test coverage detected