summaryrefslogtreecommitdiff
path: root/apps/web/src/lib/preview/hit-test.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-03-25 16:47:22 +0100
committerMaze Winther <mazewinther@gmail.com>2026-03-29 15:48:22 +0200
commit8db3bead13441a5882d8689dfc6a9f09c82375d9 (patch)
treee9d0cafa93904ffcbec3188c37961bcc16c6422d /apps/web/src/lib/preview/hit-test.ts
parent39ea298a9ccba3104c549c0ca079c231981811f5 (diff)
downloadopencut-8db3bead13441a5882d8689dfc6a9f09c82375d9.tar.gz
feat: masks, properties refactor, shaders, storage migrations, and more
Diffstat (limited to 'apps/web/src/lib/preview/hit-test.ts')
-rw-r--r--apps/web/src/lib/preview/hit-test.ts54
1 files changed, 48 insertions, 6 deletions
diff --git a/apps/web/src/lib/preview/hit-test.ts b/apps/web/src/lib/preview/hit-test.ts
index c2fde87b..2552922b 100644
--- a/apps/web/src/lib/preview/hit-test.ts
+++ b/apps/web/src/lib/preview/hit-test.ts
@@ -1,4 +1,5 @@
import type { ElementWithBounds } from "./element-bounds";
+import type { ElementRef } from "@/lib/timeline/types";
function pointInRotatedRect({
px,
@@ -24,14 +25,14 @@ function pointInRotatedRect({
const dy = py - cy;
const localX = dx * cos - dy * sin;
const localY = dx * sin + dy * cos;
- const halfW = width / 2;
- const halfH = height / 2;
+ const halfW = Math.abs(width) / 2;
+ const halfH = Math.abs(height) / 2;
return (
localX >= -halfW && localX <= halfW && localY >= -halfH && localY <= halfH
);
}
-export function hitTest({
+export function getHitElements({
canvasX,
canvasY,
elementsWithBounds,
@@ -39,7 +40,9 @@ export function hitTest({
canvasX: number;
canvasY: number;
elementsWithBounds: ElementWithBounds[];
-}): ElementWithBounds | null {
+}): ElementWithBounds[] {
+ const hits: ElementWithBounds[] = [];
+
for (let i = elementsWithBounds.length - 1; i >= 0; i--) {
const { bounds } = elementsWithBounds[i];
if (
@@ -53,8 +56,47 @@ export function hitTest({
rotation: bounds.rotation,
})
) {
- return elementsWithBounds[i];
+ hits.push(elementsWithBounds[i]);
}
}
- return null;
+
+ return hits;
+}
+
+export function hitTest({
+ canvasX,
+ canvasY,
+ elementsWithBounds,
+}: {
+ canvasX: number;
+ canvasY: number;
+ elementsWithBounds: ElementWithBounds[];
+}): ElementWithBounds | null {
+ return (
+ getHitElements({
+ canvasX,
+ canvasY,
+ elementsWithBounds,
+ })[0] ?? null
+ );
+}
+
+export function resolvePreferredHit({
+ hits,
+ preferredElements,
+}: {
+ hits: ElementWithBounds[];
+ preferredElements: ElementRef[];
+}): ElementWithBounds | null {
+ if (preferredElements.length === 0) return null;
+
+ return (
+ hits.find((hit) =>
+ preferredElements.some(
+ (preferredElement) =>
+ preferredElement.trackId === hit.trackId &&
+ preferredElement.elementId === hit.elementId,
+ ),
+ ) ?? null
+ );
}