Pārlūkot izejas kodu

fixes code bug, adds sketchy circle

main
Steve Ruiz 4 gadus atpakaļ
vecāks
revīzija
5a7e79121a

+ 0
- 1
components/canvas/cursor.tsx Parādīt failu

@@ -6,7 +6,6 @@ export default function Cursor() {
6 6
 
7 7
   useEffect(() => {
8 8
     function updatePosition(e: PointerEvent) {
9
-      console.log('hi')
10 9
       const cursor = rCursor.current
11 10
 
12 11
       cursor.setAttribute(

+ 1
- 1
components/code-panel/code-panel.tsx Parādīt failu

@@ -82,7 +82,7 @@ export default function CodePanel() {
82 82
         let error = null
83 83
 
84 84
         try {
85
-          const { shapes, controls } = generateFromCode(data.code)
85
+          const { shapes, controls } = generateFromCode(state.data, data.code)
86 86
           state.send('GENERATED_FROM_CODE', { shapes, controls })
87 87
         } catch (e) {
88 88
           console.error(e)

+ 2
- 2
lib/code/circle.ts Parādīt failu

@@ -11,10 +11,10 @@ export default class Circle extends CodeShape<CircleShape> {
11 11
     super({
12 12
       id: uuid(),
13 13
       seed: Math.random(),
14
+      parentId: (window as any).currentPageId,
14 15
       type: ShapeType.Circle,
15 16
       isGenerated: true,
16 17
       name: 'Circle',
17
-      parentId: 'page0',
18 18
       childIndex: 0,
19 19
       point: [0, 0],
20 20
       rotation: 0,
@@ -22,8 +22,8 @@ export default class Circle extends CodeShape<CircleShape> {
22 22
       isAspectRatioLocked: false,
23 23
       isLocked: false,
24 24
       isHidden: false,
25
-      style: defaultStyle,
26 25
       ...props,
26
+      style: { ...defaultStyle, ...props.style },
27 27
     })
28 28
   }
29 29
 

+ 2
- 2
lib/code/dot.ts Parādīt failu

@@ -11,10 +11,10 @@ export default class Dot extends CodeShape<DotShape> {
11 11
     super({
12 12
       id: uuid(),
13 13
       seed: Math.random(),
14
+      parentId: (window as any).currentPageId,
14 15
       type: ShapeType.Dot,
15 16
       isGenerated: true,
16 17
       name: 'Dot',
17
-      parentId: 'page0',
18 18
       childIndex: 0,
19 19
       point: [0, 0],
20 20
       rotation: 0,
@@ -25,7 +25,7 @@ export default class Dot extends CodeShape<DotShape> {
25 25
       style: {
26 26
         ...defaultStyle,
27 27
         ...props.style,
28
-        isFilled: false,
28
+        isFilled: true,
29 29
       },
30 30
     })
31 31
   }

+ 2
- 2
lib/code/ellipse.ts Parādīt failu

@@ -11,10 +11,10 @@ export default class Ellipse extends CodeShape<EllipseShape> {
11 11
     super({
12 12
       id: uuid(),
13 13
       seed: Math.random(),
14
+      parentId: (window as any).currentPageId,
14 15
       type: ShapeType.Ellipse,
15 16
       isGenerated: true,
16 17
       name: 'Ellipse',
17
-      parentId: 'page0',
18 18
       childIndex: 0,
19 19
       point: [0, 0],
20 20
       radiusX: 20,
@@ -23,8 +23,8 @@ export default class Ellipse extends CodeShape<EllipseShape> {
23 23
       isAspectRatioLocked: false,
24 24
       isLocked: false,
25 25
       isHidden: false,
26
-      style: defaultStyle,
27 26
       ...props,
27
+      style: { ...defaultStyle, ...props.style },
28 28
     })
29 29
   }
30 30
 

+ 21
- 18
lib/code/generate.ts Parādīt failu

@@ -1,15 +1,15 @@
1
-import Rectangle from "./rectangle"
2
-import Circle from "./circle"
3
-import Ellipse from "./ellipse"
4
-import Polyline from "./polyline"
5
-import Dot from "./dot"
6
-import Ray from "./ray"
7
-import Line from "./line"
8
-import Vector from "./vector"
9
-import Utils from "./utils"
10
-import { NumberControl, VectorControl, codeControls, controls } from "./control"
11
-import { codeShapes } from "./index"
12
-import { CodeControl } from "types"
1
+import Rectangle from './rectangle'
2
+import Circle from './circle'
3
+import Ellipse from './ellipse'
4
+import Polyline from './polyline'
5
+import Dot from './dot'
6
+import Ray from './ray'
7
+import Line from './line'
8
+import Vector from './vector'
9
+import Utils from './utils'
10
+import { NumberControl, VectorControl, codeControls, controls } from './control'
11
+import { codeShapes } from './index'
12
+import { CodeControl, Data } from 'types'
13 13
 
14 14
 const baseScope = {
15 15
   Dot,
@@ -30,12 +30,14 @@ const baseScope = {
30 30
  * collected shapes as an array.
31 31
  * @param code
32 32
  */
33
-export function generateFromCode(code: string) {
33
+export function generateFromCode(data: Data, code: string) {
34 34
   codeControls.clear()
35 35
   codeShapes.clear()
36 36
   ;(window as any).isUpdatingCode = false
37
+  ;(window as any).currentPageId = data.currentPageId
37 38
 
38
-  const scope = { ...baseScope, controls }
39
+  const { currentPageId } = data
40
+  const scope = { ...baseScope, controls, currentPageId }
39 41
 
40 42
   new Function(...Object.keys(scope), `${code}`)(...Object.values(scope))
41 43
 
@@ -53,15 +55,16 @@ export function generateFromCode(code: string) {
53 55
  * collected shapes as an array.
54 56
  * @param code
55 57
  */
56
-export function updateFromCode(
57
-  code: string,
58
-  controls: Record<string, CodeControl>
59
-) {
58
+export function updateFromCode(data: Data, code: string) {
60 59
   codeShapes.clear()
61 60
   ;(window as any).isUpdatingCode = true
61
+  ;(window as any).currentPageId = data.currentPageId
62
+
63
+  const { currentPageId } = data
62 64
 
63 65
   const scope = {
64 66
     ...baseScope,
67
+    currentPageId,
65 68
     controls: Object.fromEntries(
66 69
       Object.entries(controls).map(([id, control]) => [
67 70
         control.label,

+ 1
- 1
lib/code/line.ts Parādīt failu

@@ -12,10 +12,10 @@ export default class Line extends CodeShape<LineShape> {
12 12
     super({
13 13
       id: uuid(),
14 14
       seed: Math.random(),
15
+      parentId: (window as any).currentPageId,
15 16
       type: ShapeType.Line,
16 17
       isGenerated: true,
17 18
       name: 'Line',
18
-      parentId: 'page0',
19 19
       childIndex: 0,
20 20
       point: [0, 0],
21 21
       direction: [-0.5, 0.5],

+ 1
- 1
lib/code/polyline.ts Parādīt failu

@@ -12,10 +12,10 @@ export default class Polyline extends CodeShape<PolylineShape> {
12 12
     super({
13 13
       id: uuid(),
14 14
       seed: Math.random(),
15
+      parentId: (window as any).currentPageId,
15 16
       type: ShapeType.Polyline,
16 17
       isGenerated: true,
17 18
       name: 'Polyline',
18
-      parentId: 'page0',
19 19
       childIndex: 0,
20 20
       point: [0, 0],
21 21
       points: [[0, 0]],

+ 2
- 2
lib/code/rectangle.ts Parādīt failu

@@ -12,10 +12,10 @@ export default class Rectangle extends CodeShape<RectangleShape> {
12 12
     super({
13 13
       id: uuid(),
14 14
       seed: Math.random(),
15
+      parentId: (window as any).currentPageId,
15 16
       type: ShapeType.Rectangle,
16 17
       isGenerated: true,
17 18
       name: 'Rectangle',
18
-      parentId: 'page0',
19 19
       childIndex: 0,
20 20
       point: [0, 0],
21 21
       size: [100, 100],
@@ -24,8 +24,8 @@ export default class Rectangle extends CodeShape<RectangleShape> {
24 24
       isAspectRatioLocked: false,
25 25
       isLocked: false,
26 26
       isHidden: false,
27
-      style: defaultStyle,
28 27
       ...props,
28
+      style: { ...defaultStyle, ...props.style },
29 29
     })
30 30
   }
31 31
 

+ 2
- 2
lib/code/utils.ts Parādīt failu

@@ -1,5 +1,5 @@
1
-import { Bounds } from "types"
2
-import Vector, { Point } from "./vector"
1
+import { Bounds } from 'types'
2
+import Vector, { Point } from './vector'
3 3
 
4 4
 export default class Utils {
5 5
   static getRayRayIntersection(p0: Vector, n0: Vector, p1: Vector, n1: Vector) {

+ 2
- 2
lib/code/vector.ts Parādīt failu

@@ -16,7 +16,7 @@ export default class Vector {
16 16
   constructor(vector: Vector, b?: undefined)
17 17
   constructor(options: Point, b?: undefined)
18 18
   constructor(a: VectorOptions | Vector | number, b?: number) {
19
-    if (typeof a === "number") {
19
+    if (typeof a === 'number') {
20 20
       this.x = a
21 21
       this.y = b
22 22
     } else {
@@ -415,7 +415,7 @@ export default class Vector {
415 415
   }
416 416
 
417 417
   static cast(v: Point | Vector) {
418
-    return "cast" in v ? v : new Vector(v)
418
+    return 'cast' in v ? v : new Vector(v)
419 419
   }
420 420
 
421 421
   static from(v: Vector) {

+ 1
- 1
lib/shape-utils/dot.tsx Parādīt failu

@@ -34,7 +34,7 @@ const dot = registerShapeUtils<DotShape>({
34 34
   },
35 35
 
36 36
   render({ id }) {
37
-    return <use href="#dot" />
37
+    return <use id={id} href="#dot" fill="black" />
38 38
   },
39 39
 
40 40
   getBounds(shape) {

+ 89
- 9
lib/shape-utils/ellipse.tsx Parādīt failu

@@ -1,17 +1,25 @@
1 1
 import { v4 as uuid } from 'uuid'
2 2
 import * as vec from 'utils/vec'
3 3
 import { EllipseShape, ShapeType } from 'types'
4
-import { registerShapeUtils } from './index'
4
+import { getShapeUtils, registerShapeUtils } from './index'
5 5
 import { boundsContained, getRotatedEllipseBounds } from 'utils/bounds'
6 6
 import { intersectEllipseBounds } from 'utils/intersections'
7 7
 import { pointInEllipse } from 'utils/hitTests'
8 8
 import {
9
+  ease,
9 10
   getBoundsFromPoints,
10 11
   getRotatedCorners,
12
+  getSvgPathFromStroke,
13
+  pointsBetween,
14
+  rng,
11 15
   rotateBounds,
16
+  shuffleArr,
12 17
   translateBounds,
13 18
 } from 'utils/utils'
14 19
 import { defaultStyle, getShapeStyle } from 'lib/shape-styles'
20
+import getStroke from 'perfect-freehand'
21
+
22
+const pathCache = new WeakMap<EllipseShape, string>([])
15 23
 
16 24
 const ellipse = registerShapeUtils<EllipseShape>({
17 25
   boundsCache: new WeakMap([]),
@@ -37,17 +45,39 @@ const ellipse = registerShapeUtils<EllipseShape>({
37 45
     }
38 46
   },
39 47
 
40
-  render({ id, radiusX, radiusY, style }) {
48
+  render(shape) {
49
+    const { id, radiusX, radiusY, style } = shape
41 50
     const styles = getShapeStyle(style)
51
+
52
+    if (!pathCache.has(shape)) {
53
+      renderPath(shape)
54
+    }
55
+
56
+    const path = pathCache.get(shape)
57
+
42 58
     return (
43
-      <ellipse
44
-        id={id}
45
-        cx={radiusX}
46
-        cy={radiusY}
47
-        rx={Math.max(0, radiusX - Number(styles.strokeWidth) / 2)}
48
-        ry={Math.max(0, radiusY - Number(styles.strokeWidth) / 2)}
49
-      />
59
+      <g id={id}>
60
+        <ellipse
61
+          id={id}
62
+          cx={radiusX}
63
+          cy={radiusY}
64
+          rx={Math.max(0, radiusX - Number(styles.strokeWidth) / 2)}
65
+          ry={Math.max(0, radiusY - Number(styles.strokeWidth) / 2)}
66
+          stroke="none"
67
+        />
68
+        <path d={path} fill={styles.stroke} />
69
+      </g>
50 70
     )
71
+
72
+    // return (
73
+    //   <ellipse
74
+    //     id={id}
75
+    //     cx={radiusX}
76
+    //     cy={radiusY}
77
+    //     rx={Math.max(0, radiusX - Number(styles.strokeWidth) / 2)}
78
+    //     ry={Math.max(0, radiusY - Number(styles.strokeWidth) / 2)}
79
+    //   />
80
+    // )
51 81
   },
52 82
 
53 83
   getBounds(shape) {
@@ -129,3 +159,53 @@ const ellipse = registerShapeUtils<EllipseShape>({
129 159
 })
130 160
 
131 161
 export default ellipse
162
+
163
+function renderPath(shape: EllipseShape) {
164
+  const { style, id, radiusX, radiusY, point } = shape
165
+
166
+  const getRandom = rng(id)
167
+
168
+  const center = vec.sub(getShapeUtils(shape).getCenter(shape), point)
169
+
170
+  const strokeWidth = +getShapeStyle(style).strokeWidth
171
+
172
+  const rx = radiusX + getRandom() * strokeWidth
173
+  const ry = radiusY + getRandom() * strokeWidth
174
+
175
+  const points: number[][] = []
176
+  const start = Math.PI + Math.PI * getRandom()
177
+
178
+  const overlap = Math.PI / 12
179
+
180
+  for (let i = 2; i < 8; i++) {
181
+    const rads = start + overlap * 2 * (i / 8)
182
+    const x = rx * Math.cos(rads) + center[0]
183
+    const y = ry * Math.sin(rads) + center[1]
184
+    points.push([x, y])
185
+  }
186
+
187
+  for (let i = 5; i < 32; i++) {
188
+    const rads = start + overlap * 2 + Math.PI * 2.5 * ease(i / 35)
189
+    const x = rx * Math.cos(rads) + center[0]
190
+    const y = ry * Math.sin(rads) + center[1]
191
+    points.push([x, y])
192
+  }
193
+
194
+  for (let i = 0; i < 8; i++) {
195
+    const rads = start + overlap * 2 * (i / 4)
196
+    const x = rx * Math.cos(rads) + center[0]
197
+    const y = ry * Math.sin(rads) + center[1]
198
+    points.push([x, y])
199
+  }
200
+
201
+  const stroke = getStroke(points, {
202
+    size: 1 + strokeWidth * 2,
203
+    thinning: 0.6,
204
+    easing: (t) => t * t * t * t,
205
+    end: { taper: strokeWidth * 20 },
206
+    start: { taper: strokeWidth * 20 },
207
+    simulatePressure: false,
208
+  })
209
+
210
+  pathCache.set(shape, getSvgPathFromStroke(stroke))
211
+}

+ 15
- 32
lib/shape-utils/rectangle.tsx Parādīt failu

@@ -2,7 +2,13 @@ import { v4 as uuid } from 'uuid'
2 2
 import * as vec from 'utils/vec'
3 3
 import { RectangleShape, ShapeType } from 'types'
4 4
 import { registerShapeUtils } from './index'
5
-import { getSvgPathFromStroke, translateBounds, getNoise } from 'utils/utils'
5
+import {
6
+  getSvgPathFromStroke,
7
+  translateBounds,
8
+  rng,
9
+  shuffleArr,
10
+  pointsBetween,
11
+} from 'utils/utils'
6 12
 import { defaultStyle, getShapeStyle } from 'lib/shape-styles'
7 13
 import getStroke from 'perfect-freehand'
8 14
 
@@ -33,7 +39,7 @@ const rectangle = registerShapeUtils<RectangleShape>({
33 39
   },
34 40
 
35 41
   render(shape) {
36
-    const { id, size, radius, style, point } = shape
42
+    const { id, size, radius, style } = shape
37 43
     const styles = getShapeStyle(style)
38 44
 
39 45
     if (!pathCache.has(shape)) {
@@ -117,29 +123,16 @@ const rectangle = registerShapeUtils<RectangleShape>({
117 123
 
118 124
 export default rectangle
119 125
 
120
-function easeInOut(t: number) {
121
-  return t * (2 - t)
122
-}
123
-
124
-function ease(t: number) {
125
-  return t * t * t
126
-}
127
-
128
-function pointsBetween(a: number[], b: number[], steps = 6) {
129
-  return Array.from(Array(steps))
130
-    .map((_, i) => ease(i / steps))
131
-    .map((t) => [...vec.lrp(a, b, t), (1 - t) / 2])
132
-}
133
-
134 126
 function renderPath(shape: RectangleShape) {
135 127
   const styles = getShapeStyle(shape.style)
136 128
 
137
-  const noise = getNoise(shape.seed)
138
-  const off = -0.25 + shape.seed / 2
129
+  const getRandom = rng(shape.id)
130
+
131
+  const baseOffset = +styles.strokeWidth / 2
139 132
 
140 133
   const offsets = Array.from(Array(4)).map((_, i) => [
141
-    noise(i, i + 1) * off * 16,
142
-    noise(i + 2, i + 3) * off * 16,
134
+    getRandom() * baseOffset,
135
+    getRandom() * baseOffset,
143 136
   ])
144 137
 
145 138
   const [w, h] = shape.size
@@ -155,17 +148,11 @@ function renderPath(shape: RectangleShape) {
155 148
       pointsBetween(bl, tl),
156 149
       pointsBetween(tl, tr),
157 150
     ],
158
-    shape.id.charCodeAt(5)
151
+    Math.floor(5 + getRandom() * 4)
159 152
   )
160 153
 
161 154
   const stroke = getStroke(
162
-    [
163
-      ...lines.flat().slice(4),
164
-      ...lines[0].slice(0, 4),
165
-      lines[0][4],
166
-      lines[0][5],
167
-      lines[0][5],
168
-    ],
155
+    [...lines.flat().slice(2), ...lines[0], ...lines[0].slice(4)],
169 156
     {
170 157
       size: 1 + +styles.strokeWidth * 2,
171 158
       thinning: 0.6,
@@ -178,7 +165,3 @@ function renderPath(shape: RectangleShape) {
178 165
 
179 166
   pathCache.set(shape, getSvgPathFromStroke(stroke))
180 167
 }
181
-
182
-function shuffleArr<T>(arr: T[], offset: number): T[] {
183
-  return arr.map((_, i) => arr[(i + offset) % arr.length])
184
-}

+ 9
- 7
state/sessions/translate-session.ts Parādīt failu

@@ -33,9 +33,6 @@ export default class TranslateSession extends BaseSession {
33 33
     const { shapes } = getPage(data, currentPageId)
34 34
 
35 35
     const delta = vec.vec(this.origin, point)
36
-    const trueDelta = vec.sub(delta, this.prev)
37
-    this.delta = delta
38
-    this.prev = delta
39 36
 
40 37
     if (isAligned) {
41 38
       if (Math.abs(delta[0]) < Math.abs(delta[1])) {
@@ -45,13 +42,17 @@ export default class TranslateSession extends BaseSession {
45 42
       }
46 43
     }
47 44
 
45
+    const trueDelta = vec.sub(delta, this.prev)
46
+    this.delta = delta
47
+    this.prev = delta
48
+
48 49
     if (isCloning) {
49 50
       if (!this.isCloning) {
50 51
         this.isCloning = true
51 52
 
52
-        for (const { id, point } of initialShapes) {
53
+        for (const { id } of initialShapes) {
53 54
           const shape = shapes[id]
54
-          getShapeUtils(shape).translateTo(shape, point)
55
+          getShapeUtils(shape).translateBy(shape, trueDelta)
55 56
         }
56 57
 
57 58
         for (const clone of clones) {
@@ -70,9 +71,9 @@ export default class TranslateSession extends BaseSession {
70 71
         )
71 72
       }
72 73
 
73
-      for (const { id, point } of clones) {
74
+      for (const { id } of clones) {
74 75
         const shape = shapes[id]
75
-        getShapeUtils(shape).translateTo(shape, vec.add(point, delta))
76
+        getShapeUtils(shape).translateBy(shape, trueDelta)
76 77
       }
77 78
 
78 79
       updateParents(
@@ -186,6 +187,7 @@ export function getTranslateSnapshot(data: Data) {
186 187
     clones: selectedShapes
187 188
       .filter((shape) => shape.type !== ShapeType.Group)
188 189
       .flatMap((shape) => {
190
+        // TODO: Clone children recursively
189 191
         const clone = {
190 192
           ...shape,
191 193
           id: uuid(),

+ 2
- 2
state/state.ts Parādīt failu

@@ -1382,8 +1382,8 @@ const state = createState({
1382 1382
 
1383 1383
       try {
1384 1384
         const { shapes } = updateFromCode(
1385
-          data.document.code[data.currentCodeFileId].code,
1386
-          data.codeControls
1385
+          data,
1386
+          data.document.code[data.currentCodeFileId].code
1387 1387
         )
1388 1388
 
1389 1389
         commands.generate(data, data.currentPageId, shapes)

+ 37
- 60
utils/utils.ts Parādīt failu

@@ -1695,68 +1695,45 @@ const Grad = [
1695 1695
   [0, -1],
1696 1696
 ]
1697 1697
 
1698
-// Thanks to joshforisha
1699
-// https://github.com/joshforisha/fast-simplex-noise-js/blob/main/src/2d.ts
1700
-export function getNoise(seed = Math.random()) {
1701
-  const p = new Uint8Array(256)
1702
-  for (let i = 0; i < 256; i++) p[i] = i
1703
-
1704
-  let n: number
1705
-  let q: number
1706
-  for (let i = 255; i > 0; i--) {
1707
-    n = Math.floor((i + 1) * seed)
1708
-    q = p[i]
1709
-    p[i] = p[n]
1710
-    p[n] = q
1698
+/**
1699
+ * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift).
1700
+ * The result will always be betweeen -1 and 1.
1701
+ *
1702
+ * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).
1703
+ */
1704
+export function rng(seed = '') {
1705
+  let x = 0
1706
+  let y = 0
1707
+  let z = 0
1708
+  let w = 0
1709
+
1710
+  function next() {
1711
+    const t = x ^ (x << 11)
1712
+    x = y
1713
+    y = z
1714
+    z = w
1715
+    w ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0
1716
+    return w / 0x100000000
1711 1717
   }
1712 1718
 
1713
-  const perm = new Uint8Array(512)
1714
-  const permMod12 = new Uint8Array(512)
1715
-  for (let i = 0; i < 512; i++) {
1716
-    perm[i] = p[i & 255]
1717
-    permMod12[i] = perm[i] % 12
1719
+  for (var k = 0; k < seed.length + 64; k++) {
1720
+    x ^= seed.charCodeAt(k) | 0
1721
+    next()
1718 1722
   }
1719 1723
 
1720
-  return (x: number, y: number): number => {
1721
-    // Skew the input space to determine which simplex cell we're in
1722
-    const s = (x + y) * 0.5 * (Math.sqrt(3.0) - 1.0) // Hairy factor for 2D
1723
-    const i = Math.floor(x + s)
1724
-    const j = Math.floor(y + s)
1725
-    const t = (i + j) * G2
1726
-    const X0 = i - t // Unskew the cell origin back to (x,y) space
1727
-    const Y0 = j - t
1728
-    const x0 = x - X0 // The x,y distances from the cell origin
1729
-    const y0 = y - Y0
1730
-
1731
-    // Determine which simplex we are in.
1732
-    const i1 = x0 > y0 ? 1 : 0
1733
-    const j1 = x0 > y0 ? 0 : 1
1734
-
1735
-    // Offsets for corners
1736
-    const x1 = x0 - i1 + G2
1737
-    const y1 = y0 - j1 + G2
1738
-    const x2 = x0 - 1.0 + 2.0 * G2
1739
-    const y2 = y0 - 1.0 + 2.0 * G2
1740
-
1741
-    // Work out the hashed gradient indices of the three simplex corners
1742
-    const ii = i & 255
1743
-    const jj = j & 255
1744
-    const g0 = Grad[permMod12[ii + perm[jj]]]
1745
-    const g1 = Grad[permMod12[ii + i1 + perm[jj + j1]]]
1746
-    const g2 = Grad[permMod12[ii + 1 + perm[jj + 1]]]
1747
-
1748
-    // Calculate the contribution from the three corners
1749
-    const t0 = 0.5 - x0 * x0 - y0 * y0
1750
-    const n0 = t0 < 0 ? 0.0 : Math.pow(t0, 4) * (g0[0] * x0 + g0[1] * y0)
1751
-
1752
-    const t1 = 0.5 - x1 * x1 - y1 * y1
1753
-    const n1 = t1 < 0 ? 0.0 : Math.pow(t1, 4) * (g1[0] * x1 + g1[1] * y1)
1754
-
1755
-    const t2 = 0.5 - x2 * x2 - y2 * y2
1756
-    const n2 = t2 < 0 ? 0.0 : Math.pow(t2, 4) * (g2[0] * x2 + g2[1] * y2)
1757
-
1758
-    // Add contributions from each corner to get the final noise value.
1759
-    // The result is scaled to return values in the interval [-1, 1]
1760
-    return 70.14805770653952 * (n0 + n1 + n2)
1761
-  }
1724
+  return next
1725
+}
1726
+
1727
+export function ease(t: number) {
1728
+  return t * t * t
1729
+}
1730
+
1731
+export function pointsBetween(a: number[], b: number[], steps = 6) {
1732
+  return Array.from(Array(steps))
1733
+    .map((_, i) => ease(i / steps))
1734
+    .map((t) => [...vec.lrp(a, b, t), (1 - t) / 2])
1735
+}
1736
+
1737
+export function shuffleArr<T>(arr: T[], offset: number): T[] {
1738
+  return arr.map((_, i) => arr[(i + offset) % arr.length])
1762 1739
 }

Notiek ielāde…
Atcelt
Saglabāt