import Mesh from './Mesh';
import Geometry from './geometry/Geometry';
import * as core from '../core';
import { readFileSync } from 'fs';
import { join } from 'path';
let meshShader;
/**
* The Plane allows you to draw a texture across several points and them manipulate these points
*
*```js
* for (let i = 0; i < 20; i++) {
* points.push(new PIXI.Point(i * 50, 0));
* };
* let Plane = new PIXI.Plane(PIXI.Texture.fromImage("snake.png"), points);
* ```
*
* @class
* @extends PIXI.mesh.Mesh
* @memberof PIXI.mesh
*
*/
export default class Plane extends Mesh
{
/**
* @param {PIXI.Texture} texture - The texture to use on the Plane.
* @param {number} verticesX - The number of vertices in the x-axis
* @param {number} verticesY - The number of vertices in the y-axis
* @param {object} opts - an options object - add meshWidth and meshHeight
*/
constructor(texture, verticesX, verticesY, opts = {})
{
const geometry = new Geometry();
if (!meshShader)
{
meshShader = new core.Shader(readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'),
readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8'));
}
geometry.addAttribute('aVertexPosition', new Float32Array(2), 2)
.addAttribute('aTextureCoord', new Float32Array(2), 2)
.addIndex(new Uint16Array(2));
const uniforms = {
uSampler2: texture,
alpha: 1,
translationMatrix: null,
tint: new Float32Array([1, 1, 1]),
};
super(geometry, meshShader, uniforms, null, 4);
uniforms.translationMatrix = this.transform.worldTransform;
this.texture = texture;
this.segmentsX = this.verticesX = verticesX || 10;
this.segmentsY = this.verticesY = verticesY || 10;
this.meshWidth = opts.meshWidth || texture.width;
this.meshHeight = opts.meshHeight || texture.height;
if (texture.baseTexture.hasLoaded)
{
this.refresh();
}
else
{
texture.once('update', this.refresh, this);
}
this._tint = 0xFFFFFF;
this.tint = 0xFFFFFF;
}
/**
* 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;
core.utils.hex2rgb(this._tint, this.uniforms.tint);
}
/**
* Sets the texture of the rope.
*
* @param {PIXI.Texture} value - The value to set to.
*/
set texture(value)
{
this._texture = value;
this.uniforms.uSampler2 = this.texture;
}
/**
* The texture that the rope is using
*
* @member {PIXI.Texture}
* @memberof PIXI.Sprite#
*/
get texture()
{
return this._texture;
}
/**
* Refreshes
*
*/
refresh()
{
const total = this.verticesX * this.verticesY;
const verts = [];
const uvs = [];
const indices = [];
const texture = this.texture;
const segmentsX = this.verticesX - 1;
const segmentsY = this.verticesY - 1;
const sizeX = this.meshWidth / segmentsX;
const sizeY = this.meshHeight / segmentsY;
for (let i = 0; i < total; i++)
{
if (texture._uvs)
{
const x = (i % this.verticesX);
const y = ((i / this.verticesX) | 0);
verts.push((x * sizeX),
(y * sizeY));
// this works for rectangular textures.
uvs.push(
texture._uvs.x0 + ((texture._uvs.x1 - texture._uvs.x0) * (x / (this.verticesX - 1))),
texture._uvs.y0 + ((texture._uvs.y3 - texture._uvs.y0) * (y / (this.verticesY - 1)))
);
}
else
{
uvs.push(0);
}
}
const totalSub = segmentsX * segmentsY;
for (let i = 0; i < totalSub; i++)
{
const xpos = i % segmentsX;
const ypos = (i / segmentsX) | 0;
const value = (ypos * this.verticesX) + xpos;
const value2 = (ypos * this.verticesX) + xpos + 1;
const value3 = ((ypos + 1) * this.verticesX) + xpos;
const value4 = ((ypos + 1) * this.verticesX) + xpos + 1;
indices.push(value, value2, value3);
indices.push(value2, value4, value3);
}
this.shader.uniforms.alpha = 1;
this.shader.uniforms.uSampler2 = this.texture;
this.vertices = new Float32Array(verts);
this.uvs = new Float32Array(uvs);
this.indices = new Uint16Array(indices);
this.geometry.getAttribute('aVertexPosition').data = this.vertices;
this.geometry.getAttribute('aTextureCoord').data = this.uvs;
this.geometry.data.indexBuffer.data = this.indices;
// ensure that the changes are uploaded
this.geometry.getAttribute('aVertexPosition').update();
this.geometry.getAttribute('aTextureCoord').update();
this.geometry.data.indexBuffer.update();
}
/**
* Updates the object transform for rendering
*
* @private
*/
updateTransform()
{
this.geometry.getAttribute('aVertexPosition').update();
this.containerUpdateTransform();
}
}