<commit_before>/*
entity/transform - Transform component
Part of Stardazed
(c) 2015-Present by <NAME> - @zenmumbler
https://github.com/stardazed/stardazed
*/

import { Float, SInt32 } from "stardazed/core";
import { MultiArrayBuffer, StructField, InvalidatePointers } from "stardazed/container";
import { mat4, vec3, quat, copyIndexedVec3, copyIndexedVec4, refIndexedMat4, copyIndexedMat4 } from "stardazed/vector";
import { Component, Instance, InstanceRange, InstanceArrayView, InstanceLinearRange } from "./instance";
import { Entity, EntityArrayView, entityIndex } from "./entity";

export interface Transform {
	position: Float3;
	rotation?: Float4; // quat
	scale?: Float3;
}

export type TransformInstance = Instance<TransformComponent>;
export type TransformRange = InstanceRange<TransformComponent>;
// export type TransformSet = InstanceSet<TransformComponent>;
// export type TransformIterator = InstanceIterator<TransformComponent>;
export type TransformArrayView = InstanceArrayView<TransformComponent>;

export class TransformComponent implements Component<TransformComponent> {
	private instanceData_: MultiArrayBuffer;

	private entityBase_!: EntityArrayView;

	private parentBase_!: TransformArrayView;
	private firstChildBase_!: TransformArrayView;
	private prevSiblingBase_!: TransformArrayView;
	private nextSiblingBase_!: TransformArrayView;

	private positionBase_!: Float32Array;
	private rotationBase_!: Float32Array;
	private scaleBase_!: Float32Array;
	private localMatrixBase_!: Float32Array;
	private worldMatrixBase_!: Float32Array;

	private readonly defaultPos_: Float3 = vec3.zero();
	private readonly defaultRot_: Float4 = quat.create();
	private readonly defaultScale_: Float3 = vec3.one();

	constructor() {
		const instanceFields: StructField[] = [
			{ type: SInt32, width: 1 }, // entity

			{ type: SInt32, width: 1 }, // parentInstance
			{ type: SInt32, width: 1 }, // firstChild
			{ type: SInt32, width: 1 }, // prevSibling
			{ type: SInt32, width: 1 }, // nextSibling

			{ type: Float, width: 3 },  // position
			{ type: Float, width: 4 },  // rotation
			{ type: Float, width: 3 },  // scale

			{ type: Float, width: 16 }, // localMatrix
			{ type: Float, width: 16 }  // worldMatrix
		];
		this.instanceData_ = new MultiArrayBuffer(instanceFields, 2048); // 376 KiB

		this.rebase();
	}

	rebase() {
		this.entityBase_ = this.instanceData_.arrayFieldView(0);

		this.parentBase_ = this.instanceData_.arrayFieldView(1);
		this.firstChildBase_ = this.instanceData_.arrayFieldView(2);
		this.prevSiblingBase_ = this.instanceData_.arrayFieldView(3);
		this.nextSiblingBase_ = this.instanceData_.arrayFieldView(4);

		this.positionBase_ = this.instanceData_.arrayFieldView(5) as Float32Array;
		this.rotationBase_ = this.instanceData_.arrayFieldView(6) as Float32Array;
		this.scaleBase_ = this.instanceData_.arrayFieldView(7) as Float32Array;

		this.localMatrixBase_ = this.instanceData_.arrayFieldView(8) as Float32Array;
		this.worldMatrixBase_ = this.instanceData_.arrayFieldView(9) as Float32Array;
	}


