refactor(canvas): normalize guide domain naming
This commit is contained in:
parent
27ad48b365
commit
3497aef818
|
|
@ -18,14 +18,6 @@ export interface GuideScreenSegment {
|
||||||
y2: number
|
y2: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GuideHit {
|
|
||||||
ownerId: string
|
|
||||||
guideId: string
|
|
||||||
axis: CanvasGuide['axis']
|
|
||||||
position: number
|
|
||||||
distance: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getGuideScreenSegment(
|
export function getGuideScreenSegment(
|
||||||
graph: SceneGraph,
|
graph: SceneGraph,
|
||||||
owner: SceneNode,
|
owner: SceneNode,
|
||||||
|
|
@ -70,42 +62,3 @@ export function distanceToGuideSegment(x: number, y: number, segment: GuideScree
|
||||||
: Math.max(0, Math.min(1, ((x - segment.x1) * dx + (y - segment.y1) * dy) / lengthSquared))
|
: Math.max(0, Math.min(1, ((x - segment.x1) * dx + (y - segment.y1) * dy) / lengthSquared))
|
||||||
return Math.hypot(x - (segment.x1 + t * dx), y - (segment.y1 + t * dy))
|
return Math.hypot(x - (segment.x1 + t * dx), y - (segment.y1 + t * dy))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hitTestGuides(
|
|
||||||
graph: SceneGraph,
|
|
||||||
pageId: string,
|
|
||||||
viewport: GuideViewport,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
tolerance = 5
|
|
||||||
): GuideHit | null {
|
|
||||||
const page = graph.getNode(pageId)
|
|
||||||
if (!page) return null
|
|
||||||
let closest: GuideHit | null = null
|
|
||||||
|
|
||||||
const visit = (owner: SceneNode) => {
|
|
||||||
for (const guide of owner.guides) {
|
|
||||||
const distance = distanceToGuideSegment(
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
getGuideScreenSegment(graph, owner, guide, viewport)
|
|
||||||
)
|
|
||||||
if (distance <= tolerance && (!closest || distance < closest.distance)) {
|
|
||||||
closest = {
|
|
||||||
ownerId: owner.id,
|
|
||||||
guideId: guide.id,
|
|
||||||
axis: guide.axis,
|
|
||||||
position: guide.position,
|
|
||||||
distance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const childId of owner.childIds) {
|
|
||||||
const child = graph.getNode(childId)
|
|
||||||
if (child) visit(child)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visit(page)
|
|
||||||
return closest
|
|
||||||
}
|
|
||||||
|
|
|
||||||
51
packages/core/src/canvas/guides/hit-test.ts
Normal file
51
packages/core/src/canvas/guides/hit-test.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import type { SceneGraph, SceneNode } from '@open-pencil/scene-graph'
|
||||||
|
import type { CanvasGuide } from '@open-pencil/scene-graph/guides'
|
||||||
|
|
||||||
|
import { distanceToGuideSegment, getGuideScreenSegment, type GuideViewport } from './geometry'
|
||||||
|
|
||||||
|
export interface GuideHit {
|
||||||
|
ownerId: string
|
||||||
|
guideId: string
|
||||||
|
axis: CanvasGuide['axis']
|
||||||
|
position: number
|
||||||
|
distance: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hitTestGuides(
|
||||||
|
graph: SceneGraph,
|
||||||
|
pageId: string,
|
||||||
|
viewport: GuideViewport,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
tolerance = 5
|
||||||
|
): GuideHit | null {
|
||||||
|
const page = graph.getNode(pageId)
|
||||||
|
if (!page) return null
|
||||||
|
let closest: GuideHit | null = null
|
||||||
|
|
||||||
|
const visit = (owner: SceneNode) => {
|
||||||
|
for (const guide of owner.guides) {
|
||||||
|
const distance = distanceToGuideSegment(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
getGuideScreenSegment(graph, owner, guide, viewport)
|
||||||
|
)
|
||||||
|
if (distance <= tolerance && (!closest || distance < closest.distance)) {
|
||||||
|
closest = {
|
||||||
|
ownerId: owner.id,
|
||||||
|
guideId: guide.id,
|
||||||
|
axis: guide.axis,
|
||||||
|
position: guide.position,
|
||||||
|
distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const childId of owner.childIds) {
|
||||||
|
const child = graph.getNode(childId)
|
||||||
|
if (child) visit(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit(page)
|
||||||
|
return closest
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,9 @@ export {
|
||||||
export {
|
export {
|
||||||
distanceToGuideSegment,
|
distanceToGuideSegment,
|
||||||
getGuideScreenSegment,
|
getGuideScreenSegment,
|
||||||
hitTestGuides,
|
|
||||||
type GuideHit,
|
|
||||||
type GuideScreenSegment,
|
type GuideScreenSegment,
|
||||||
type GuideViewport
|
type GuideViewport
|
||||||
} from './guides/geometry'
|
} from './guides/geometry'
|
||||||
|
export { hitTestGuides, type GuideHit } from './guides/hit-test'
|
||||||
export type { GuideOverlayState, GuidePreview, GuideSelection } from './guides/types'
|
export type { GuideOverlayState, GuidePreview, GuideSelection } from './guides/types'
|
||||||
export { SkiaRenderer, type RenderOverlays, type RulerTheme } from './renderer'
|
export { SkiaRenderer, type RenderOverlays, type RulerTheme } from './renderer'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { Canvas } from 'canvaskit-wasm'
|
||||||
|
|
||||||
import type { SceneGraph } from '@open-pencil/scene-graph'
|
import type { SceneGraph } from '@open-pencil/scene-graph'
|
||||||
|
|
||||||
import { drawGuides } from '#core/canvas/guides/render'
|
import { drawGuides } from '#core/canvas/guides/draw'
|
||||||
import type { RenderOverlays, SkiaRenderer } from '#core/canvas/renderer'
|
import type { RenderOverlays, SkiaRenderer } from '#core/canvas/renderer'
|
||||||
|
|
||||||
function measurementVisible(overlays: RenderOverlays): boolean {
|
function measurementVisible(overlays: RenderOverlays): boolean {
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import type { Canvas } from 'canvaskit-wasm'
|
||||||
import { SceneGraph } from '@open-pencil/scene-graph'
|
import { SceneGraph } from '@open-pencil/scene-graph'
|
||||||
import type { SceneNode } from '@open-pencil/scene-graph'
|
import type { SceneNode } from '@open-pencil/scene-graph'
|
||||||
|
|
||||||
import { drawGuides } from '#core/canvas/guides/render'
|
import { drawGuides } from '#core/canvas/guides/draw'
|
||||||
|
|
||||||
import { createMockCanvas, createMockRenderer, mockCalls } from './effects/helpers'
|
import { createMockCanvas, createMockRenderer, mockCalls } from '../effects/helpers'
|
||||||
|
|
||||||
function graphWithGuides(guides: SceneNode['guides']): SceneGraph {
|
function graphWithGuides(guides: SceneNode['guides']): SceneGraph {
|
||||||
const page = {
|
const page = {
|
||||||
|
|
@ -3,11 +3,8 @@ import { describe, expect, test } from 'bun:test'
|
||||||
import { SceneGraph } from '@open-pencil/scene-graph'
|
import { SceneGraph } from '@open-pencil/scene-graph'
|
||||||
import type { SceneNode } from '@open-pencil/scene-graph'
|
import type { SceneNode } from '@open-pencil/scene-graph'
|
||||||
|
|
||||||
import {
|
import { distanceToGuideSegment, getGuideScreenSegment } from '#core/canvas/guides/geometry'
|
||||||
distanceToGuideSegment,
|
import { hitTestGuides } from '#core/canvas/guides/hit-test'
|
||||||
getGuideScreenSegment,
|
|
||||||
hitTestGuides
|
|
||||||
} from '#core/canvas/guides/geometry'
|
|
||||||
|
|
||||||
function pageWithGuide(): { graph: SceneGraph; page: SceneNode } {
|
function pageWithGuide(): { graph: SceneGraph; page: SceneNode } {
|
||||||
const page = {
|
const page = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue