import RawMesh from './RawMesh';
import { Geometry, Program, Shader, Texture, TextureMatrix } from '@pixi/core';
import { Matrix } from '@pixi/math';
import { BLEND_MODES } from '@pixi/constants';
import { hex2rgb, premultiplyRgba } from '@pixi/utils';
import vertex from './mesh.vert';
import fragment from './mesh.frag';
let meshProgram;
/**
* Base mesh class
* @class
* @extends PIXI.Container
* @memberof PIXI
*/
export default class Mesh extends RawMesh
{
/**
* @param {PIXI.Texture} [texture=Texture.EMPTY] - The texture to use
* @param {Float32Array} [vertices] - if you want to specify the vertices
* @param {Float32Array} [uvs] - if you want to specify the uvs
* @param {Uint16Array} [indices] - if you want to specify the indices
* @param {number} [drawMode] - the drawMode, can be any of the Mesh.DRAW_MODES consts
*/
constructor(texture = Texture.EMPTY, vertices, uvs, indices, drawMode)
{
const geometry = new Geometry();
if (!meshProgram)
{
meshProgram = new Program(vertex, fragment);
}
geometry.addAttribute('aVertexPosition', vertices)
.addAttribute('aTextureCoord', uvs)
.addIndex(indices);
geometry.getAttribute('aVertexPosition').static = false;
const uniforms = {
uSampler: texture,
uTextureMatrix: Matrix.IDENTITY,
alpha: 1,
uColor: new Float32Array([1, 1, 1, 1]),
};
super(geometry, new Shader(meshProgram, uniforms), null, drawMode);
/**
* The Uvs of the Mesh
*
* @member {Float32Array}
*/
this.uvs = geometry.getAttribute('aTextureCoord').data;
/**
* An array of vertices
*
* @member {Float32Array}
*/
this.vertices = geometry.getAttribute('aVertexPosition').data;
this.uniforms = uniforms;
/**
* The texture of the Mesh
*
* @member {PIXI.Texture}
* @default PIXI.Texture.EMPTY
* @private
*/
this.texture = texture;
/**
* The tint applied to the mesh. This is a [r,g,b] value. A value of [1,1,1] will remove any
* tint effect.
*
* @member {number}
* @private
*/
this._tintRGB = new Float32Array([1, 1, 1]);
// Set default tint
this.tint = 0xFFFFFF;
this.blendMode = BLEND_MODES.NORMAL;
/**
* TextureMatrix instance for this Mesh, used to track Texture changes
*
* @member {PIXI.TextureMatrix}
* @readonly
*/
this.uvMatrix = new TextureMatrix(this._texture);
/**
* whether or not upload uvMatrix to shader
* if its false, then uvs should be pre-multiplied
* if you change it for generated mesh, please call 'refresh(true)'
* @member {boolean}
* @default false
*/
this.uploadUvMatrix = false;
/**
* Uploads vertices buffer every frame, like in PixiJS V3 and V4.
*
* @member {boolean}
* @default true
*/
this.autoUpdate = true;
}
/**
* The tint applied to the Rope. This is a hex value. A value of
* 0xFFFFFF will remove any tint effect.
*
* @member {number}
* @memberof PIXI.Sprite#
* @default 0xFFFFFF
*/
get tint()
{
return this._tint;
}
/**
* Sets the tint of the rope.
*
* @param {number} value - The value to set to.
*/
set tint(value)
{
this._tint = value;
hex2rgb(this._tint, this._tintRGB);
}
/**
* The blend mode to be applied to the sprite. Set to `PIXI.BLEND_MODES.NORMAL` to remove any blend mode.
*
* @member {number}
* @default PIXI.BLEND_MODES.NORMAL
* @see PIXI.BLEND_MODES
*/
get blendMode()
{
return this.state.blendMode;
}
set blendMode(value) // eslint-disable-line require-jsdoc
{
this.state.blendMode = value;
}
/**
* The texture that the mesh uses.
*
* @member {PIXI.Texture}
*/
get texture()
{
return this._texture;
}
set texture(value) // eslint-disable-line require-jsdoc
{
if (this._texture === value)
{
return;
}
this._texture = value;
this.uniforms.uSampler = this.texture;
if (value)
{
// wait for the texture to load
if (value.baseTexture.valid)
{
this._onTextureUpdate();
}
else
{
value.once('update', this._onTextureUpdate, this);
}
}
}
_render(renderer)
{
const baseTex = this._texture.baseTexture;
premultiplyRgba(this._tintRGB, this.worldAlpha, this.uniforms.uColor, baseTex.premultiplyAlpha);
super._render(renderer);
}
/**
* When the texture is updated, this event will fire to update the scale and frame
*
* @private
*/
_onTextureUpdate()
{
// constructor texture update stop
if (!this.uvMatrix)
{
return;
}
this.uvMatrix.texture = this._texture;
this.refresh();
}
/**
* multiplies uvs only if uploadUvMatrix is false
* call it after you change uvs manually
* make sure that texture is valid
*/
multiplyUvs()
{
if (!this.uploadUvMatrix)
{
this.uvMatrix.multiplyUvs(this.uvs);
}
}
/**
* Refreshes uvs for generated meshes (rope, plane)
* sometimes refreshes vertices too
*
* @param {boolean} [forceUpdate=false] if true, matrices will be updated any case
*/
refresh(forceUpdate)
{
if (this.uvMatrix.update(forceUpdate))
{
this._refresh();
}
}
/**
* Updates the object transform for rendering
*
* @private
*/
updateTransform()
{
if (this.autoUpdate)
{
this.geometry.buffers[0].update();
}
this.containerUpdateTransform();
}
/**
* re-calculates mesh coords
* @private
*/
_refresh()
{
/* empty */
}
}