@wodzik/cubecore 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/README.md +118 -0
- package/analyze/client.d.ts +18 -0
- package/analyze/client.js +42 -0
- package/analyze/index.d.ts +114 -0
- package/analyze/index.js +151 -0
- package/analyze/rotations.d.ts +3 -0
- package/analyze/rotations.js +15 -0
- package/analyze/roux.d.ts +67 -0
- package/analyze/roux.js +95 -0
- package/analyze/worker.d.ts +6 -0
- package/analyze/worker.js +31 -0
- package/analyze/zz.d.ts +47 -0
- package/analyze/zz.js +102 -0
- package/bld/index.d.ts +14 -0
- package/bld/index.js +14 -0
- package/bld/memo.d.ts +66 -0
- package/bld/memo.js +139 -0
- package/bld/scheme.d.ts +30 -0
- package/bld/scheme.js +35 -0
- package/bld/skin.d.ts +26 -0
- package/bld/skin.js +46 -0
- package/bld/tracker.d.ts +68 -0
- package/bld/tracker.js +145 -0
- package/bluetooth/clock.d.ts +22 -0
- package/bluetooth/clock.js +37 -0
- package/bluetooth/cubeSkins.d.ts +31 -0
- package/bluetooth/cubeSkins.js +32 -0
- package/bluetooth/gyro.d.ts +31 -0
- package/bluetooth/gyro.js +46 -0
- package/bluetooth/index.d.ts +5 -0
- package/bluetooth/index.js +5 -0
- package/bluetooth/session.d.ts +140 -0
- package/bluetooth/session.js +201 -0
- package/bluetooth/simulated.d.ts +52 -0
- package/bluetooth/simulated.js +80 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-cube-definitions.d.ts +38 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-cube-definitions.js +51 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-cube-encrypter.d.ts +35 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-cube-encrypter.js +70 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-cube-protocol.d.ts +273 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-cube-protocol.js +846 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-gen1.d.ts +38 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-gen1.js +340 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-gen234-packet-validate.d.ts +11 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-gen234-packet-validate.js +118 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-mac-salt.d.ts +2 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-mac-salt.js +15 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-smart-cube.d.ts +18 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-smart-cube.js +152 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-smart-timer.d.ts +74 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-smart-timer.js +161 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-write-queue.d.ts +7 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gan-write-queue.js +11 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gatt-characteristic-write.d.ts +2 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/gatt-characteristic-write.js +36 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/index.d.ts +4 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/index.js +4 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/address-hints.d.ts +12 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/address-hints.js +122 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/build-picker-options.d.ts +11 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/build-picker-options.js +55 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/default-optional-services.d.ts +21 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/default-optional-services.js +47 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/device-name-scan-filters.d.ts +6 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/device-name-scan-filters.js +24 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/gatt-snapshot.d.ts +6 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/gatt-snapshot.js +57 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/mac-candidates.d.ts +11 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/mac-candidates.js +67 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/mac-probe-moyu32.d.ts +8 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/mac-probe-moyu32.js +98 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/mac-probe-qiyi.d.ts +8 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/mac-probe-qiyi.js +128 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/moyu32-session-crypto.d.ts +5 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/moyu32-session-crypto.js +60 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/normalize-uuid.d.ts +2 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/normalize-uuid.js +8 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/packet-sanity.d.ts +7 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/packet-sanity.js +142 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/profile-rank.d.ts +6 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/profile-rank.js +21 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/types.d.ts +32 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/attachment/types.js +1 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/ble-utils.d.ts +6 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/ble-utils.js +68 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/connect.d.ts +3 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/connect.js +178 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/cubie-cube.d.ts +16 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/cubie-cube.js +141 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/index.d.ts +11 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/index.js +10 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocol.d.ts +26 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocol.js +8 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/gan.d.ts +3 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/gan.js +265 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/giiker.d.ts +3 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/giiker.js +345 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/gocube.d.ts +15 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/gocube.js +382 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/moyu-mhc.d.ts +3 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/moyu-mhc.js +352 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/moyu-v1.d.ts +57 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/moyu-v1.js +243 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/moyu32.d.ts +3 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/moyu32.js +454 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/qiyi.d.ts +3 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/protocols/qiyi.js +424 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/types.d.ts +78 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/smartcube/types.js +1 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/utils.d.ts +45 -0
- package/bluetooth/vendor/smartcube-web-bluetooth/utils.js +150 -0
- package/cfop/caseData.d.ts +16 -0
- package/cfop/caseData.js +88 -0
- package/cfop/cases.d.ts +42 -0
- package/cfop/cases.js +116 -0
- package/cfop/f2l.d.ts +28 -0
- package/cfop/f2l.js +88 -0
- package/cfop/f2lData.d.ts +15 -0
- package/cfop/f2lData.js +49 -0
- package/cfop/index.d.ts +41 -0
- package/cfop/index.js +110 -0
- package/cfop/slots.d.ts +2 -0
- package/cfop/slots.js +1 -0
- package/core/arrows.d.ts +24 -0
- package/core/arrows.js +22 -0
- package/core/bytes.d.ts +27 -0
- package/core/bytes.js +145 -0
- package/core/centers.d.ts +32 -0
- package/core/centers.js +83 -0
- package/core/checks.d.ts +53 -0
- package/core/checks.js +85 -0
- package/core/cubies.d.ts +45 -0
- package/core/cubies.js +169 -0
- package/core/frames.d.ts +61 -0
- package/core/frames.js +126 -0
- package/core/geometry.d.ts +58 -0
- package/core/geometry.js +132 -0
- package/core/index.d.ts +19 -0
- package/core/index.js +19 -0
- package/core/masks.d.ts +32 -0
- package/core/masks.js +39 -0
- package/core/method.d.ts +35 -0
- package/core/method.js +30 -0
- package/core/moves.d.ts +48 -0
- package/core/moves.js +88 -0
- package/core/notation.d.ts +48 -0
- package/core/notation.js +226 -0
- package/core/physical.d.ts +53 -0
- package/core/physical.js +99 -0
- package/core/practice.d.ts +62 -0
- package/core/practice.js +87 -0
- package/core/sequence.d.ts +90 -0
- package/core/sequence.js +157 -0
- package/core/stages.d.ts +90 -0
- package/core/stages.js +21 -0
- package/core/state.d.ts +55 -0
- package/core/state.js +140 -0
- package/core/stateCodec.d.ts +12 -0
- package/core/stateCodec.js +51 -0
- package/core/stream.d.ts +45 -0
- package/core/stream.js +75 -0
- package/core/tracker.d.ts +62 -0
- package/core/tracker.js +121 -0
- package/element/alg.d.ts +45 -0
- package/element/alg.js +150 -0
- package/element/base.d.ts +2 -0
- package/element/base.js +3 -0
- package/element/bld.d.ts +82 -0
- package/element/bld.js +222 -0
- package/element/index.d.ts +8 -0
- package/element/index.js +21 -0
- package/element/model.d.ts +36 -0
- package/element/model.js +64 -0
- package/element/player.d.ts +196 -0
- package/element/player.js +680 -0
- package/element/practice.d.ts +75 -0
- package/element/practice.js +150 -0
- package/element/scramble.d.ts +50 -0
- package/element/scramble.js +107 -0
- package/element/sequence.d.ts +126 -0
- package/element/sequence.js +254 -0
- package/element/styles.d.ts +32 -0
- package/element/styles.js +196 -0
- package/image/cache.d.ts +21 -0
- package/image/cache.js +66 -0
- package/image/index.d.ts +2 -0
- package/image/index.js +2 -0
- package/image/png-node.d.ts +6 -0
- package/image/png-node.js +10 -0
- package/image/svg.d.ts +36 -0
- package/image/svg.js +215 -0
- package/lbl/index.d.ts +10 -0
- package/lbl/index.js +31 -0
- package/methods/index.d.ts +20 -0
- package/methods/index.js +33 -0
- package/package.json +133 -0
- package/petrus/index.d.ts +11 -0
- package/petrus/index.js +27 -0
- package/react/index.d.ts +176 -0
- package/react/index.js +228 -0
- package/render/arrows.d.ts +68 -0
- package/render/arrows.js +190 -0
- package/render/build/attachments.d.ts +35 -0
- package/render/build/attachments.js +94 -0
- package/render/build/models.d.ts +9 -0
- package/render/build/models.js +27 -0
- package/render/build/tiles.d.ts +48 -0
- package/render/build/tiles.js +194 -0
- package/render/gltf.d.ts +10 -0
- package/render/gltf.js +106 -0
- package/render/index.d.ts +12 -0
- package/render/index.js +12 -0
- package/render/layers.d.ts +21 -0
- package/render/layers.js +24 -0
- package/render/pictures.d.ts +46 -0
- package/render/pictures.js +80 -0
- package/render/pieceModels.d.ts +38 -0
- package/render/pieceModels.js +43 -0
- package/render/renderer.d.ts +165 -0
- package/render/renderer.js +647 -0
- package/render/tile.d.ts +114 -0
- package/render/tile.js +390 -0
- package/render/viewports.d.ts +25 -0
- package/render/viewports.js +26 -0
- package/roux/cmll.d.ts +35 -0
- package/roux/cmll.js +121 -0
- package/roux/cmllData.d.ts +12 -0
- package/roux/cmllData.js +49 -0
- package/roux/index.d.ts +52 -0
- package/roux/index.js +175 -0
- package/skin/attachments.d.ts +82 -0
- package/skin/attachments.js +110 -0
- package/skin/index.d.ts +3 -0
- package/skin/index.js +3 -0
- package/skin/shapes.d.ts +112 -0
- package/skin/shapes.js +147 -0
- package/skin/skin.d.ts +911 -0
- package/skin/skin.js +412 -0
- package/solve/client.d.ts +58 -0
- package/solve/client.js +56 -0
- package/solve/handle.d.ts +6 -0
- package/solve/handle.js +38 -0
- package/solve/index.d.ts +8 -0
- package/solve/index.js +7 -0
- package/solve/lse.d.ts +42 -0
- package/solve/lse.js +151 -0
- package/solve/pieces.d.ts +18 -0
- package/solve/pieces.js +24 -0
- package/solve/protocol.d.ts +70 -0
- package/solve/protocol.js +16 -0
- package/solve/scramble.d.ts +76 -0
- package/solve/scramble.js +187 -0
- package/solve/stage.d.ts +108 -0
- package/solve/stage.js +532 -0
- package/solve/twophase.d.ts +36 -0
- package/solve/twophase.js +229 -0
- package/solve/worker.d.ts +6 -0
- package/solve/worker.js +15 -0
- package/timeline/codec.d.ts +23 -0
- package/timeline/codec.js +84 -0
- package/timeline/index.d.ts +7 -0
- package/timeline/index.js +7 -0
- package/timeline/recording.d.ts +19 -0
- package/timeline/recording.js +20 -0
- package/timeline/replay.d.ts +68 -0
- package/timeline/replay.js +145 -0
- package/timeline/segments.d.ts +31 -0
- package/timeline/segments.js +39 -0
- package/timeline/share.d.ts +30 -0
- package/timeline/share.js +62 -0
- package/timeline/stats.d.ts +34 -0
- package/timeline/stats.js +56 -0
- package/timeline/timings.d.ts +30 -0
- package/timeline/timings.js +54 -0
- package/zz/index.d.ts +29 -0
- package/zz/index.js +68 -0
- package/zz/seeds.d.ts +9 -0
- package/zz/seeds.js +29 -0
package/skin/shapes.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sticker shapes — pure geometry, no three.js.
|
|
3
|
+
*
|
|
4
|
+
* Real cubes (e.g. GAN stickerless tiles) shape a tile by what piece it is on
|
|
5
|
+
* and which way the face centre is: a corner tile rounds off the corner that
|
|
6
|
+
* points at the centre, an edge tile rounds its inner side into a "tongue",
|
|
7
|
+
* the centre tile is nearly round. `StickerShape` describes that with four
|
|
8
|
+
* corner radii per piece kind; custom SVG paths can replace any kind.
|
|
9
|
+
*
|
|
10
|
+
* Local sticker frame: x = tangent `a`, y = tangent `b`, z = outward normal
|
|
11
|
+
* (a × b = n). Coordinates of a sticker's corners are (±1, ±1)·half-size.
|
|
12
|
+
*/
|
|
13
|
+
import { FACE_BASIS } from "../core/index.js";
|
|
14
|
+
export type PieceKind = "corner" | "edge" | "center";
|
|
15
|
+
export interface CornerRadii {
|
|
16
|
+
/** Radius of the corner(s) facing the face centre, as a fraction of the tile side (0..0.5). */
|
|
17
|
+
inner: number;
|
|
18
|
+
/** Radius of the other corners. */
|
|
19
|
+
outer: number;
|
|
20
|
+
}
|
|
21
|
+
export interface StickerShape {
|
|
22
|
+
corner: CornerRadii;
|
|
23
|
+
edge: CornerRadii;
|
|
24
|
+
/** Centre tiles: one radius for all four corners. */
|
|
25
|
+
center: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Custom tile outlines as SVG path data in a 0..1 box (y down, like SVG).
|
|
29
|
+
* Convention: the face centre lies towards the BOTTOM-RIGHT for corner tiles
|
|
30
|
+
* and towards the BOTTOM for edge tiles; centre tiles are drawn as-is.
|
|
31
|
+
* The renderer rotates each path into place.
|
|
32
|
+
*/
|
|
33
|
+
export type StickerPaths = Partial<Record<PieceKind, string>>;
|
|
34
|
+
export { FACE_BASIS };
|
|
35
|
+
export interface StickerLayout {
|
|
36
|
+
kind: PieceKind;
|
|
37
|
+
/** Position of the tile on its face: (u, v) ∈ {-1, 0, 1}², in the face's (a, b) axes. */
|
|
38
|
+
u: number;
|
|
39
|
+
v: number;
|
|
40
|
+
/**
|
|
41
|
+
* Radii of the corners in local order: (+x,+y), (−x,+y), (−x,−y), (+x,−y)
|
|
42
|
+
* — i.e. counter-clockwise from top-right.
|
|
43
|
+
*/
|
|
44
|
+
radii: [number, number, number, number];
|
|
45
|
+
/** Quarter turns (CCW) that bring the path convention's "centre direction" onto this tile's. */
|
|
46
|
+
pathQuarters: number;
|
|
47
|
+
}
|
|
48
|
+
export declare function stickerLayout(faceletIndex: number, shape: StickerShape): StickerLayout;
|
|
49
|
+
/** Outline of a tile of side `side` with per-corner radii (fractions of `side`), as points CCW. */
|
|
50
|
+
export declare function roundedOutline(side: number, radii: readonly number[], segments?: number): [number, number][];
|
|
51
|
+
export interface TileExtents {
|
|
52
|
+
xMin: number;
|
|
53
|
+
xMax: number;
|
|
54
|
+
yMin: number;
|
|
55
|
+
yMax: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Which sides of a tile lie on the cube's outer edge (in local x/y): e.g. the
|
|
59
|
+
* top-left corner tile of a face has its −x and +y sides on the edge.
|
|
60
|
+
*/
|
|
61
|
+
export declare function outerSides(layout: StickerLayout): {
|
|
62
|
+
xMin: boolean;
|
|
63
|
+
xMax: boolean;
|
|
64
|
+
yMin: boolean;
|
|
65
|
+
yMax: boolean;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* A custom (path) outline made stickerless: the half of the tile towards
|
|
69
|
+
* each outer side is stretched so that side reaches `edge` (from `half`), the
|
|
70
|
+
* inner sides stay put. The path should run straight along its outer sides
|
|
71
|
+
* and be square where two of them meet (the cube corner — the edge round
|
|
72
|
+
* shapes it there).
|
|
73
|
+
*/
|
|
74
|
+
export declare function reachEdge(outline: readonly [number, number][], layout: StickerLayout, half: number, edge: number): [number, number][];
|
|
75
|
+
/**
|
|
76
|
+
* Stickerless tiles: sides on the cube's outer edge run all the way to
|
|
77
|
+
* `edge` (the cubie face half-size plus a little overlap), so two faces'
|
|
78
|
+
* colours meet directly on the cube's edges and corners with no black line
|
|
79
|
+
* between them; the other sides keep the gap at `half`. A tile corner where
|
|
80
|
+
* two outer sides meet (a cube corner) is sharp.
|
|
81
|
+
*/
|
|
82
|
+
export declare function stickerlessOutline(layout: StickerLayout, side: number, edge: number, segments?: number): [number, number][];
|
|
83
|
+
/** Rectangle with independent extents and absolute per-corner radii, CCW from the (+x,+y) corner. */
|
|
84
|
+
export declare function roundedRect(ext: TileExtents, radii: readonly number[], segments?: number): [number, number][];
|
|
85
|
+
/** A sticker laid on a (black) tile — see `Skin.stickers.overlay`. */
|
|
86
|
+
export interface StickerOverlay {
|
|
87
|
+
/** Side of the sticker (fraction of a cubie face) — its inner sides. */
|
|
88
|
+
size: number;
|
|
89
|
+
centerSize?: number;
|
|
90
|
+
/** How far the sticker keeps from the cube's outer edges (cubie units) — room for the rounded cube edge. */
|
|
91
|
+
margin: number;
|
|
92
|
+
/** Corner radii as in `StickerShape` (fractions of the sticker side). */
|
|
93
|
+
shape: StickerShape;
|
|
94
|
+
/** Radius where a corner sticker meets the cube's corner (cubie units). Default: its outer radius. */
|
|
95
|
+
cornerRadius?: number;
|
|
96
|
+
/** How far the sticker stands on the tile (cubie units). */
|
|
97
|
+
thickness: number;
|
|
98
|
+
/** Rounding of the sticker's edge (≤ thickness). Default: a hair. */
|
|
99
|
+
bevel?: number;
|
|
100
|
+
/**
|
|
101
|
+
* A black pedestal with a flat print on top: the raised part is the body's
|
|
102
|
+
* plastic, only its top (inside the bevel) takes the colour.
|
|
103
|
+
*/
|
|
104
|
+
pedestal?: boolean;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A sticker's outline on its tile: the inner sides at the sticker's size,
|
|
108
|
+
* the sides on the cube's outer edge `margin` short of it (the black rounded
|
|
109
|
+
* edge shows round it), per-corner radii from the shape; a corner sticker's
|
|
110
|
+
* corner at the cube's corner takes `cornerRadius`.
|
|
111
|
+
*/
|
|
112
|
+
export declare function overlayOutline(faceletIndex: number, overlay: StickerOverlay, segments?: number, inset?: number): [number, number][];
|
package/skin/shapes.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sticker shapes — pure geometry, no three.js.
|
|
3
|
+
*
|
|
4
|
+
* Real cubes (e.g. GAN stickerless tiles) shape a tile by what piece it is on
|
|
5
|
+
* and which way the face centre is: a corner tile rounds off the corner that
|
|
6
|
+
* points at the centre, an edge tile rounds its inner side into a "tongue",
|
|
7
|
+
* the centre tile is nearly round. `StickerShape` describes that with four
|
|
8
|
+
* corner radii per piece kind; custom SVG paths can replace any kind.
|
|
9
|
+
*
|
|
10
|
+
* Local sticker frame: x = tangent `a`, y = tangent `b`, z = outward normal
|
|
11
|
+
* (a × b = n). Coordinates of a sticker's corners are (±1, ±1)·half-size.
|
|
12
|
+
*/
|
|
13
|
+
import { FACELETS, FACE_BASIS } from "../core/index.js";
|
|
14
|
+
export { FACE_BASIS };
|
|
15
|
+
const dot = (p, q) => p[0] * q[0] + p[1] * q[1] + p[2] * q[2];
|
|
16
|
+
const LOCAL_CORNERS = [[1, 1], [-1, 1], [-1, -1], [1, -1]];
|
|
17
|
+
export function stickerLayout(faceletIndex, shape) {
|
|
18
|
+
const f = FACELETS[faceletIndex];
|
|
19
|
+
const { a, b } = FACE_BASIS[f.face];
|
|
20
|
+
const u = dot(f.pos, a), v = dot(f.pos, b);
|
|
21
|
+
const kind = u === 0 && v === 0 ? "center" : u !== 0 && v !== 0 ? "corner" : "edge";
|
|
22
|
+
let radii;
|
|
23
|
+
if (kind === "center")
|
|
24
|
+
radii = [shape.center, shape.center, shape.center, shape.center];
|
|
25
|
+
else {
|
|
26
|
+
const r = kind === "corner" ? shape.corner : shape.edge;
|
|
27
|
+
// A corner of the tile faces the centre when it points the opposite way to the tile's offset.
|
|
28
|
+
radii = LOCAL_CORNERS.map(([sx, sy]) => {
|
|
29
|
+
const inner = kind === "corner" ? sx === -Math.sign(u) && sy === -Math.sign(v) : u !== 0 ? sx === -Math.sign(u) : sy === -Math.sign(v);
|
|
30
|
+
return inner ? r.inner : r.outer;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// Path convention (SVG, y down): centre towards bottom-right (corner) / bottom (edge). In local
|
|
34
|
+
// coords (y up) that is direction (+1, −1) / (0, −1). Rotate it onto (−u, −v).
|
|
35
|
+
const target = [-Math.sign(u), -Math.sign(v)];
|
|
36
|
+
const from = kind === "corner" ? [1, -1] : [0, -1];
|
|
37
|
+
let q = 0;
|
|
38
|
+
let d = from;
|
|
39
|
+
while (q < 4 && (d[0] !== target[0] || d[1] !== target[1])) {
|
|
40
|
+
d = [-d[1], d[0]];
|
|
41
|
+
q++;
|
|
42
|
+
}
|
|
43
|
+
return { kind, u, v, radii, pathQuarters: kind === "center" ? 0 : q % 4 };
|
|
44
|
+
}
|
|
45
|
+
/** Outline of a tile of side `side` with per-corner radii (fractions of `side`), as points CCW. */
|
|
46
|
+
export function roundedOutline(side, radii, segments = 8) {
|
|
47
|
+
const h = side / 2;
|
|
48
|
+
const pts = [];
|
|
49
|
+
LOCAL_CORNERS.forEach(([sx, sy], i) => {
|
|
50
|
+
const r = Math.min(radii[i] * side, h);
|
|
51
|
+
const cx = sx * (h - r), cy = sy * (h - r);
|
|
52
|
+
// Arc from the corner's first edge to the second, going CCW.
|
|
53
|
+
const start = Math.atan2(sy, sx) - Math.PI / 4;
|
|
54
|
+
for (let k = 0; k <= segments; k++) {
|
|
55
|
+
const t = start + (k / segments) * (Math.PI / 2);
|
|
56
|
+
pts.push([cx + r * Math.cos(t), cy + r * Math.sin(t)]);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return pts;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Which sides of a tile lie on the cube's outer edge (in local x/y): e.g. the
|
|
63
|
+
* top-left corner tile of a face has its −x and +y sides on the edge.
|
|
64
|
+
*/
|
|
65
|
+
export function outerSides(layout) {
|
|
66
|
+
return { xMin: layout.u === -1, xMax: layout.u === 1, yMin: layout.v === -1, yMax: layout.v === 1 };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A custom (path) outline made stickerless: the half of the tile towards
|
|
70
|
+
* each outer side is stretched so that side reaches `edge` (from `half`), the
|
|
71
|
+
* inner sides stay put. The path should run straight along its outer sides
|
|
72
|
+
* and be square where two of them meet (the cube corner — the edge round
|
|
73
|
+
* shapes it there).
|
|
74
|
+
*/
|
|
75
|
+
export function reachEdge(outline, layout, half, edge) {
|
|
76
|
+
const o = outerSides(layout);
|
|
77
|
+
const k = edge / half;
|
|
78
|
+
return outline.map(([x, y]) => [(x < 0 && o.xMin) || (x > 0 && o.xMax) ? x * k : x, (y < 0 && o.yMin) || (y > 0 && o.yMax) ? y * k : y]);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Stickerless tiles: sides on the cube's outer edge run all the way to
|
|
82
|
+
* `edge` (the cubie face half-size plus a little overlap), so two faces'
|
|
83
|
+
* colours meet directly on the cube's edges and corners with no black line
|
|
84
|
+
* between them; the other sides keep the gap at `half`. A tile corner where
|
|
85
|
+
* two outer sides meet (a cube corner) is sharp.
|
|
86
|
+
*/
|
|
87
|
+
export function stickerlessOutline(layout, side, edge, segments = 8) {
|
|
88
|
+
const half = side / 2;
|
|
89
|
+
const o = outerSides(layout);
|
|
90
|
+
const ext = { xMin: o.xMin ? -edge : -half, xMax: o.xMax ? edge : half, yMin: o.yMin ? -edge : -half, yMax: o.yMax ? edge : half };
|
|
91
|
+
// Local corners in order (+,+), (−,+), (−,−), (+,−).
|
|
92
|
+
const cornerOuter = [
|
|
93
|
+
[o.xMax, o.yMax],
|
|
94
|
+
[o.xMin, o.yMax],
|
|
95
|
+
[o.xMin, o.yMin],
|
|
96
|
+
[o.xMax, o.yMin],
|
|
97
|
+
];
|
|
98
|
+
const radii = layout.radii.map((r, i) => (cornerOuter[i][0] && cornerOuter[i][1] ? 0 : r * side));
|
|
99
|
+
return roundedRect(ext, radii, segments);
|
|
100
|
+
}
|
|
101
|
+
/** Rectangle with independent extents and absolute per-corner radii, CCW from the (+x,+y) corner. */
|
|
102
|
+
export function roundedRect(ext, radii, segments = 8) {
|
|
103
|
+
const corners = [
|
|
104
|
+
[ext.xMax, ext.yMax, 1, 1],
|
|
105
|
+
[ext.xMin, ext.yMax, -1, 1],
|
|
106
|
+
[ext.xMin, ext.yMin, -1, -1],
|
|
107
|
+
[ext.xMax, ext.yMin, 1, -1],
|
|
108
|
+
];
|
|
109
|
+
const w = ext.xMax - ext.xMin, h = ext.yMax - ext.yMin;
|
|
110
|
+
const pts = [];
|
|
111
|
+
corners.forEach(([x, y, sx, sy], i) => {
|
|
112
|
+
const r = Math.min(radii[i], w / 2, h / 2);
|
|
113
|
+
const cx = x - sx * r, cy = y - sy * r;
|
|
114
|
+
const start = Math.atan2(sy, sx) - Math.PI / 4;
|
|
115
|
+
if (r === 0) {
|
|
116
|
+
pts.push([x, y]);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (let k = 0; k <= segments; k++) {
|
|
120
|
+
const t = start + (k / segments) * (Math.PI / 2);
|
|
121
|
+
pts.push([cx + r * Math.cos(t), cy + r * Math.sin(t)]);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return pts;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* A sticker's outline on its tile: the inner sides at the sticker's size,
|
|
128
|
+
* the sides on the cube's outer edge `margin` short of it (the black rounded
|
|
129
|
+
* edge shows round it), per-corner radii from the shape; a corner sticker's
|
|
130
|
+
* corner at the cube's corner takes `cornerRadius`.
|
|
131
|
+
*/
|
|
132
|
+
export function overlayOutline(faceletIndex, overlay, segments = 8, inset = 0) {
|
|
133
|
+
const layout = stickerLayout(faceletIndex, overlay.shape);
|
|
134
|
+
const half = (layout.kind === "center" ? (overlay.centerSize ?? overlay.size) : overlay.size) / 2 - inset;
|
|
135
|
+
const out = 0.5 - overlay.margin - inset;
|
|
136
|
+
const o = outerSides(layout);
|
|
137
|
+
const ext = { xMin: o.xMin ? -out : -half, xMax: o.xMax ? out : half, yMin: o.yMin ? -out : -half, yMax: o.yMax ? out : half };
|
|
138
|
+
const side = 2 * half;
|
|
139
|
+
const both = [
|
|
140
|
+
[o.xMax, o.yMax],
|
|
141
|
+
[o.xMin, o.yMax],
|
|
142
|
+
[o.xMin, o.yMin],
|
|
143
|
+
[o.xMax, o.yMin],
|
|
144
|
+
];
|
|
145
|
+
const radii = layout.radii.map((r, i) => Math.max(0, (both[i][0] && both[i][1] && overlay.cornerRadius !== undefined ? overlay.cornerRadius : r * (side + 2 * inset)) - inset));
|
|
146
|
+
return roundedRect(ext, radii, segments);
|
|
147
|
+
}
|