Initial commit
This commit is contained in:
37
C#/TSEngine/Core/Graphics/color.ts
Normal file
37
C#/TSEngine/Core/Graphics/color.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace TSE {
|
||||
|
||||
export class Color {
|
||||
public static get white(): Color { return new Color(255, 255, 255, 255); }
|
||||
public static get black(): Color { return new Color(0, 0, 0, 255) };
|
||||
public static get red(): Color { return new Color(255, 0, 0, 255) };
|
||||
public static get green(): Color { return new Color(0, 255, 0, 255) };
|
||||
public static get blue(): Color { return new Color(0, 0, 255, 255) };
|
||||
|
||||
private _red;
|
||||
private _green;
|
||||
private _blue;
|
||||
private _alpha;
|
||||
|
||||
public constructor(red: number = 255, green: number = 255, blue: number = 255, alpha: number = 255) {
|
||||
this._red = red;
|
||||
this._green = green;
|
||||
this._blue = blue;
|
||||
this._alpha = alpha;
|
||||
}
|
||||
|
||||
public get red(): number { return this._red; }
|
||||
public get green(): number { return this._green; }
|
||||
public get blue(): number { return this._blue; }
|
||||
public get alpha(): number { return this._alpha; }
|
||||
|
||||
public get redFload(): number { return this._red / 255; }
|
||||
public get greenFload(): number { return this._green / 255; }
|
||||
public get blueFload(): number { return this._blue / 255; }
|
||||
public get alphaFload(): number { return this._alpha / 255; }
|
||||
|
||||
public toArray(): number[] { return [this._red, this._green, this._blue, this._alpha] }
|
||||
public toFloatArray(): number[] { return [this.redFload, this.greenFload, this.blueFload, this.alphaFload]; }
|
||||
public toFloat32Array(): Float32Array { return new Float32Array(this.toFloatArray()); }
|
||||
}
|
||||
|
||||
}
|
||||
41
C#/TSEngine/Core/Graphics/material.ts
Normal file
41
C#/TSEngine/Core/Graphics/material.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace TSE {
|
||||
|
||||
export class Material {
|
||||
|
||||
private _name: string;
|
||||
private _diffuseTextureName: string;
|
||||
|
||||
private _diffuseTexture: Texture;
|
||||
private _tint: Color;
|
||||
|
||||
public constructor(name: string, diffuseTextureName: string, tint: Color = Color.white) {
|
||||
this._name = name;
|
||||
this._diffuseTextureName = diffuseTextureName;
|
||||
this._tint = tint;
|
||||
|
||||
if (this._diffuseTextureName !== undefined)
|
||||
this._diffuseTexture = TextureManager.getTexture(this._diffuseTextureName);
|
||||
}
|
||||
|
||||
public get name(): string { return this._name; }
|
||||
public get diffuseTextureName(): string { return this._diffuseTextureName; }
|
||||
public get diffuseTexture(): Texture { return this._diffuseTexture; }
|
||||
public get tint(): Color { return this._tint; }
|
||||
|
||||
public set diffuseTextureName(value: string) {
|
||||
if (this._diffuseTexture !== undefined)
|
||||
TextureManager.releaseTexture(this._diffuseTextureName);
|
||||
|
||||
if (value === undefined) return;
|
||||
this.diffuseTextureName = value;
|
||||
this._diffuseTexture = TextureManager.getTexture(this._diffuseTextureName);
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
TextureManager.releaseTexture(this._diffuseTextureName);
|
||||
this._diffuseTexture = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
45
C#/TSEngine/Core/Graphics/materialManager.ts
Normal file
45
C#/TSEngine/Core/Graphics/materialManager.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace TSE {
|
||||
|
||||
class MaterialReferenceNode {
|
||||
|
||||
public material: Material;
|
||||
public referenceCount: number = 1;
|
||||
|
||||
public constructor(material: Material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class MaterialManager {
|
||||
|
||||
private static _materials: { [name: string]: MaterialReferenceNode } = {};
|
||||
|
||||
private constructor() { }
|
||||
|
||||
public static registerMaterial(material: Material): void {
|
||||
if (MaterialManager._materials[material.name] === undefined)
|
||||
MaterialManager._materials[material.name] = new MaterialReferenceNode(material);
|
||||
}
|
||||
|
||||
public static getMaterial(materialName: string): Material {
|
||||
if (MaterialManager._materials[materialName] === undefined) return undefined;
|
||||
|
||||
MaterialManager._materials[materialName].referenceCount++;
|
||||
return MaterialManager._materials[materialName].material;
|
||||
}
|
||||
|
||||
public static releaseMaterial(materialName: string): void {
|
||||
if (MaterialManager._materials[materialName] === undefined) console.warn("Cannot release an undefined Material!");
|
||||
else {
|
||||
MaterialManager._materials[materialName].referenceCount--;
|
||||
if (MaterialManager._materials[materialName].referenceCount < 1) {
|
||||
MaterialManager._materials[materialName].material.destroy();
|
||||
delete MaterialManager._materials[materialName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
151
C#/TSEngine/Core/Graphics/sprite.ts
Normal file
151
C#/TSEngine/Core/Graphics/sprite.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
namespace TSE {
|
||||
|
||||
export class Sprite {
|
||||
protected _buffer: GLBuffer;
|
||||
|
||||
protected _width: number;
|
||||
protected _height: number;
|
||||
protected _name: string;
|
||||
|
||||
protected _material: Material;
|
||||
protected _vertices: Vertex[] = [];
|
||||
|
||||
public constructor(name: string, materialName: string, width: number = 100, height: number = 100) {
|
||||
this._name = name;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._material = MaterialManager.getMaterial(materialName);
|
||||
}
|
||||
|
||||
public load(): void {
|
||||
this._buffer = new GLBuffer();
|
||||
|
||||
this._buffer.addAttributeLocation(new AttributeInfo(0, 3)); //Position
|
||||
this._buffer.addAttributeLocation(new AttributeInfo(1, 2)); //UVs
|
||||
|
||||
this._vertices = [
|
||||
new Vertex(0, 0, 0, 0, 0),
|
||||
new Vertex(0, this._height, 0, 0, 1.0),
|
||||
new Vertex(this._width, this._height, 0, 1.0, 1.0),
|
||||
|
||||
new Vertex(this._width, this._height, 0, 1.0, 1.0),
|
||||
new Vertex(this._width, 0, 0, 1.0, 0),
|
||||
new Vertex(0, 0, 0, 0, 0)
|
||||
];
|
||||
|
||||
this._buffer.pushBackData(Vertex.vertexArray(this._vertices));
|
||||
this._buffer.upload();
|
||||
this._buffer.unbind();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this._buffer.destroy();
|
||||
MaterialManager.releaseMaterial(this._material.name);
|
||||
delete this._material;
|
||||
}
|
||||
|
||||
public update(time: number): void {
|
||||
|
||||
}
|
||||
|
||||
public draw(shader: Shader, model: Matrix4x4): void {
|
||||
let modelLocation = shader.getUniformLocation("u_model");
|
||||
gl.uniformMatrix4fv(modelLocation, false, model.toFloat32Array());
|
||||
|
||||
let colorLocation = shader.getUniformLocation("u_tint");
|
||||
gl.uniform4fv(colorLocation, this._material.tint.toFloat32Array());
|
||||
|
||||
if (this._material.diffuseTexture !== undefined) {
|
||||
this._material.diffuseTexture.activateAndBind(0);
|
||||
let diffuseLocation = shader.getUniformLocation("u_diffuse");
|
||||
gl.uniform1i(diffuseLocation, 0);
|
||||
}
|
||||
|
||||
this._buffer.bind();
|
||||
this._buffer.draw();
|
||||
}
|
||||
|
||||
public get name(): string { return this._name; }
|
||||
|
||||
}
|
||||
|
||||
export class AnimatedSprite extends Sprite {
|
||||
|
||||
private _frameHeight: number;
|
||||
private _frameWidth: number;
|
||||
private _frameCount: number;
|
||||
private _frameSequence: number[];
|
||||
|
||||
private _currentFrame: number = 0;
|
||||
private currentTime: number = 0;
|
||||
private _frameTime: number = 300;
|
||||
private _frameUVs: Vector2[][];
|
||||
private _loaded: boolean = false;
|
||||
|
||||
public constructor(name: string, materialName: string, frameWidth: number = 10, frameHeight: number = 10, frameCount: number = 1, frameSequence: number[] = []) {
|
||||
super(name, materialName, frameWidth, frameHeight);
|
||||
this._frameWidth = frameWidth;
|
||||
this._frameHeight = frameHeight;
|
||||
this._frameCount = frameCount;
|
||||
this._frameSequence = frameSequence;
|
||||
}
|
||||
|
||||
public load() {
|
||||
super.load();
|
||||
this.calculateUVs();
|
||||
}
|
||||
|
||||
private calculateUVs(): void {
|
||||
setTimeout(() => {
|
||||
this._frameUVs = [];
|
||||
|
||||
let totalWidth: number = 0;
|
||||
let totalHeight: number = 0;
|
||||
for (let i = 0; i < this._frameCount; i++) {
|
||||
totalWidth += this._frameWidth;
|
||||
if (totalWidth > this._material.diffuseTexture.width) {
|
||||
totalWidth = 0;
|
||||
totalHeight++;
|
||||
}
|
||||
|
||||
const u = (i * this._frameWidth) / this._material.diffuseTexture.width;
|
||||
const v = (totalHeight * this._frameHeight) / this._material.diffuseTexture.height;
|
||||
const um = ((i * this._frameWidth) + this._frameWidth) / this._material.diffuseTexture.width;
|
||||
const vm = ((totalHeight * this._frameHeight) + this._frameHeight) / this._material.diffuseTexture.height;
|
||||
this._frameUVs.push([new Vector2(u, v), new Vector2(um, vm)]);
|
||||
}
|
||||
this._loaded = true;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public update(time: number) {
|
||||
if (!this._loaded) return;
|
||||
this.currentTime += time;
|
||||
if (this.currentTime > this._frameTime) {
|
||||
this._currentFrame++;
|
||||
this.currentTime = 0;
|
||||
|
||||
if (this._currentFrame >= this._frameSequence.length)
|
||||
this._currentFrame = 0;
|
||||
|
||||
const frameUVs = this._frameUVs[this._frameSequence[this._currentFrame]];
|
||||
|
||||
this._vertices[0].texCoords.copyFrom(frameUVs[0]);
|
||||
this._vertices[1].texCoords = new Vector2(frameUVs[0].x, frameUVs[1].y);
|
||||
this._vertices[2].texCoords.copyFrom(frameUVs[1]);
|
||||
|
||||
this._vertices[3].texCoords.copyFrom(frameUVs[1]);
|
||||
this._vertices[4].texCoords = new Vector2(frameUVs[1].x, frameUVs[0].y);
|
||||
this._vertices[5].texCoords.copyFrom(frameUVs[0]);
|
||||
|
||||
this._buffer.setData(Vertex.vertexArray(this._vertices));
|
||||
this._buffer.upload();
|
||||
this._buffer.unbind();
|
||||
}
|
||||
|
||||
super.update(time);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
94
C#/TSEngine/Core/Graphics/texture.ts
Normal file
94
C#/TSEngine/Core/Graphics/texture.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
namespace TSE {
|
||||
|
||||
const LEVEL: number = 0;
|
||||
const BORDER: number = 0;
|
||||
const TEMP_IMAGE_DATA: Uint8Array = new Uint8Array([255, 255, 255, 255]);
|
||||
|
||||
export class Texture implements IMessageHanlder {
|
||||
|
||||
private _name: string;
|
||||
private _handle: WebGLTexture;
|
||||
private _isLoaded: boolean = false;
|
||||
private _width: number;
|
||||
private _height: number;
|
||||
|
||||
public constructor(name: string, width: number = 1, height: number = 1) {
|
||||
this._name = name;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
this._handle = gl.createTexture();
|
||||
|
||||
Message.subscribe(MESSAGE_ASSET_LOADER_ASSET_LOADED + this._name, this);
|
||||
|
||||
this.bind();
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, LEVEL, gl.RGBA, 1, 1, BORDER, gl.RGBA, gl.UNSIGNED_BYTE, TEMP_IMAGE_DATA);
|
||||
|
||||
let asset = AssetManager.getAsset(this._name) as ImageAsset;
|
||||
if (asset !== undefined) {
|
||||
this.loadTextureFromAsset(asset);
|
||||
}
|
||||
}
|
||||
|
||||
public onMessage(message: Message): void {
|
||||
if (message.code === MESSAGE_ASSET_LOADER_ASSET_LOADED + this._name) {
|
||||
this.loadTextureFromAsset(message.context as ImageAsset);
|
||||
}
|
||||
}
|
||||
|
||||
public get name(): string { return this._name; }
|
||||
public get isLoaded(): boolean { return this._isLoaded; }
|
||||
public get width(): number { return this._width; }
|
||||
public get height(): number { return this._height; }
|
||||
|
||||
public activateAndBind(textureUnit: number = 0): void {
|
||||
gl.activeTexture(gl.TEXTURE0 + textureUnit);
|
||||
|
||||
this.bind();
|
||||
}
|
||||
|
||||
public bind(): void {
|
||||
gl.bindTexture(gl.TEXTURE_2D, this._handle);
|
||||
}
|
||||
|
||||
public unbind(): void {
|
||||
gl.bindTexture(gl.TEXTURE_2D, undefined);
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
gl.deleteTexture(this._handle);
|
||||
}
|
||||
|
||||
private loadTextureFromAsset(asset: ImageAsset): void {
|
||||
this._width = asset.width;
|
||||
this._height = asset.height;
|
||||
|
||||
this.bind();
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, LEVEL, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, asset.data);
|
||||
|
||||
if (this.isPowerOf2()) {
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
} else {
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
|
||||
this._isLoaded = true;
|
||||
}
|
||||
|
||||
private isPowerOf2(): boolean {
|
||||
return (this.isValuePowerOf2(this.width) && this.isValuePowerOf2(this.height));
|
||||
}
|
||||
|
||||
private isValuePowerOf2(value: number): boolean {
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
44
C#/TSEngine/Core/Graphics/textureManager.ts
Normal file
44
C#/TSEngine/Core/Graphics/textureManager.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace TSE {
|
||||
|
||||
class TextureReferenceNode {
|
||||
|
||||
public texture: Texture;
|
||||
public referenceCount: number = 1;
|
||||
|
||||
public constructor(texture: Texture) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class TextureManager {
|
||||
|
||||
private static _textures: { [name: string]: TextureReferenceNode } = {};
|
||||
|
||||
private constructor() { }
|
||||
|
||||
public static getTexture(textureName: string): Texture {
|
||||
if (TextureManager._textures[textureName] === undefined)
|
||||
TextureManager._textures[textureName] = new TextureReferenceNode(new Texture(textureName));
|
||||
else
|
||||
TextureManager._textures[textureName].referenceCount++;
|
||||
|
||||
return TextureManager._textures[textureName].texture;
|
||||
}
|
||||
|
||||
public static releaseTexture(textureName: string): void {
|
||||
if (TextureManager._textures[textureName] === undefined) {
|
||||
console.warn(`A Texture named ${textureName} does not exist and cannot be released!`);
|
||||
} else {
|
||||
TextureManager._textures[textureName].referenceCount--;
|
||||
if (TextureManager._textures[textureName].referenceCount < 1) {
|
||||
TextureManager._textures[textureName].texture.destroy();
|
||||
TextureManager._textures[textureName] = undefined;
|
||||
delete TextureManager._textures[textureName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
30
C#/TSEngine/Core/Graphics/vertex.ts
Normal file
30
C#/TSEngine/Core/Graphics/vertex.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace TSE {
|
||||
|
||||
export class Vertex {
|
||||
|
||||
public static vertexArray(vertices: Vertex[]): number[] {
|
||||
let array: number[] = [];
|
||||
for (let vertex of vertices)
|
||||
array = array.concat(vertex.toArray());
|
||||
return array;
|
||||
}
|
||||
|
||||
public position: Vector3;
|
||||
public texCoords: Vector2;
|
||||
|
||||
public constructor(x: number = 0, y: number = 0, z: number = 0, u: number = 0, v: number = 0) {
|
||||
this.position = new Vector3(x, y, z);
|
||||
this.texCoords = new Vector2(u, v);
|
||||
}
|
||||
|
||||
public toArray(): number[] {
|
||||
let array: number[] = [];
|
||||
array = array.concat(this.position.toArray(), this.texCoords.toArray());
|
||||
return array;
|
||||
}
|
||||
|
||||
public toFloat32Array(): Float32Array { return new Float32Array(this.toArray()); }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user