	create(linkedEntity: Entity, parent?: TransformInstance): TransformInstance;
	create(linkedEntity: Entity, desc?: Transform, parent?: TransformInstance): TransformInstance;
	create(linkedEntity: Entity, descOrParent?: Transform | TransformInstance, parent?: TransformInstance): TransformInstance {
		const entIndex = entityIndex(linkedEntity);

		if (this.instanceData_.count < entIndex) {
			if (this.instanceData_.resize(entIndex) === InvalidatePointers.Yes) {
				this.rebase();
			}
		}

		const thisInstance = entIndex;
		let parentInstance = 0;
		let descriptor: Transform | null = null;

		this.entityBase_[thisInstance] = linkedEntity;

		if (descOrParent) {
			if (typeof descOrParent === "number") {
				parentInstance = descOrParent as number;
			}
			else {
				descriptor = descOrParent as Transform;
				parentInstance = parent as number; // can be 0
			}
		}
		else if (typeof parent === "number") {
			parentInstance = parent as number;
		}

		if (parentInstance) {
			this.parentBase_[thisInstance] = parentInstance;
			let myPrevSibling = this.firstChildBase_[parentInstance] as number;

			if (myPrevSibling) {
				// assert(this.prevSiblingBase_[myPrevSibling] === 0, "firstChild cannot have prev siblings");

				// find end of child chain
				while (this.nextSiblingBase_[myPrevSibling] !== 0) {
					myPrevSibling = this.nextSiblingBase_[myPrevSibling] as number;
				}

				// append self to parent's child list
				this.nextSiblingBase_[myPrevSibling] = thisInstance;
				this.prevSiblingBase_[thisInstance] = myPrevSibling;
			}
			else {
				this.firstChildBase_[parentInstance] = thisInstance;
				this.prevSiblingBase_[thisInstance] = 0;
				this.nextSiblingBase_[thisInstance] = 0;
			}
		}
		else {
			this.parentBase_[thisInstance] = 0;
			this.prevSiblingBase_[thisInstance] = 0;
			this.nextSiblingBase_[thisInstance] = 0;
		}


		if (descriptor) {
			// optional descriptor fields
			const rotation = descriptor.rotation || this.defaultRot_;
			const scale = descriptor.scale || this.defaultScale_;

			this.positionBase_.set(descriptor.position, thisInstance * vec3.ELEMENT_COUNT);
			this.rotationBase_.set(rotation, thisInstance * quat.ELEMENT_COUNT);
			this.scaleBase_.set(scale, thisInstance * vec3.ELEMENT_COUNT);

			this.setLocalMatrix(thisInstance, rotation, descriptor.position, scale);
		}
		else {
			this.positionBase_.set(this.defaultPos_, thisInstance * quat.ELEMENT_COUNT);
			this.rotationBase_.set(this.defaultRot_, thisInstance * quat.ELEMENT_COUNT);
			this.scaleBase_.set(this.defaultScale_, thisInstance * vec3.ELEMENT_COUNT);

			this.setLocalMatrix(thisInstance, this.defaultRot_, this.defaultPos_, this.defaultScale_);
		}

		return thisInstance;
	}


	destroy(_inst: TransformInstance) {
		// TBI
	}


	destroyRange(range: TransformRange) {
		const iter = range.makeIterator();
		while (iter.next()) {
			this.destroy(iter.current);
		}
	}


	get count() { return this.instanceData_.count; }

	valid(inst: TransformInstance) {
		return inst as number <= this.count;
	}

	all(): TransformRange {
		return new InstanceLinearRange<TransformComponent>(1, this.count);
	}


	// Entity -> TransformInstance mapping
	forEntity(ent: Entity): TransformInstance {
		const index = entityIndex(ent);
		if (index > 0 && index <= this.instanceData_.count) {
			return ent as Instance<any> as TransformInstance;
		}

		// assert(false, `No transform for entity ${index}`);
		return 0;
	}


	// -- single instance getters
	entity(inst: TransformInstance): Entity { return this.entityBase_[inst as number]; }

	parent(inst: TransformInstance): TransformInstance { return this.parentBase_[inst as number]; }
	firstChild(inst: TransformInstance): TransformInstance { return this.firstChildBase_[inst as number]; }
	prevSibling(inst: TransformInstance): TransformInstance { return this.prevSiblingBase_[inst as number]; }
	nextSibling(inst: TransformInstance): TransformInstance { return this.nextSiblingBase_[inst as number]; }

	localPosition(inst: TransformInstance) { return copyIndexedVec3(this.positionBase_, inst as number); }
	localRotation(inst: TransformInstance) { return copyIndexedVec4(this.rotationBase_, inst as number); }
	localScale(inst: TransformInstance) { return copyIndexedVec3(this.scaleBase_, inst as number); }

	worldPosition(inst: TransformInstance): number[] {
		const matOffset = inst as number * 16;
		return [this.worldMatrixBase_[matOffset + 12], this.worldMatrixBase_[matOffset + 13], this.worldMatrixBase_[matOffset + 14]];
	}

