Accueil / npm / three@0.186.1 / src / nodes / core / StructTypeNode.js
StructTypeNode.js
import Node from './Node.js';
import { getAlignmentFromType, getMemoryLengthFromType } from './NodeUtils.js';
/**
* Generates a layout for struct members.
* This function takes an object representing struct members and returns an array of member layouts.
* Each member layout includes the member's name, type, and whether it is atomic.
*
* @param {Object.<string, string|Object>} members - An object where keys are member names and values are either types (as strings) or objects with type and atomic properties.
* @returns {Array.<{name: string, type: string, atomic: boolean}>} An array of member layouts.
*/
function getMembersLayout( members ) {
return Object.entries( members ).map( ( [ name, value ] ) => {
if ( typeof value === 'string' ) {
return { name, type: value, atomic: false };
}
return { name, type: value.type, atomic: value.atomic || false };
} );
}
/**
* Represents a struct type node in the node-based system.
* This class is used to define and manage the layout and types of struct members.
* It extends the base Node class and provides methods to get the length of the struct,
* retrieve member types, and generate the struct type for a builder.
*
* @augments Node
*/
class StructTypeNode extends Node {
static get type() {
return 'StructTypeNode';
}
/**
* Creates an instance of StructTypeNode.
*
* @param {Object} membersLayout - The layout of the members for the struct.
* @param {?string} [name=null] - The optional name of the struct.
*/
constructor( membersLayout, name = null ) {
super( 'struct' );
/**
* The layout of the members for the struct
*
* @type {Array.<{name: string, type: string, atomic: boolean}>}
*/
this.membersLayout = getMembersLayout( membersLayout );
/**
* The name of the struct.
*
* @type {?string}
* @default null
*/
this.name = name;
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isStructTypeNode = true;
}
/**
* Returns the length of the struct in 4-byte elements (e.g. float or int components).
* The length is calculated by summing the lengths of the struct's members, accounting for memory alignment.
* To get the size in bytes, multiply the returned value by 4.
*
* @returns {number} The length of the struct in 4-byte elements.
*/
getLength() {
let maxAlignment = 1; // maximum alignment value in this struct
let offset = 0; // global buffer offset in 4 byte elements
for ( const member of this.membersLayout ) {
const type = member.type;
const itemSize = getMemoryLengthFromType( type );
const alignment = getAlignmentFromType( type );
maxAlignment = Math.max( maxAlignment, alignment );
const chunkOffset = offset % maxAlignment; // offset in the current chunk of maxAlignment elements
const overhang = chunkOffset % alignment; // distance from the last aligned offset
if ( overhang !== 0 ) {
offset += alignment - overhang; // move to next aligned offset
}
offset += itemSize;
}
return ( Math.ceil( offset / maxAlignment ) * maxAlignment ); // ensure length is a multiple of maxAlignment
}
getMemberType( builder, name ) {
const member = this.membersLayout.find( m => m.name === name );
return member ? member.type : 'void';
}
generateNodeType( builder ) {
const structType = builder.getStructTypeFromNode( this, this.membersLayout, this.name );
return structType.name;
}
setup( builder ) {
builder.getStructTypeFromNode( this, this.membersLayout, this.name );
builder.addInclude( this );
}
generate( builder ) {
return this.getNodeType( builder );
}
}
export default StructTypeNode;