Skip to content

Commit 67cafed

Browse files
committed
Simplify core files
Add utils into domHandler, create index for core
1 parent 52ae49d commit 67cafed

File tree

7 files changed

+300
-347
lines changed

7 files changed

+300
-347
lines changed

src/core/base.ts renamed to src/core/domHandler.ts

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { Utils } from './utils'
2-
31
export const enum MethodName {
42
TOUCH,
53
INIT,
@@ -39,7 +37,7 @@ export class domHandler {
3937
this.container.addEventListener('touchmove', this.inputHandler, { passive: true });
4038

4139
this.resizeHandler = this.resize.bind(this);
42-
window.addEventListener('resize', Utils.domUtils.debounce(this.resizeHandler), { passive: true });
40+
window.addEventListener('resize', this.debounce(this.resizeHandler), { passive: true });
4341

4442
this.setSize();
4543
}
@@ -87,7 +85,7 @@ export class domHandler {
8785

8886
protected mainLoop = (refreshRate: number = 0) => {
8987
if (this.loopActive) {
90-
Utils.scriptUtils.requestTimeout(() => this.mainLoop(refreshRate), refreshRate);
88+
this.requestTimeout(() => this.mainLoop(refreshRate), refreshRate);
9189
this.loop();
9290
}
9391
}
@@ -98,4 +96,80 @@ export class domHandler {
9896
public get container(): HTMLCanvasElement {
9997
return this._container;
10098
}
99+
100+
/**
101+
* Returns id for touch from a list.
102+
* Returns -1 if not found.
103+
*
104+
* @param {number} idToFind
105+
* @param {Array<Touch>} ongoingTouches
106+
* @return {*} {number}
107+
* @memberof domUtils
108+
*/
109+
protected ongoingTouchIndexById(idToFind: number, ongoingTouches: Array<Touch>): number {
110+
for (var i = 0; i < ongoingTouches.length; i++) {
111+
var id = ongoingTouches[i].identifier;
112+
113+
if (id == idToFind) {
114+
return i;
115+
}
116+
}
117+
return -1; // not found
118+
}
119+
120+
/**
121+
* Debounce functions for better performance
122+
* (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com
123+
* @param {Function} fn The function to debounce
124+
*/
125+
protected debounce(this: any, fn: any, delay: number = 0) {
126+
127+
// Setup a timer
128+
let timeout: number;
129+
130+
// Return a function to run debounced
131+
return () => {
132+
133+
// Setup the arguments
134+
let context: any = this;
135+
let args: any = arguments;
136+
137+
// If there's a timer, cancel it
138+
if (timeout) {
139+
window.cancelAnimationFrame(timeout);
140+
}
141+
// Setup the new requestAnimationFrame()
142+
timeout = window.requestAnimationFrame(() => {
143+
this._ScriptUtils.requestTimeout(fn, delay);
144+
});
145+
146+
}
147+
};
148+
149+
protected noop = () => { };
150+
151+
protected requestTimeout = (fn: () => void, delay: number, registerCancel: any = this.registerCancel) => {
152+
const start = new Date().getTime();
153+
154+
const loop = () => {
155+
const delta = new Date().getTime() - start;
156+
157+
if (delta >= delay) {
158+
fn();
159+
registerCancel(this.noop);
160+
return;
161+
}
162+
163+
const raf = requestAnimationFrame(loop);
164+
registerCancel(() => cancelAnimationFrame(raf));
165+
};
166+
167+
const raf = requestAnimationFrame(loop);
168+
registerCancel(() => cancelAnimationFrame(raf));
169+
};
170+
171+
protected cancel = this.noop;
172+
protected registerCancel = (fn: () => void) => this.cancel = fn;
101173
}
174+
175+

src/core/index.ts

Lines changed: 3 additions & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -1,218 +1,5 @@
1-
import { shaderArgs, UniformValue, ShaderHook } from "../types";
2-
import { domHandler, MethodName } from "./base";
1+
import { Shader } from './shader'
2+
import { domHandler, MethodName } from './domHandler'
33

44

5-
/** Shader Class
6-
* @export
7-
* @class Shader
8-
* @extends {domHandler}
9-
*
10-
*/
11-
export class Shader extends domHandler {
12-
private hooks: Record<string, ShaderHook[]> = {};
13-
private gl: WebGLRenderingContext;
14-
private shaderProgram: WebGLProgram;
15-
private vertexBuffer: WebGLBuffer;
16-
private uniforms: Array<UniformValue> | undefined
17-
18-
constructor(container: HTMLCanvasElement, args: shaderArgs) {
19-
super(container);
20-
this.gl = container.getContext('webgl') as WebGLRenderingContext;
21-
this.shaderProgram = this.initializeShader(args.vertShader, args.fragShader);
22-
this.vertexBuffer = this.initBuffers();
23-
this.uniforms = args.uniforms
24-
// Initialize custom logic if provided
25-
args.hooks?.forEach((hook) => {
26-
this.addHook(hook.methodName, hook.hook)
27-
})
28-
}
29-
30-
public init() {
31-
super.init();
32-
this.runHooks(MethodName.INIT);
33-
34-
this.resize()
35-
this.startLoop(60);
36-
37-
this.uniforms?.forEach((uniform) => {
38-
this.setUniform(uniform)
39-
})
40-
}
41-
42-
public addHook(methodName: MethodName, hook: ShaderHook): void {
43-
if (!this.hooks[methodName]) this.hooks[methodName] = [];
44-
this.hooks[methodName].push(hook);
45-
}
46-
47-
protected runHooks(method: MethodName, ...args: any[]) {
48-
if (this.hooks[method]) {
49-
this.hooks[method].forEach((hook) => hook(this, ...args));
50-
}
51-
}
52-
53-
private initBuffers(): WebGLBuffer {
54-
const vertices = new Float32Array([
55-
-1.0, 1.0, // Top-left
56-
-1.0, -1.0, // Bottom-left
57-
1.0, -1.0, // Bottom-right
58-
59-
-1.0, 1.0, // Top-left
60-
1.0, -1.0, // Bottom-right
61-
1.0, 1.0 // Top-right
62-
]);
63-
64-
const vertexBuffer = this.gl.createBuffer();
65-
if (!vertexBuffer) throw new Error('Failed to create vertex buffer');
66-
67-
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer);
68-
this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);
69-
70-
return vertexBuffer;
71-
}
72-
73-
private loadShader(gl: WebGLRenderingContext, type: GLenum, source: string = ''): WebGLShader | null {
74-
const shader = gl.createShader(type);
75-
if (!shader) return null;
76-
77-
gl.shaderSource(shader, source);
78-
gl.compileShader(shader);
79-
80-
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
81-
console.error('Shader compilation error:', gl.getShaderInfoLog(shader));
82-
gl.deleteShader(shader);
83-
return null;
84-
}
85-
86-
return shader;
87-
}
88-
89-
private initializeShader(vertShader?: string, fragShader?: string): WebGLProgram {
90-
const vertexShader = this.loadShader(this.gl, this.gl.VERTEX_SHADER, vertShader);
91-
const fragmentShader = this.loadShader(this.gl, this.gl.FRAGMENT_SHADER, fragShader);
92-
if (!vertexShader || !fragmentShader) throw new Error('Shader compilation failed');
93-
94-
const shaderProgram = this.gl.createProgram();
95-
if (!shaderProgram) throw new Error('Failed to create shader program');
96-
97-
this.gl.attachShader(shaderProgram, vertexShader);
98-
this.gl.attachShader(shaderProgram, fragmentShader);
99-
this.gl.linkProgram(shaderProgram);
100-
101-
if (!this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS)) {
102-
console.error('Shader program link error:', this.gl.getProgramInfoLog(shaderProgram));
103-
throw new Error('Unable to initialize the shader program');
104-
}
105-
return shaderProgram;
106-
}
107-
108-
// Main render loop
109-
protected loop(): void {
110-
super.loop();
111-
this.runHooks(MethodName.LOOP);
112-
this.render();
113-
}
114-
115-
protected render(): void {
116-
const gl = this.gl;
117-
this.runHooks(MethodName.RENDER);
118-
119-
gl.clear(gl.COLOR_BUFFER_BIT);
120-
gl.clear(gl.DEPTH_BUFFER_BIT);
121-
gl.clear(gl.STENCIL_BUFFER_BIT);
122-
123-
const vertexPosition = gl.getAttribLocation(this.shaderProgram, 'a_position');
124-
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
125-
gl.vertexAttribPointer(vertexPosition, 2, gl.FLOAT, false, 0, 0);
126-
gl.enableVertexAttribArray(vertexPosition);
127-
128-
gl.useProgram(this.shaderProgram);
129-
gl.drawArrays(gl.TRIANGLES, 0, 6);
130-
}
131-
132-
/** Gets a uniform value from the shader */
133-
public getUniform(name: string): UniformValue | undefined {
134-
const uLoc = this.gl.getUniformLocation(this.shaderProgram, name);
135-
if (!uLoc) {
136-
console.error(`Uniform ${name} not found.`);
137-
return;
138-
}
139-
140-
return this.gl.getUniform(this.shaderProgram, uLoc)
141-
}
142-
143-
/** Sets a uniform value for the shader */
144-
public setUniform(uniform: UniformValue): void {
145-
const { name, type, value } = uniform
146-
const uLoc = this.gl.getUniformLocation(this.shaderProgram, name);
147-
148-
if (!uLoc) {
149-
console.error(`Uniform ${name} not found.`);
150-
return;
151-
}
152-
153-
switch (type) {
154-
case "float":
155-
this.gl.uniform1f(uLoc, value as number);
156-
break;
157-
case "vec2":
158-
this.gl.uniform2fv(uLoc, value as Float32Array);
159-
break;
160-
case "vec3":
161-
this.gl.uniform3fv(uLoc, value as Float32Array);
162-
break;
163-
case "vec4":
164-
this.gl.uniform4fv(uLoc, value as Float32Array);
165-
break;
166-
case "int":
167-
this.gl.uniform1i(uLoc, value as number);
168-
break;
169-
case "ivec2":
170-
this.gl.uniform2iv(uLoc, value as Int32Array);
171-
break;
172-
case "ivec3":
173-
this.gl.uniform3iv(uLoc, value as Int32Array);
174-
break;
175-
case "ivec4":
176-
this.gl.uniform4iv(uLoc, value as Int32Array);
177-
break;
178-
case "mat2":
179-
this.gl.uniformMatrix2fv(uLoc, false, value as Float32Array);
180-
break;
181-
case "mat3":
182-
this.gl.uniformMatrix3fv(uLoc, false, value as Float32Array);
183-
break;
184-
case "mat4":
185-
this.gl.uniformMatrix4fv(uLoc, false, value as Float32Array);
186-
break;
187-
default:
188-
console.error(`Unsupported uniform type: ${type}`);
189-
}
190-
}
191-
192-
// Resize handler
193-
protected resize(e?: Event): void {
194-
super.resize(e);
195-
const { width, height } = this.container.getBoundingClientRect();
196-
this.container.width = width;
197-
this.container.height = height;
198-
this.gl.viewport(0, 0, width, height);
199-
this.runHooks(MethodName.RESIZE);
200-
201-
this.render(); // Render immediately on resize to avoid jitter waiting for render call
202-
}
203-
204-
// Handles input events
205-
protected handleInput(e: Event): void {
206-
super.handleInput(e);
207-
this.runHooks(MethodName.INPUT);
208-
209-
}
210-
211-
// Handles touch start events
212-
protected touchStart(e: Event): void {
213-
super.touchStart(e);
214-
this.runHooks(MethodName.TOUCH);
215-
216-
217-
}
218-
}
5+
export { Shader, domHandler, MethodName }

0 commit comments

Comments
 (0)