	localMatrix(inst: TransformInstance) { return refIndexedMat4(this.localMatrixBase_, inst as number); }
	worldMatrix(inst: TransformInstance) { return refIndexedMat4(this.worldMatrixBase_, inst as number); }
<commit_msg>ref(entity): remove linkage from Trasform<commit_after>/*
entity/transform - Transform component
Part of Stardazed
(c) 2015-Present by <NAME> - @zenmumbler
https://github.com/stardazed/stardazed
*/

import { Float, SInt32 } from "stardazed/core";
import { MultiArrayBuffer, StructField, InvalidatePointers } from "stardazed/container";
import { mat4, vec3, quat, copyIndexedVec3, copyIndexedVec4, refIndexedMat4, copyIndexedMat4 } from "stardazed/vector";
import { Component, Instance, InstanceRange, InstanceArrayView, InstanceLinearRange } from "./instance";

export interface TransformDesc {
	position: Float3;
	rotation?: Float4; // quat
	scale?: Float3;
}

export type TransformInstance = Instance<TransformComponent>;
export type TransformRange = InstanceRange<TransformComponent>;
// export type TransformSet = InstanceSet<TransformComponent>;
// export type TransformIterator = InstanceIterator<TransformComponent>;
export type TransformArrayView = InstanceArrayView<TransformComponent>;

export class TransformComponent implements Component<TransformComponent> {
	private instanceData_: MultiArrayBuffer;

	private parentBase_!: TransformArrayView;
	private firstChildBase_!: TransformArrayView;
	private prevSiblingBase_!: TransformArrayView;
	private nextSiblingBase_!: TransformArrayView;

	private positionBase_!: Float32Array;
	private rotationBase_!: Float32Array;
	private scaleBase_!: Float32Array;
	private localMatrixBase_!: Float32Array;
	private worldMatrixBase_!: Float32Array;

	private readonly defaultPos_: Float3 = vec3.zero();
	private readonly defaultRot_: Float4 = quat.create();
	private readonly defaultScale_: Float3 = vec3.one();

	constructor() {
		const instanceFields: StructField[] = [
			{ type: SInt32, width: 1 }, // parentInstance
			{ type: SInt32, width: 1 }, // firstChild
			{ type: SInt32, width: 1 }, // prevSibling
			{ type: SInt32, width: 1 }, // nextSibling

			{ type: Float, width: 3 },  // position
			{ type: Float, width: 4 },  // rotation
			{ type: Float, width: 3 },  // scale

			{ type: Float, width: 16 }, // localMatrix
			{ type: Float, width: 16 }  // worldMatrix
		];
		this.instanceData_ = new MultiArrayBuffer(instanceFields, 2048); // 376 KiB

		this.rebase();
	}

	rebase() {
		this.parentBase_ = this.instanceData_.arrayFieldView(0);
		this.firstChildBase_ = this.instanceData_.arrayFieldView(1);
		this.prevSiblingBase_ = this.instanceData_.arrayFieldView(2);
		this.nextSiblingBase_ = this.instanceData_.arrayFieldView(3);

		this.positionBase_ = this.instanceData_.arrayFieldView(4) as Float32Array;
		this.rotationBase_ = this.instanceData_.arrayFieldView(5) as Float32Array;
		this.scaleBase_ = this.instanceData_.arrayFieldView(6) as Float32Array;

		this.localMatrixBase_ = this.instanceData_.arrayFieldView(7) as Float32Array;
		this.worldMatrixBase_ = this.instanceData_.arrayFieldView(8) as Float32Array;
	}


