stripped down transformed space so we can debug

This commit is contained in:
Orion Reed 2024-12-20 15:36:00 -05:00
parent 1a6e358b9e
commit 38ed641b77
2 changed files with 18 additions and 116 deletions

View File

@ -4,13 +4,6 @@ import { html } from '@lib/tags';
import { TransformEvent } from '@lib/TransformEvent'; import { TransformEvent } from '@lib/TransformEvent';
import { css } from '@lit/reactive-element'; import { css } from '@lit/reactive-element';
interface TransformRect {
x: number;
y: number;
width: number;
height: number;
}
export class FolkTransformedSpace extends FolkElement { export class FolkTransformedSpace extends FolkElement {
static override tagName = 'folk-transformed-space'; static override tagName = 'folk-transformed-space';
@ -29,8 +22,7 @@ export class FolkTransformedSpace extends FolkElement {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
transform-style: preserve-3d; transform-origin: 0 0;
transform-origin: center;
backface-visibility: hidden; backface-visibility: hidden;
} }
`; `;
@ -46,9 +38,6 @@ export class FolkTransformedSpace extends FolkElement {
</div> </div>
`); `);
// Listen for transform events from shapes
this.addEventListener('transform', this.#handleTransform);
return root; return root;
} }
@ -63,93 +52,19 @@ export class FolkTransformedSpace extends FolkElement {
Gizmos.clear(); Gizmos.clear();
} }
#handleTransform = (event: TransformEvent) => { static projectPoint(point: Point, space: FolkTransformedSpace): Point {
const previous = this.transformRect(event.previous); // Visualize the click location in screen space
const current = this.transformRect(event.current); Gizmos.point(point, { color: 'red', size: 2 });
Gizmos.rect(event.current, { // Get the inverse of the current transform matrix
color: 'rgba(0, 0, 255, 0.1)', const inverseMatrix = space.#matrix.inverse();
width: 2,
layer: 'default',
});
Gizmos.line(event.current, current, { // Transform the screen point back to find where it should be placed on the transformed plane
color: 'gray', const pointOnTransformedSpace = inverseMatrix.transformPoint(point);
width: 2,
layer: 'transformed',
});
Gizmos.point(event.current, {
color: 'blue',
size: 3,
layer: 'transformed',
});
Gizmos.point(current, {
color: 'red',
size: 3,
layer: 'transformed',
});
const delta = { // Visualize where we'll place the point on the transformed plane
x: current.x - previous.x, Gizmos.point(pointOnTransformedSpace, { color: 'blue', size: 4, layer: 'transformed' });
y: current.y - previous.y,
};
event.current.x += delta.x; return pointOnTransformedSpace;
event.current.y += delta.y;
};
localToScreen(point: Point): Point {
const spaceRect = this.getBoundingClientRect();
const centerX = spaceRect.width / 2;
const centerY = spaceRect.height / 2;
// Use the same matrix we're using for CSS
const matrix = new DOMMatrix().translate(centerX, centerY).multiply(this.#matrix).translate(-centerX, -centerY);
const transformedPoint = matrix.transformPoint(new DOMPoint(point.x, point.y, 0, 1));
const w = transformedPoint.w || 1;
return {
x: transformedPoint.x / w,
y: transformedPoint.y / w,
};
}
/**
* Transforms a rect from an element in either face to screen coordinates
*/
transformRect(rect: TransformRect): TransformRect {
// Get center point
const center = {
x: rect.x,
y: rect.y,
};
// Transform center point
const transformedCenter = this.localToScreen(center);
return {
x: transformedCenter.x,
y: transformedCenter.y,
width: rect.width,
height: rect.height,
};
}
/**
* Transforms a rect using an instance of FolkTransformedSpace if it exists in the DOM
* @param rect The rectangle to transform
* @param element Any element that might be within a FolkTransformedSpace
* @returns The transformed rect, or the original rect if no FolkTransformedSpace is found
*/
static transformRect(rect: TransformRect, element: Element): TransformRect {
const space = element.closest(this.tagName);
if (space instanceof FolkTransformedSpace) {
Gizmos.point(rect, { color: 'red', size: 2 });
const transformed = space.transformRect(rect);
Gizmos.point(transformed, { color: 'blue', layer: 'transformed' });
return transformed;
}
return rect;
} }
} }

View File

@ -9,10 +9,6 @@
margin: 0; margin: 0;
height: 100%; height: 100%;
} }
folk-transformed-space {
width: 100%;
height: 100%;
}
folk-shape { folk-shape {
background: rgb(134, 37, 37); background: rgb(134, 37, 37);
border: 1px solid rgba(0, 0, 0, 0.5); border: 1px solid rgba(0, 0, 0, 0.5);
@ -37,40 +33,31 @@
const space = document.querySelector('folk-transformed-space'); const space = document.querySelector('folk-transformed-space');
// Track pointer state
let isPointerDown = false; let isPointerDown = false;
let lastPoint = null;
document.addEventListener('pointerdown', (event) => { document.addEventListener('pointerdown', (event) => {
isPointerDown = true; isPointerDown = true;
lastPoint = { x: event.clientX, y: event.clientY };
}); });
document.addEventListener('pointermove', (event) => { document.addEventListener('pointermove', (event) => {
if (!isPointerDown || !lastPoint) return; if (!isPointerDown) return;
const rect = { const point = {
x: lastPoint.x, x: event.clientX,
y: lastPoint.y, y: event.clientY,
width: 1,
height: 1,
}; };
const transformedRect = FolkTransformedSpace.transformRect(rect, space); const transformedPoint = FolkTransformedSpace.projectPoint(point, space);
lastPoint = { x: event.clientX, y: event.clientY };
}); });
document.addEventListener('pointerup', () => { document.addEventListener('pointerup', () => {
isPointerDown = false; isPointerDown = false;
lastPoint = null;
}); });
// Keep existing click handler for rotation
document.addEventListener('click', (event) => { document.addEventListener('click', (event) => {
if (event.target !== space) return; if (event.target !== space) return;
const min = 20; const min = -50;
const max = 70; const max = 50;
const randomRotation = Math.random() * (max - min) + min; const randomRotation = Math.random() * (max - min) + min;
space.rotate(randomRotation); space.rotate(randomRotation);
}); });