import { Utils } from '../common/Utils'
import { GeometryResource } from '../resources/GeometryResource';
import { MaterialResource } from '../resources/MaterialResource';
import { Object3D } from './Object3D';
const __ = {
private: Symbol('private'),
}
/**
* @class Mesh
* The mesh object.
* @memberof THING
* @extends THING.Object3D
* @public
*/
class Mesh extends Object3D {
static defaultTagArray = ['Geometry'];
/**
* The mesh object that with custom geometry info in scene.
* @param {Object} param The initial parameters.
*/
constructor(param = {}) {
super(param);
this[__.private] = {};
let _private = this[__.private];
_private.geometry = null;
_private.material = null;
let data = param['data'];
if (data) {
_private.geometry = new GeometryResource(data);
}
else if (param['geometry']) {
_private.geometry = param['geometry'];
_private.geometry.addRef();
}
let material = param['material'];
if (material) {
if (material.isMaterialResource) {
_private.material = material;
_private.material.addRef();
}
else {
_private.material = new MaterialResource(material);
}
}
else {
_private.material = new MaterialResource();
}
}
// #region Private
_createCustomNode() {
let _private = this[__.private];
let geometryResource = _private.geometry.resource;
let materialResource = _private.material.resource;
return Utils.createObject('CustomNode', { geometryResource, materialResource });
}
// #endregion
// #region Overrides
onDestroy() {
let _private = this[__.private];
if (_private.geometry) {
_private.geometry.release();
_private.geometry = null;
}
if (_private.material) {
_private.material.release();
_private.material = null;
}
super.onDestroy();
}
onLoadResource(options, resolve, reject) {
let dynamic = Utils.parseValue(options['dynamic'], false);
if (!dynamic) {
Utils.setTimeout(() => {
if (this.destroyed) {
reject(`The object had been destroyed, skip to load resources`);
}
else {
let node = this._createCustomNode();
this.body.setNode(node);
resolve();
}
});
}
}
onCopy(object) {
super.onCopy(object);
let resource = object.geometry.resource;
if (!this.geometry) {
this.geometry = new GeometryResource({ array: resource._vertexData });
}
else {
this.setNormal(resource.getAttribute('a_Normal'));
this.setPosition(resource.getAttribute('a_Position'));
this.setUv(resource.getAttribute('a_Uv'));
this.setUv2(resource.getAttribute('a_Uv2'));
}
}
/**
* Set the vertex of the mesh.Use the current interface when the geometry references only itself, and use the attribute (mesh.geometry.position) interface when the geometry is shared.
* @param {Array<Number>|Float32Array} array
* @public
*/
setPosition(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Position', array);
}
}
/**
* Get the vertex of the mesh.
* @returns {Float32Array}
* @public
*/
getPosition() {
return this.geometry.resource.getAttribute('a_Position');
}
/**
* Set the vertex uv of the mesh.Use the current interface when the geometry references only itself, and use the attribute (mesh.geometry.uv) interface when the geometry is shared.
* @param {Array<Number>|Float32Array} array
* @public
*/
setUv(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Uv', array);
}
}
/**
* Get the vertex uv of the mesh.
* @returns {Float32Array}
* @public
*/
getUv() {
return this.geometry.resource.getAttribute('a_Uv');
}
/**
* Set the vertex uv2 of the mesh.Use the current interface when the geometry references only itself, and use the attribute (mesh.geometry.uv2) interface when the geometry is shared.
* @param {Array<Number>|Float32Array} array
* @private
*/
setUv2(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Uv2', array);
}
}
/**
* Set the vertex normal of the mesh.Use the current interface when the geometry references only itself, and use the attribute (mesh.geometry.normal) interface when the geometry is shared.
* @param {Array<Number>|Float32Array} array
* @public
*/
setNormal(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Normal', array);
}
}
/**
* Get the vertex normal of the mesh.
* @returns {Float32Array}
* @public
*/
getNormal() {
return this.geometry.resource.getAttribute('a_Normal');
}
// #endregion
// #region Accessor
/**
* Get mesh data.
* @type {Object}
* @public
*/
get data() {
let _private = this[__.private];
return {
geometryData: _private.geometry.vertexData,
materialData: _private.material.data,
}
}
/**
* Get geometry.
* @type {GeometryResource}
* @private
*/
get geometry() {
let _private = this[__.private];
return _private.geometry;
}
set geometry(value) {
let _private = this[__.private];
_private.geometry = value;
}
// #endregion
/**
* Check whether it's Mesh type or inherit from it.
* @type {Boolean}
* @public
*/
get isMesh() {
return true;
}
}
export { Mesh }