	create(linkedEntity: Entity, parent?: TransformInstance): TransformInstance;
	create(linkedEntity: Entity, desc?: Transform, parent?: TransformInstance): TransformInstance;
	create(linkedEntity: Entity, descOrParent?: Transform | TransformInstance, parent?: TransformInstance): TransformInstance {
		if (this.instanceData_.extend() === InvalidatePointers.Yes) {
			this.rebase();
		}

		let parentInstance = 0;
		let descriptor: Transform | null = null;

		if (descOrParent) {
			if (typeof descOrParent === "number") {
				parentInstance = descOrParent as number;
			}
			else {
				descriptor = descOrParent as Transform;
				parentInstance = parent as number; // can be 0
			}
		}
		else if (typeof parent === "number") {
			parentInstance = parent as number;
		}
		const thisInstance = this.instanceData_.count;

		if (parentInstance) {
			this.parentBase_[thisInstance] = parentInstance;
			let myPrevSibling = this.firstChildBase_[parentInstance] as number;

			if (myPrevSibling) {
				// assert(this.prevSiblingBase_[myPrevSibling] === 0, "firstChild cannot have prev siblings");

				// find end of child chain
				while (this.nextSiblingBase_[myPrevSibling] !== 0) {
					myPrevSibling = this.nextSiblingBase_[myPrevSibling] as number;
				}

				// append self to parent's child list
				this.nextSiblingBase_[myPrevSibling] = thisInstance;
				this.prevSiblingBase_[thisInstance] = myPrevSibling;
			}
			else {
				this.firstChildBase_[parentInstance] = thisInstance;
				this.prevSiblingBase_[thisInstance] = 0;
				this.nextSiblingBase_[thisInstance] = 0;
			}
		}
		else {
			this.parentBase_[thisInstance] = 0;
			this.prevSiblingBase_[thisInstance] = 0;
			this.nextSiblingBase_[thisInstance] = 0;
		}


		if (descriptor) {
			// optional descriptor fields
			const rotation = descriptor.rotation || this.defaultRot_;
			const scale = descriptor.scale || this.defaultScale_;

			this.positionBase_.set(descriptor.position, thisInstance * vec3.ELEMENT_COUNT);
			this.rotationBase_.set(rotation, thisInstance * quat.ELEMENT_COUNT);
			this.scaleBase_.set(scale, thisInstance * vec3.ELEMENT_COUNT);

			this.setLocalMatrix(thisInstance, rotation, descriptor.position, scale);
		}
		else {
			this.positionBase_.set(this.defaultPos_, thisInstance * quat.ELEMENT_COUNT);
			this.rotationBase_.set(this.defaultRot_, thisInstance * quat.ELEMENT_COUNT);
			this.scaleBase_.set(this.defaultScale_, thisInstance * vec3.ELEMENT_COUNT);

			this.setLocalMatrix(thisInstance, this.defaultRot_, this.defaultPos_, this.defaultScale_);
		}

		return thisInstance;
	}


	destroy(_inst: TransformInstance) {
		// TBI
	}


	destroyRange(range: TransformRange) {
		const iter = range.makeIterator();
		while (iter.next()) {
			this.destroy(iter.current);
		}
	}


	get count() { return this.instanceData_.count; }

	valid(inst: TransformInstance) {
		return inst as number <= this.count;
	}

	all(): TransformRange {
		return new InstanceLinearRange<TransformComponent>(1, this.count);
	}

	// -- single instance getters
	parent(inst: TransformInstance): TransformInstance { return this.parentBase_[inst as number]; }
	firstChild(inst: TransformInstance): TransformInstance { return this.firstChildBase_[inst as number]; }
	prevSibling(inst: TransformInstance): TransformInstance { return this.prevSiblingBase_[inst as number]; }
	nextSibling(inst: TransformInstance): TransformInstance { return this.nextSiblingBase_[inst as number]; }

	localPosition(inst: TransformInstance) { return copyIndexedVec3(this.positionBase_, inst as number); }
	localRotation(inst: TransformInstance) { return copyIndexedVec4(this.rotationBase_, inst as number); }
	localScale(inst: TransformInstance) { return copyIndexedVec3(this.scaleBase_, inst as number); }

	worldPosition(inst: TransformInstance): number[] {
		const matOffset = inst as number * 16;
		return [this.worldMatrixBase_[matOffset + 12], this.worldMatrixBase_[matOffset + 13], this.worldMatrixBase_[matOffset + 14]];
	}

	localMatrix(inst: TransformInstance) { return refIndexedMat4(this.localMatrixBase_, inst as number); }
	worldMatrix(inst: TransformInstance) { return refIndexedMat4(this.worldMatrixBase_, inst as number); }

{'fraction_non_alphanumeric': 0.10936763418412014, 'fraction_numerical': 0.014007677284665634, 'mean_word_length': 5.0661764705882355, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 22, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6779728', 'n_tokens_mistral': 4934, 'n_tokens_neox': 4389, 'n_words': 1023}