Selaa lähdekoodia

Adds lines, improves transforms

main
Steve Ruiz 4 vuotta sitten
vanhempi
commit
b8d3b35b07

+ 1
- 1
components/canvas/bounds.tsx Näytä tiedosto

@@ -27,7 +27,7 @@ export default function Bounds() {
27 27
         height={height}
28 28
         pointerEvents="none"
29 29
       />
30
-      {width * zoom > 8 && (
30
+      {width * zoom > 8 && height * zoom > 8 && (
31 31
         <>
32 32
           <EdgeHorizontal
33 33
             x={minX + p}

+ 5
- 6
components/canvas/shape.tsx Näytä tiedosto

@@ -7,13 +7,12 @@ import styled from "styles"
7 7
 function Shape({ id }: { id: string }) {
8 8
   const rGroup = useRef<SVGGElement>(null)
9 9
 
10
+  const isSelected = useSelector((state) => state.values.selectedIds.has(id))
11
+
10 12
   const shape = useSelector(
11
-    ({ data: { currentPageId, document } }) =>
12
-      document.pages[currentPageId].shapes[id]
13
+    ({ data }) => data.document.pages[data.currentPageId].shapes[id]
13 14
   )
14 15
 
15
-  const isSelected = useSelector((state) => state.values.selectedIds.has(id))
16
-
17 16
   const handlePointerDown = useCallback(
18 17
     (e: React.PointerEvent) => {
19 18
       e.stopPropagation()
@@ -33,12 +32,12 @@ function Shape({ id }: { id: string }) {
33 32
   )
34 33
 
35 34
   const handlePointerEnter = useCallback(
36
-    (e: React.PointerEvent) => state.send("HOVERED_SHAPE", { id }),
35
+    () => state.send("HOVERED_SHAPE", { id }),
37 36
     [id]
38 37
   )
39 38
 
40 39
   const handlePointerLeave = useCallback(
41
-    (e: React.PointerEvent) => state.send("UNHOVERED_SHAPE", { id }),
40
+    () => state.send("UNHOVERED_SHAPE", { id }),
42 41
     [id]
43 42
   )
44 43
   return (

+ 19
- 0
lib/shapes/base-shape.tsx Näytä tiedosto

@@ -0,0 +1,19 @@
1
+import { Bounds, Shape } from "types"
2
+
3
+export default interface ShapeUtil<K extends Shape> {
4
+  create(props: Partial<K>): K
5
+  getBounds(this: ShapeUtil<K>, shape: K): Bounds
6
+  hitTest(this: ShapeUtil<K>, shape: K, test: number[]): boolean
7
+  hitTestBounds(this: ShapeUtil<K>, shape: K, bounds: Bounds): boolean
8
+  rotate(this: ShapeUtil<K>, shape: K): K
9
+  translate(this: ShapeUtil<K>, shape: K, delta: number[]): K
10
+  scale(this: ShapeUtil<K>, shape: K, scale: number): K
11
+  stretch(this: ShapeUtil<K>, shape: K, scaleX: number, scaleY: number): K
12
+  render(this: ShapeUtil<K>, shape: K): JSX.Element
13
+}
14
+
15
+export function createShape<T extends Shape>(
16
+  shape: ShapeUtil<T>
17
+): ShapeUtil<T> {
18
+  return shape
19
+}

+ 5
- 1
lib/shapes/circle.tsx Näytä tiedosto

@@ -88,8 +88,12 @@ const circle = createShape<CircleShape>({
88 88
   },
89 89
 
90 90
   transform(shape, bounds) {
91
-    shape.point = [bounds.minX, bounds.minY]
91
+    // shape.point = [bounds.minX, bounds.minY]
92 92
     shape.radius = Math.min(bounds.width, bounds.height) / 2
93
+    shape.point = [
94
+      bounds.minX + bounds.width / 2 - shape.radius,
95
+      bounds.minY + bounds.height / 2 - shape.radius,
96
+    ]
93 97
 
94 98
     return shape
95 99
   },

+ 8
- 1
lib/shapes/index.tsx Näytä tiedosto

@@ -41,7 +41,14 @@ export interface ShapeUtility<K extends Shape> {
41 41
   translate(this: ShapeUtility<K>, shape: K, delta: number[]): K
42 42
 
43 43
   // Transform to fit a new bounding box.
44
-  transform(this: ShapeUtility<K>, shape: K, bounds: Bounds): K
44
+  transform(
45
+    this: ShapeUtility<K>,
46
+    shape: K,
47
+    bounds: Bounds & { isFlippedX: boolean; isFlippedY: boolean },
48
+    initialShape: K,
49
+    initialShapeBounds: BoundsSnapshot,
50
+    initialBounds: Bounds
51
+  ): K
45 52
 
46 53
   // Apply a scale to a shape.
47 54
   scale(this: ShapeUtility<K>, shape: K, scale: number): K

+ 18
- 12
lib/shapes/line.tsx Näytä tiedosto

@@ -16,15 +16,23 @@ const line = createShape<LineShape>({
16 16
       parentId: "page0",
17 17
       childIndex: 0,
18 18
       point: [0, 0],
19
-      vector: [0, 0],
19
+      direction: [0, 0],
20 20
       rotation: 0,
21 21
       style: {},
22 22
       ...props,
23 23
     }
24 24
   },
25 25
 
26
-  render({ id }) {
27
-    return <circle id={id} cx={4} cy={4} r={4} />
26
+  render({ id, direction }) {
27
+    const [x1, y1] = vec.add([0, 0], vec.mul(direction, 100000))
28
+    const [x2, y2] = vec.sub([0, 0], vec.mul(direction, 100000))
29
+
30
+    return (
31
+      <g id={id}>
32
+        <line x1={x1} y1={y1} x2={x2} y2={y2} />
33
+        <circle cx={0} cy={0} r={4} />
34
+      </g>
35
+    )
28 36
   },
29 37
 
30 38
   getBounds(shape) {
@@ -38,11 +46,11 @@ const line = createShape<LineShape>({
38 46
 
39 47
     const bounds = {
40 48
       minX: x,
41
-      maxX: x + 8,
49
+      maxX: x + 1,
42 50
       minY: y,
43
-      maxY: y + 8,
44
-      width: 8,
45
-      height: 8,
51
+      maxY: y + 1,
52
+      width: 1,
53
+      height: 1,
46 54
     }
47 55
 
48 56
     this.boundsCache.set(shape, bounds)
@@ -55,11 +63,7 @@ const line = createShape<LineShape>({
55 63
   },
56 64
 
57 65
   hitTestBounds(this, shape, brushBounds) {
58
-    const shapeBounds = this.getBounds(shape)
59
-    return (
60
-      boundsContained(shapeBounds, brushBounds) ||
61
-      intersectCircleBounds(shape.point, 4, brushBounds).length > 0
62
-    )
66
+    return true
63 67
   },
64 68
 
65 69
   rotate(shape) {
@@ -80,6 +84,8 @@ const line = createShape<LineShape>({
80 84
   },
81 85
 
82 86
   transform(shape, bounds) {
87
+    shape.point = [bounds.minX, bounds.minY]
88
+
83 89
     return shape
84 90
   },
85 91
 })

+ 14
- 9
lib/shapes/polyline.tsx Näytä tiedosto

@@ -90,15 +90,20 @@ const polyline = createShape<PolylineShape>({
90 90
     return shape
91 91
   },
92 92
 
93
-  transform(shape, bounds) {
94
-    const currentBounds = this.getBounds(shape)
95
-
96
-    const scaleX = bounds.width / currentBounds.width
97
-    const scaleY = bounds.height / currentBounds.height
98
-
99
-    shape.points = shape.points.map((point) => {
100
-      let pt = vec.mulV(point, [scaleX, scaleY])
101
-      return pt
93
+  transform(shape, bounds, initialShape, initialShapeBounds) {
94
+    shape.points = shape.points.map((_, i) => {
95
+      const [x, y] = initialShape.points[i]
96
+
97
+      return [
98
+        bounds.width *
99
+          (bounds.isFlippedX
100
+            ? 1 - x / initialShapeBounds.width
101
+            : x / initialShapeBounds.width),
102
+        bounds.height *
103
+          (bounds.isFlippedY
104
+            ? 1 - y / initialShapeBounds.height
105
+            : y / initialShapeBounds.height),
106
+      ]
102 107
     })
103 108
 
104 109
     shape.point = [bounds.minX, bounds.minY]

+ 1
- 1
lib/shapes/ray.tsx Näytä tiedosto

@@ -16,7 +16,7 @@ const ray = createShape<RayShape>({
16 16
       parentId: "page0",
17 17
       childIndex: 0,
18 18
       point: [0, 0],
19
-      vector: [0, 0],
19
+      direction: [0, 0],
20 20
       rotation: 0,
21 21
       style: {},
22 22
       ...props,

+ 2
- 1
state/commands/index.ts Näytä tiedosto

@@ -1,5 +1,6 @@
1 1
 import translate from "./translate-command"
2
+import transform from "./transform-command"
2 3
 
3
-const commands = { translate }
4
+const commands = { translate, transform }
4 5
 
5 6
 export default commands

+ 67
- 0
state/commands/transform-command.ts Näytä tiedosto

@@ -0,0 +1,67 @@
1
+import Command from "./command"
2
+import history from "../history"
3
+import { Data } from "types"
4
+import { TransformSnapshot } from "state/sessions/transform-session"
5
+import { getShapeUtils } from "lib/shapes"
6
+
7
+export default function translateCommand(
8
+  data: Data,
9
+  before: TransformSnapshot,
10
+  after: TransformSnapshot
11
+) {
12
+  history.execute(
13
+    data,
14
+    new Command({
15
+      name: "translate_shapes",
16
+      category: "canvas",
17
+      do(data) {
18
+        const { shapeBounds, initialBounds, currentPageId, selectedIds } = after
19
+        const { shapes } = data.document.pages[currentPageId]
20
+
21
+        selectedIds.forEach((id) => {
22
+          const { initialShape, initialShapeBounds } = shapeBounds[id]
23
+          const shape = shapes[id]
24
+
25
+          getShapeUtils(shape).transform(
26
+            shape,
27
+            {
28
+              ...initialShapeBounds,
29
+              isFlippedX: false,
30
+              isFlippedY: false,
31
+            },
32
+            initialShape,
33
+            initialShapeBounds,
34
+            initialBounds
35
+          )
36
+        })
37
+      },
38
+      undo(data) {
39
+        const {
40
+          shapeBounds,
41
+          initialBounds,
42
+          currentPageId,
43
+          selectedIds,
44
+        } = before
45
+
46
+        const { shapes } = data.document.pages[currentPageId]
47
+
48
+        selectedIds.forEach((id) => {
49
+          const { initialShape, initialShapeBounds } = shapeBounds[id]
50
+          const shape = shapes[id]
51
+
52
+          getShapeUtils(shape).transform(
53
+            shape,
54
+            {
55
+              ...initialShapeBounds,
56
+              isFlippedX: false,
57
+              isFlippedY: false,
58
+            },
59
+            initialShape,
60
+            initialShapeBounds,
61
+            initialBounds
62
+          )
63
+        })
64
+      },
65
+    })
66
+  )
67
+}

+ 16
- 4
state/data.ts Näytä tiedosto

@@ -15,7 +15,7 @@ export const defaultDocument: Data["document"] = {
15 15
           childIndex: 3,
16 16
           point: [500, 100],
17 17
           style: {
18
-            fill: "#aaa",
18
+            fill: "#AAA",
19 19
             stroke: "#777",
20 20
             strokeWidth: 1,
21 21
           },
@@ -27,7 +27,7 @@ export const defaultDocument: Data["document"] = {
27 27
           point: [100, 100],
28 28
           radius: 50,
29 29
           style: {
30
-            fill: "#aaa",
30
+            fill: "#AAA",
31 31
             stroke: "#777",
32 32
             strokeWidth: 1,
33 33
           },
@@ -40,7 +40,7 @@ export const defaultDocument: Data["document"] = {
40 40
           radiusX: 50,
41 41
           radiusY: 30,
42 42
           style: {
43
-            fill: "#aaa",
43
+            fill: "#AAA",
44 44
             stroke: "#777",
45 45
             strokeWidth: 1,
46 46
           },
@@ -70,7 +70,19 @@ export const defaultDocument: Data["document"] = {
70 70
           point: [300, 300],
71 71
           size: [200, 200],
72 72
           style: {
73
-            fill: "#aaa",
73
+            fill: "#AAA",
74
+            stroke: "#777",
75
+            strokeWidth: 1,
76
+          },
77
+        }),
78
+        shape6: shapeUtils[ShapeType.Line].create({
79
+          id: "shape6",
80
+          name: "Shape 6",
81
+          childIndex: 1,
82
+          point: [400, 400],
83
+          direction: [0.2, 0.2],
84
+          style: {
85
+            fill: "#AAA",
74 86
             stroke: "#777",
75 87
             strokeWidth: 1,
76 88
           },

+ 2
- 4
state/sessions/brush-session.ts Näytä tiedosto

@@ -1,7 +1,7 @@
1 1
 import { current } from "immer"
2 2
 import { ShapeUtil, Bounds, Data, Shapes } from "types"
3 3
 import BaseSession from "./base-session"
4
-import shapes from "lib/shapes"
4
+import shapes, { getShapeUtils } from "lib/shapes"
5 5
 import { getBoundsFromPoints } from "utils/utils"
6 6
 import * as vec from "utils/vec"
7 7
 
@@ -68,9 +68,7 @@ export default class BrushSession extends BaseSession {
68 68
         .map((shape) => ({
69 69
           id: shape.id,
70 70
           test: (brushBounds: Bounds): boolean =>
71
-            (shapes[shape.type] as ShapeUtil<
72
-              Shapes[typeof shape.type]
73
-            >).hitTestBounds(shape, brushBounds),
71
+            getShapeUtils(shape).hitTestBounds(shape, brushBounds),
74 72
         })),
75 73
     }
76 74
   }

+ 100
- 83
state/sessions/transform-session.ts Näytä tiedosto

@@ -1,4 +1,10 @@
1
-import { Data, TransformEdge, TransformCorner, Bounds } from "types"
1
+import {
2
+  Data,
3
+  TransformEdge,
4
+  TransformCorner,
5
+  Bounds,
6
+  BoundsSnapshot,
7
+} from "types"
2 8
 import * as vec from "utils/vec"
3 9
 import BaseSession from "./base-session"
4 10
 import commands from "state/commands"
@@ -11,7 +17,6 @@ export default class TransformSession extends BaseSession {
11 17
   transformType: TransformEdge | TransformCorner
12 18
   origin: number[]
13 19
   snapshot: TransformSnapshot
14
-  currentBounds: Bounds
15 20
   corners: {
16 21
     a: number[]
17 22
     b: number[]
@@ -29,8 +34,6 @@ export default class TransformSession extends BaseSession {
29 34
 
30 35
     const { minX, minY, maxX, maxY } = this.snapshot.initialBounds
31 36
 
32
-    this.currentBounds = { ...this.snapshot.initialBounds }
33
-
34 37
     this.corners = {
35 38
       a: [minX, minY],
36 39
       b: [maxX, maxY],
@@ -38,130 +41,144 @@ export default class TransformSession extends BaseSession {
38 41
   }
39 42
 
40 43
   update(data: Data, point: number[]) {
41
-    const { shapeBounds, currentPageId, selectedIds } = this.snapshot
42 44
     const {
43
-      document: { pages },
44
-    } = data
45
+      shapeBounds,
46
+      initialBounds,
47
+      currentPageId,
48
+      selectedIds,
49
+    } = this.snapshot
50
+
51
+    const { shapes } = data.document.pages[currentPageId]
45 52
 
46 53
     let [x, y] = point
47
-    const { corners, transformType } = this
54
+
55
+    const {
56
+      corners: { a, b },
57
+      transformType,
58
+    } = this
48 59
 
49 60
     // Edge Transform
50 61
 
51 62
     switch (transformType) {
52 63
       case TransformEdge.Top: {
53
-        corners.a[1] = y
64
+        a[1] = y
54 65
         break
55 66
       }
56 67
       case TransformEdge.Right: {
57
-        corners.b[0] = x
68
+        b[0] = x
58 69
         break
59 70
       }
60 71
       case TransformEdge.Bottom: {
61
-        corners.b[1] = y
72
+        b[1] = y
62 73
         break
63 74
       }
64 75
       case TransformEdge.Left: {
65
-        corners.a[0] = x
76
+        a[0] = x
66 77
         break
67 78
       }
68 79
       case TransformCorner.TopLeft: {
69
-        corners.a[1] = y
70
-        corners.a[0] = x
80
+        a[1] = y
81
+        a[0] = x
71 82
         break
72 83
       }
73 84
       case TransformCorner.TopRight: {
74
-        corners.b[0] = x
75
-        corners.a[1] = y
85
+        b[0] = x
86
+        a[1] = y
76 87
         break
77 88
       }
78 89
       case TransformCorner.BottomRight: {
79
-        corners.b[1] = y
80
-        corners.b[0] = x
90
+        b[1] = y
91
+        b[0] = x
81 92
         break
82 93
       }
83 94
       case TransformCorner.BottomLeft: {
84
-        corners.a[0] = x
85
-        corners.b[1] = y
95
+        a[0] = x
96
+        b[1] = y
86 97
         break
87 98
       }
88 99
     }
89 100
 
101
+    // Calculate new common (externior) bounding box
90 102
     const newBounds = {
91
-      minX: Math.min(corners.a[0], corners.b[0]),
92
-      minY: Math.min(corners.a[1], corners.b[1]),
93
-      maxX: Math.max(corners.a[0], corners.b[0]),
94
-      maxY: Math.max(corners.a[1], corners.b[1]),
95
-      width: Math.abs(corners.b[0] - corners.a[0]),
96
-      height: Math.abs(corners.b[1] - corners.a[1]),
103
+      minX: Math.min(a[0], b[0]),
104
+      minY: Math.min(a[1], b[1]),
105
+      maxX: Math.max(a[0], b[0]),
106
+      maxY: Math.max(a[1], b[1]),
107
+      width: Math.abs(b[0] - a[0]),
108
+      height: Math.abs(b[1] - a[1]),
97 109
     }
98 110
 
99
-    const isFlippedX = corners.b[0] - corners.a[0] < 0
100
-    const isFlippedY = corners.b[1] - corners.a[1] < 0
101
-
102
-    // const dx = newBounds.minX - currentBounds.minX
103
-    // const dy = newBounds.minY - currentBounds.minY
104
-    // const scaleX = newBounds.width / currentBounds.width
105
-    // const scaleY = newBounds.height / currentBounds.height
111
+    const isFlippedX = b[0] < a[0]
112
+    const isFlippedY = b[1] < a[1]
106 113
 
107
-    this.currentBounds = newBounds
114
+    // Now work backward to calculate a new bounding box for each of the shapes.
108 115
 
109 116
     selectedIds.forEach((id) => {
110
-      const { nx, nmx, nw, ny, nmy, nh } = shapeBounds[id]
117
+      const { initialShape, initialShapeBounds } = shapeBounds[id]
118
+      const { nx, nmx, nw, ny, nmy, nh } = initialShapeBounds
119
+      const shape = shapes[id]
111 120
 
112 121
       const minX = newBounds.minX + (isFlippedX ? nmx : nx) * newBounds.width
113 122
       const minY = newBounds.minY + (isFlippedY ? nmy : ny) * newBounds.height
114 123
       const width = nw * newBounds.width
115 124
       const height = nh * newBounds.height
116 125
 
117
-      const shape = pages[currentPageId].shapes[id]
118
-
119
-      getShapeUtils(shape).transform(shape, {
126
+      const newShapeBounds = {
120 127
         minX,
121 128
         minY,
122 129
         maxX: minX + width,
123 130
         maxY: minY + height,
124 131
         width,
125 132
         height,
126
-      })
127
-      // utils.stretch(shape, scaleX, scaleY)
128
-    })
133
+        isFlippedX,
134
+        isFlippedY,
135
+      }
129 136
 
130
-    // switch (this.transformHandle) {
131
-    //   case TransformEdge.Top:
132
-    //   case TransformEdge.Left:
133
-    //   case TransformEdge.Right:
134
-    //   case TransformEdge.Bottom: {
135
-    //     for (let id in shapeBounds) {
136
-    //       const { ny, nmy, nh } = shapeBounds[id]
137
-    //       const minY = v.my + (v.y1 < v.y0 ? nmy : ny) * v.mh
138
-    //       const height = nh * v.mh
139
-
140
-    //       const shape = pages[currentPageId].shapes[id]
141
-
142
-    //       getShapeUtils(shape).transform(shape)
143
-    //     }
144
-    //   }
145
-    //   case TransformCorner.TopLeft:
146
-    //   case TransformCorner.TopRight:
147
-    //   case TransformCorner.BottomLeft:
148
-    //   case TransformCorner.BottomRight: {
149
-    //   }
150
-    // }
137
+      // Pass the new data to the shape's transform utility for mutation.
138
+      // Most shapes should be able to transform using only the bounding box,
139
+      // however some shapes (e.g. those with internal points) will need more
140
+      // data here too.
141
+
142
+      getShapeUtils(shape).transform(
143
+        shape,
144
+        newShapeBounds,
145
+        initialShape,
146
+        initialShapeBounds,
147
+        initialBounds
148
+      )
149
+    })
151 150
   }
152 151
 
153 152
   cancel(data: Data) {
154
-    const { currentPageId } = this.snapshot
155
-    const { document } = data
153
+    const {
154
+      shapeBounds,
155
+      initialBounds,
156
+      currentPageId,
157
+      selectedIds,
158
+    } = this.snapshot
156 159
 
157
-    // for (let id in shapes) {
158
-    // Restore shape using original bounds
159
-    // document.pages[currentPageId].shapes[id]
160
-    // }
160
+    const { shapes } = data.document.pages[currentPageId]
161
+
162
+    selectedIds.forEach((id) => {
163
+      const shape = shapes.shapes[id]
164
+      const { initialShape, initialShapeBounds } = shapeBounds[id]
165
+
166
+      getShapeUtils(shape).transform(
167
+        shape,
168
+        {
169
+          ...initialShapeBounds,
170
+          isFlippedX: false,
171
+          isFlippedY: false,
172
+        },
173
+        initialShape,
174
+        initialShapeBounds,
175
+        initialBounds
176
+      )
177
+    })
161 178
   }
162 179
 
163 180
   complete(data: Data) {
164
-    // commands.translate(data, this.snapshot, getTransformSnapshot(data))
181
+    commands.transform(data, this.snapshot, getTransformSnapshot(data))
165 182
   }
166 183
 }
167 184
 
@@ -172,21 +189,18 @@ export function getTransformSnapshot(data: Data) {
172 189
     currentPageId,
173 190
   } = current(data)
174 191
 
192
+  const pageShapes = pages[currentPageId].shapes
193
+
175 194
   // A mapping of selected shapes and their bounds
176 195
   const shapesBounds = Object.fromEntries(
177 196
     Array.from(selectedIds.values()).map((id) => {
178
-      const shape = pages[currentPageId].shapes[id]
197
+      const shape = pageShapes[id]
179 198
       return [shape.id, getShapeUtils(shape).getBounds(shape)]
180 199
     })
181 200
   )
182 201
 
183 202
   // The common (exterior) bounds of the selected shapes
184
-  const bounds = getCommonBounds(
185
-    ...Array.from(selectedIds.values()).map((id) => {
186
-      const shape = pages[currentPageId].shapes[id]
187
-      return getShapeUtils(shape).getBounds(shape)
188
-    })
189
-  )
203
+  const bounds = getCommonBounds(...Object.values(shapesBounds))
190 204
 
191 205
   // Return a mapping of shapes to bounds together with the relative
192 206
   // positions of the shape's bounds within the common bounds shape.
@@ -200,13 +214,16 @@ export function getTransformSnapshot(data: Data) {
200 214
         return [
201 215
           id,
202 216
           {
203
-            ...bounds,
204
-            nx: (minX - bounds.minX) / bounds.width,
205
-            ny: (minY - bounds.minY) / bounds.height,
206
-            nmx: 1 - (minX + width - bounds.minX) / bounds.width,
207
-            nmy: 1 - (minY + height - bounds.minY) / bounds.height,
208
-            nw: width / bounds.width,
209
-            nh: height / bounds.height,
217
+            initialShape: pageShapes[id],
218
+            initialShapeBounds: {
219
+              ...shapesBounds[id],
220
+              nx: (minX - bounds.minX) / bounds.width,
221
+              ny: (minY - bounds.minY) / bounds.height,
222
+              nmx: 1 - (minX + width - bounds.minX) / bounds.width,
223
+              nmy: 1 - (minY + height - bounds.minY) / bounds.height,
224
+              nw: width / bounds.width,
225
+              nh: height / bounds.height,
226
+            },
210 227
           },
211 228
         ]
212 229
       })

+ 2
- 2
types.ts Näytä tiedosto

@@ -65,12 +65,12 @@ export interface EllipseShape extends BaseShape {
65 65
 
66 66
 export interface LineShape extends BaseShape {
67 67
   type: ShapeType.Line
68
-  vector: number[]
68
+  direction: number[]
69 69
 }
70 70
 
71 71
 export interface RayShape extends BaseShape {
72 72
   type: ShapeType.Ray
73
-  vector: number[]
73
+  direction: number[]
74 74
 }
75 75
 
76 76
 export interface PolylineShape extends BaseShape {

Loading…
Peruuta
Tallenna