@guinetik/gcanvas 1.0.5 → 2.0.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/dist/aizawa.html +27 -0
- package/dist/clifford.html +25 -0
- package/dist/cmb.html +24 -0
- package/dist/dadras.html +26 -0
- package/dist/dejong.html +25 -0
- package/dist/gcanvas.es.js +5130 -372
- package/dist/gcanvas.es.min.js +1 -1
- package/dist/gcanvas.umd.js +1 -1
- package/dist/gcanvas.umd.min.js +1 -1
- package/dist/halvorsen.html +27 -0
- package/dist/index.html +96 -48
- package/dist/js/aizawa.js +425 -0
- package/dist/js/bezier.js +5 -5
- package/dist/js/clifford.js +236 -0
- package/dist/js/cmb.js +594 -0
- package/dist/js/dadras.js +405 -0
- package/dist/js/dejong.js +257 -0
- package/dist/js/halvorsen.js +405 -0
- package/dist/js/isometric.js +34 -46
- package/dist/js/lorenz.js +425 -0
- package/dist/js/painter.js +8 -8
- package/dist/js/rossler.js +480 -0
- package/dist/js/schrodinger.js +314 -18
- package/dist/js/thomas.js +394 -0
- package/dist/lorenz.html +27 -0
- package/dist/rossler.html +27 -0
- package/dist/scene-interactivity-test.html +220 -0
- package/dist/thomas.html +27 -0
- package/package.json +1 -1
- package/readme.md +30 -22
- package/src/game/objects/go.js +7 -0
- package/src/game/objects/index.js +2 -0
- package/src/game/objects/isometric-scene.js +53 -3
- package/src/game/objects/layoutscene.js +57 -0
- package/src/game/objects/mask.js +241 -0
- package/src/game/objects/scene.js +19 -0
- package/src/game/objects/wrapper.js +14 -2
- package/src/game/pipeline.js +17 -0
- package/src/game/ui/button.js +101 -16
- package/src/game/ui/theme.js +0 -6
- package/src/game/ui/togglebutton.js +25 -14
- package/src/game/ui/tooltip.js +12 -4
- package/src/index.js +3 -0
- package/src/io/gesture.js +409 -0
- package/src/io/index.js +4 -1
- package/src/io/keys.js +9 -1
- package/src/io/screen.js +476 -0
- package/src/math/attractors.js +664 -0
- package/src/math/heat.js +106 -0
- package/src/math/index.js +1 -0
- package/src/mixins/draggable.js +15 -19
- package/src/painter/painter.shapes.js +11 -5
- package/src/particle/particle-system.js +165 -1
- package/src/physics/index.js +26 -0
- package/src/physics/physics-updaters.js +333 -0
- package/src/physics/physics.js +375 -0
- package/src/shapes/image.js +5 -5
- package/src/shapes/index.js +2 -0
- package/src/shapes/parallelogram.js +147 -0
- package/src/shapes/righttriangle.js +115 -0
- package/src/shapes/svg.js +281 -100
- package/src/shapes/text.js +22 -6
- package/src/shapes/transformable.js +5 -0
- package/src/sound/effects.js +807 -0
- package/src/sound/index.js +13 -0
- package/src/webgl/index.js +7 -0
- package/src/webgl/shaders/clifford-point-shaders.js +131 -0
- package/src/webgl/shaders/dejong-point-shaders.js +131 -0
- package/src/webgl/shaders/point-sprite-shaders.js +152 -0
- package/src/webgl/webgl-clifford-renderer.js +477 -0
- package/src/webgl/webgl-dejong-renderer.js +472 -0
- package/src/webgl/webgl-line-renderer.js +391 -0
- package/src/webgl/webgl-particle-renderer.js +410 -0
- package/types/index.d.ts +30 -2
- package/types/io.d.ts +217 -0
- package/types/physics.d.ts +299 -0
- package/types/shapes.d.ts +8 -0
- package/types/webgl.d.ts +188 -109
package/src/shapes/image.js
CHANGED
|
@@ -147,23 +147,23 @@ export class ImageShape extends Shape {
|
|
|
147
147
|
// Skip drawing if not visible or no bitmap available
|
|
148
148
|
if (!this.visible) return;
|
|
149
149
|
if (!this._bitmap && !this._buffer) return;
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
super.draw();
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
// For ImageData, we must use the buffer
|
|
154
154
|
let source = (this._bitmap instanceof ImageData) ? this._buffer : this._bitmap;
|
|
155
|
-
|
|
155
|
+
|
|
156
156
|
if (!source || (this._bitmap instanceof ImageData && !this._buffer)) {
|
|
157
157
|
// If we need a buffer but don't have one yet, try to create it
|
|
158
158
|
if (this._bitmap instanceof ImageData) {
|
|
159
159
|
this.buffer(this._bitmap);
|
|
160
160
|
source = this._buffer;
|
|
161
161
|
}
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
// If we still don't have a valid source, skip drawing
|
|
164
164
|
if (!source) return;
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
// Delegates all transform/alpha/smoothing handling to Painter.img.draw
|
|
168
168
|
Painter.img.draw(source, 0, 0, {
|
|
169
169
|
width: this.width,
|
package/src/shapes/index.js
CHANGED
|
@@ -95,6 +95,8 @@ export { Cylinder } from "./cylinder.js";
|
|
|
95
95
|
export { Diamond } from "./diamond.js";
|
|
96
96
|
export { Line } from "./line.js";
|
|
97
97
|
export { Triangle } from "./triangle.js";
|
|
98
|
+
export { RightTriangle } from "./righttriangle.js";
|
|
99
|
+
export { Parallelogram } from "./parallelogram.js";
|
|
98
100
|
export { Star } from "./star.js";
|
|
99
101
|
export { Sphere } from "./sphere.js";
|
|
100
102
|
export { Sphere3D } from "./sphere3d.js";
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter/painter.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parallelogram
|
|
6
|
+
* -------------
|
|
7
|
+
*
|
|
8
|
+
* A four-sided shape with opposite sides parallel. The shape is defined by
|
|
9
|
+
* its width, height, and slant offset.
|
|
10
|
+
*
|
|
11
|
+
* ### Geometry
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* slant
|
|
15
|
+
* ├───┤
|
|
16
|
+
* ●───────────● ─┬─
|
|
17
|
+
* / / │ height
|
|
18
|
+
* ●───────────● ─┴─
|
|
19
|
+
* ├───────────┤
|
|
20
|
+
* width
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* - `width`: Length of the top and bottom edges
|
|
24
|
+
* - `height`: Perpendicular distance between top and bottom
|
|
25
|
+
* - `slant`: Horizontal offset of top edge relative to bottom (positive = right, negative = left)
|
|
26
|
+
*
|
|
27
|
+
* ### Positioning
|
|
28
|
+
*
|
|
29
|
+
* The shape is centered at its geometric center (centroid).
|
|
30
|
+
*
|
|
31
|
+
* @extends Shape
|
|
32
|
+
*/
|
|
33
|
+
export class Parallelogram extends Shape {
|
|
34
|
+
/**
|
|
35
|
+
* @param {Object} [options={}] - Shape options
|
|
36
|
+
* @param {number} [options.width=100] - Width of the parallel edges
|
|
37
|
+
* @param {number} [options.height=50] - Height (perpendicular distance)
|
|
38
|
+
* @param {number} [options.slant] - Horizontal offset of top edge (defaults to height for 45° slant)
|
|
39
|
+
* @param {boolean} [options.flipX=false] - Mirror horizontally (slant in opposite direction)
|
|
40
|
+
*/
|
|
41
|
+
constructor(options = {}) {
|
|
42
|
+
super(options);
|
|
43
|
+
this._pgWidth = options.width ?? 100;
|
|
44
|
+
this._pgHeight = options.height ?? 50;
|
|
45
|
+
this._slant = options.slant ?? this._pgHeight; // Default 45° slant
|
|
46
|
+
this._flipX = options.flipX ?? false;
|
|
47
|
+
this._updateDimensions();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @type {number} Width of the parallel edges */
|
|
51
|
+
get pgWidth() {
|
|
52
|
+
return this._pgWidth;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
set pgWidth(v) {
|
|
56
|
+
this._pgWidth = v;
|
|
57
|
+
this._updateDimensions();
|
|
58
|
+
this.invalidateCache();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** @type {number} Height (perpendicular distance between edges) */
|
|
62
|
+
get pgHeight() {
|
|
63
|
+
return this._pgHeight;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
set pgHeight(v) {
|
|
67
|
+
this._pgHeight = v;
|
|
68
|
+
this._updateDimensions();
|
|
69
|
+
this.invalidateCache();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** @type {number} Horizontal offset of top edge */
|
|
73
|
+
get slant() {
|
|
74
|
+
return this._slant;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
set slant(v) {
|
|
78
|
+
this._slant = v;
|
|
79
|
+
this._updateDimensions();
|
|
80
|
+
this.invalidateCache();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** @type {boolean} Whether to mirror horizontally */
|
|
84
|
+
get flipX() {
|
|
85
|
+
return this._flipX;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
set flipX(v) {
|
|
89
|
+
this._flipX = v;
|
|
90
|
+
this.invalidateCache();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
_updateDimensions() {
|
|
94
|
+
// Bounding box includes the slant
|
|
95
|
+
this._width = this._pgWidth + Math.abs(this._slant);
|
|
96
|
+
this._height = this._pgHeight;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get the vertices of the parallelogram, centered at origin.
|
|
101
|
+
* @returns {Array<{x: number, y: number}>}
|
|
102
|
+
*/
|
|
103
|
+
getVertices() {
|
|
104
|
+
const w = this._pgWidth;
|
|
105
|
+
const h = this._pgHeight;
|
|
106
|
+
let slant = this._slant;
|
|
107
|
+
|
|
108
|
+
if (this._flipX) {
|
|
109
|
+
slant = -slant;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Calculate total width for centering
|
|
113
|
+
const totalWidth = w + Math.abs(slant);
|
|
114
|
+
const offsetX = -totalWidth / 2 + (slant < 0 ? -slant : 0);
|
|
115
|
+
|
|
116
|
+
// Vertices: bottom-left, bottom-right, top-right, top-left
|
|
117
|
+
// Bottom edge at y = h/2, top edge at y = -h/2
|
|
118
|
+
return [
|
|
119
|
+
{ x: offsetX, y: h / 2 }, // Bottom-left
|
|
120
|
+
{ x: offsetX + w, y: h / 2 }, // Bottom-right
|
|
121
|
+
{ x: offsetX + w + slant, y: -h / 2 }, // Top-right
|
|
122
|
+
{ x: offsetX + slant, y: -h / 2 }, // Top-left
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
draw() {
|
|
127
|
+
super.draw();
|
|
128
|
+
const vertices = this.getVertices();
|
|
129
|
+
|
|
130
|
+
Painter.shapes.polygon(
|
|
131
|
+
vertices,
|
|
132
|
+
this.color,
|
|
133
|
+
this.stroke,
|
|
134
|
+
this.lineWidth,
|
|
135
|
+
this.lineJoin
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
calculateBounds() {
|
|
140
|
+
return {
|
|
141
|
+
x: this.x,
|
|
142
|
+
y: this.y,
|
|
143
|
+
width: this._width,
|
|
144
|
+
height: this._height,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter/painter.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* RightTriangle
|
|
6
|
+
* -------------
|
|
7
|
+
*
|
|
8
|
+
* A right isoceles triangle shape, commonly used in tangram puzzles.
|
|
9
|
+
*
|
|
10
|
+
* The triangle has:
|
|
11
|
+
* - Two equal legs of length `leg`
|
|
12
|
+
* - A right angle (90°) at one corner
|
|
13
|
+
* - Hypotenuse = leg × √2
|
|
14
|
+
*
|
|
15
|
+
* ### Positioning
|
|
16
|
+
*
|
|
17
|
+
* The triangle is centered at its centroid (center of mass).
|
|
18
|
+
* Before rotation, the right angle points toward the bottom-left (-135° from center).
|
|
19
|
+
*
|
|
20
|
+
* ```
|
|
21
|
+
* ●────────● (leg, 0)
|
|
22
|
+
* /|
|
|
23
|
+
* / |
|
|
24
|
+
* / | centroid at (leg/3, leg/3)
|
|
25
|
+
* / |
|
|
26
|
+
* ●────┘ right angle at origin
|
|
27
|
+
* (0, leg)
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* ### Rotation Reference
|
|
31
|
+
*
|
|
32
|
+
* To orient the right angle toward a specific direction:
|
|
33
|
+
* - Right angle pointing RIGHT: rotation = 0°
|
|
34
|
+
* - Right angle pointing DOWN: rotation = 90°
|
|
35
|
+
* - Right angle pointing LEFT: rotation = 180°
|
|
36
|
+
* - Right angle pointing UP: rotation = 270°
|
|
37
|
+
*
|
|
38
|
+
* Add 135° to these values since the default right angle is at -135° from centroid.
|
|
39
|
+
*
|
|
40
|
+
* @extends Shape
|
|
41
|
+
*/
|
|
42
|
+
export class RightTriangle extends Shape {
|
|
43
|
+
/**
|
|
44
|
+
* @param {number} leg - Length of the two equal legs
|
|
45
|
+
* @param {Object} [options={}] - Shape options (x, y, rotation, color, stroke, etc.)
|
|
46
|
+
*/
|
|
47
|
+
constructor(leg = 50, options = {}) {
|
|
48
|
+
super(options);
|
|
49
|
+
this._leg = leg;
|
|
50
|
+
this._updateDimensions();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @type {number} Length of the equal legs */
|
|
54
|
+
get leg() {
|
|
55
|
+
return this._leg;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
set leg(v) {
|
|
59
|
+
this._leg = v;
|
|
60
|
+
this._updateDimensions();
|
|
61
|
+
this.invalidateCache();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** @type {number} Length of the hypotenuse (leg × √2) */
|
|
65
|
+
get hypotenuse() {
|
|
66
|
+
return this._leg * Math.SQRT2;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_updateDimensions() {
|
|
70
|
+
// Bounding box of the centered triangle
|
|
71
|
+
this._width = this._leg;
|
|
72
|
+
this._height = this._leg;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get the vertices of the triangle, centered at origin.
|
|
77
|
+
* Right angle is at the adjusted (0,0) before centering.
|
|
78
|
+
* @returns {Array<{x: number, y: number}>}
|
|
79
|
+
*/
|
|
80
|
+
getVertices() {
|
|
81
|
+
const leg = this._leg;
|
|
82
|
+
// Original vertices: right angle at (0,0), legs along +x and +y
|
|
83
|
+
// Centroid at (leg/3, leg/3)
|
|
84
|
+
const cx = leg / 3;
|
|
85
|
+
const cy = leg / 3;
|
|
86
|
+
|
|
87
|
+
return [
|
|
88
|
+
{ x: -cx, y: -cy }, // Right angle corner
|
|
89
|
+
{ x: leg - cx, y: -cy }, // End of horizontal leg
|
|
90
|
+
{ x: -cx, y: leg - cy }, // End of vertical leg
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
draw() {
|
|
95
|
+
super.draw();
|
|
96
|
+
const vertices = this.getVertices();
|
|
97
|
+
|
|
98
|
+
Painter.shapes.polygon(
|
|
99
|
+
vertices,
|
|
100
|
+
this.color,
|
|
101
|
+
this.stroke,
|
|
102
|
+
this.lineWidth,
|
|
103
|
+
this.lineJoin
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
calculateBounds() {
|
|
108
|
+
return {
|
|
109
|
+
x: this.x,
|
|
110
|
+
y: this.y,
|
|
111
|
+
width: this._width,
|
|
112
|
+
height: this._height,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|