refactor sand to use base-set

This commit is contained in:
“chrisshank” 2024-12-10 16:22:26 -08:00
parent e8d64cc907
commit c9afe5e935
2 changed files with 63 additions and 72 deletions

View File

@ -23,11 +23,6 @@
border-radius: 2px;
}
folk-sand {
position: absolute;
inset: 0;
}
.key-helper {
position: fixed;
top: 20px;
@ -50,6 +45,15 @@
border-radius: 3px;
margin-right: 10px;
}
p {
box-sizing: border-box;
color: white;
position: absolute;
top: 150px;
left: 25px;
border: 1px solid white;
}
</style>
</head>
<body>
@ -64,6 +68,7 @@
</div>
<folk-sand>
<p>Sanding</p>
<folk-shape x="100" y="100" width="50" height="50"></folk-shape>
<folk-shape x="100" y="200" width="50" height="50"></folk-shape>
<folk-shape x="100" y="300" width="50" height="50"></folk-shape>

View File

@ -8,13 +8,26 @@ import {
visualizationShader,
vertexShader,
} from './folk-sand.glsl.ts';
import { FolkShape } from './folk-shape.ts';
import { requestAnimationFrame } from './common/rAF.ts';
import { FolkBaseSet } from './folk-base-set.ts';
import { css, PropertyValues } from '@lit/reactive-element';
import { DOMRectTransformReadonly } from './common/DOMRectTransform.ts';
export class FolkSand extends HTMLElement {
static tagName = 'folk-sand';
export class FolkSand extends FolkBaseSet {
static override tagName = 'folk-sand';
private canvas!: HTMLCanvasElement;
static styles = [
FolkBaseSet.styles,
css`
canvas {
height: 100%;
width: 100%;
pointer-events: auto;
}
`,
];
private canvas = document.createElement('canvas');
private gl!: WebGL2RenderingContext;
private program!: WebGLProgram;
@ -47,8 +60,6 @@ export class FolkSand extends HTMLElement {
private materialType = 4;
private brushRadius = 5;
private shapes: NodeListOf<FolkShape> = document.querySelectorAll('folk-shape');
private frames = 0;
private swap = 0;
private shadowSwap = 0;
@ -64,53 +75,21 @@ export class FolkSand extends HTMLElement {
private shapeIndexBuffer!: WebGLBuffer;
private shapeIndexCount = 0;
static define() {
if (customElements.get(this.tagName)) return;
FolkShape.define();
customElements.define(this.tagName, this);
}
connectedCallback(): void {
super.connectedCallback();
connectedCallback() {
this.setupCanvas();
this.renderRoot.appendChild(this.canvas);
this.initializeWebGL();
this.initializeSimulation();
this.initializeCollisionDetection();
// Collect all FolkShape elements
this.shapes = document.querySelectorAll('folk-shape');
// Attach event listeners to shapes
this.shapes.forEach((shape) => {
shape.addEventListener('transform', this.handleShapeTransform);
});
// Initialize collision texture with current shapes
this.collectShapeData();
this.updateCollisionTexture();
this.attachEventListeners();
this.handleShapeTransform();
this.render();
}
disconnectedCallback() {
super.disconnectedCallback();
this.detachEventListeners();
// Remove event listeners from shapes
this.shapes.forEach((shape) => {
shape.removeEventListener('transform', this.handleShapeTransform);
});
}
private setupCanvas() {
this.canvas = document.createElement('canvas');
this.canvas.id = 'main-canvas';
this.canvas.style.width = '100%';
this.canvas.style.height = '100%';
this.canvas.style.display = 'block';
this.style.display = 'block';
this.style.width = '100%';
this.style.height = '100%';
this.appendChild(this.canvas);
}
private initializeWebGL() {
@ -206,10 +185,6 @@ export class FolkSand extends HTMLElement {
gl.vertexAttribPointer(posAttribLoc, 2, gl.FLOAT, false, 0, 0);
gl.bindVertexArray(null);
// Initial collection and render of shape data
this.collectShapeData();
this.updateCollisionTexture();
}
private setupBuffers() {
@ -295,11 +270,6 @@ export class FolkSand extends HTMLElement {
}
private attachEventListeners() {
this.handlePointerDown = this.handlePointerDown.bind(this);
this.handlePointerMove = this.handlePointerMove.bind(this);
this.handlePointerUp = this.handlePointerUp.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.canvas.addEventListener('pointerdown', this.handlePointerDown);
this.canvas.addEventListener('pointermove', this.handlePointerMove);
this.canvas.addEventListener('pointerup', this.handlePointerUp);
@ -313,7 +283,7 @@ export class FolkSand extends HTMLElement {
document.removeEventListener('keydown', this.handleKeyDown);
}
private handlePointerMove(event: PointerEvent) {
private handlePointerMove = (event: PointerEvent) => {
const rect = this.canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
@ -325,9 +295,9 @@ export class FolkSand extends HTMLElement {
// Scale coordinates relative to canvas size
this.pointer.x = (x / rect.width) * this.canvas.width;
this.pointer.y = (y / rect.height) * this.canvas.height;
}
};
private handlePointerDown(event: PointerEvent) {
private handlePointerDown = (event: PointerEvent) => {
const rect = this.canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
@ -338,18 +308,18 @@ export class FolkSand extends HTMLElement {
this.pointer.prevX = this.pointer.x;
this.pointer.prevY = this.pointer.y;
this.pointer.down = true;
}
};
private handlePointerUp() {
private handlePointerUp = () => {
this.pointer.down = false;
}
};
private handleKeyDown(event: KeyboardEvent) {
private handleKeyDown = (event: KeyboardEvent) => {
const key = parseInt(event.key);
if (!isNaN(key)) {
this.setMaterialType(key);
}
}
};
private setMaterialType(type: number) {
this.materialType = Math.min(Math.max(type, 0), 9);
@ -636,12 +606,20 @@ export class FolkSand extends HTMLElement {
const indices: number[] = [];
let vertexOffset = 0;
this.shapes.forEach((shape) => {
const rect = shape.getTransformDOMRect();
if (!rect) return;
this.sourceRects.forEach((rect) => {
// Get the transformed vertices in parent space
const transformedPoints = rect.vertices().map((point) => rect.toParentSpace(point));
let transformedPoints;
if (rect instanceof DOMRectTransformReadonly) {
transformedPoints = rect.vertices().map((point) => rect.toParentSpace(point));
} else {
transformedPoints = [
{ x: rect.left, y: rect.top },
{ x: rect.right, y: rect.top },
{ x: rect.left, y: rect.bottom },
{ x: rect.right, y: rect.bottom },
];
}
// Convert the transformed points to buffer coordinates
const bufferPoints = transformedPoints.map((point) => this.convertToBufferCoordinates(point.x, point.y));
@ -704,10 +682,18 @@ export class FolkSand extends HTMLElement {
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
private handleShapeTransform = () => {
override update(changedProperties: PropertyValues<this>) {
super.update(changedProperties);
if (this.sourcesMap.size !== this.sourceElements.size) return;
this.handleShapeTransform();
}
private handleShapeTransform() {
// Recollect and update all shape data when any shape changes
// TODO: do this more piecemeal
this.collectShapeData();
this.updateCollisionTexture();
};
}
}