@pixel-normal-edit/mcp 2.1.0 → 2.2.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/clear-firebase.js +37 -0
- package/domains/art-tree/README.md +134 -0
- package/domains/art-tree/REORGANIZATION_PLAN.md +168 -0
- package/domains/art-tree/REORGANIZATION_SUMMARY.md +260 -0
- package/domains/art-tree/index.js +58 -58
- package/domains/art-tree/lessons/3d/box-properties.js +38 -0
- package/domains/art-tree/lessons/3d/cone-properties.js +31 -0
- package/domains/art-tree/lessons/3d/cylinder-properties.js +29 -0
- package/domains/art-tree/lessons/3d/sphere-properties.js +25 -0
- package/domains/art-tree/lessons/advanced/angles.js +30 -0
- package/domains/art-tree/lessons/advanced/distances.js +26 -0
- package/domains/art-tree/lessons/advanced/shape-ratios.js +25 -0
- package/domains/art-tree/lessons/advanced/shape-relationships.js +28 -0
- package/domains/art-tree/lessons/advanced/symmetry-and-axis.js +26 -0
- package/domains/art-tree/{analysis_lessons.js → lessons/analysis/object-analysis.js} +5 -16
- package/domains/art-tree/lessons/basic/circles.js +26 -0
- package/domains/art-tree/lessons/basic/composition.js +34 -0
- package/domains/art-tree/lessons/basic/curves.js +31 -0
- package/domains/art-tree/lessons/basic/ellipses.js +26 -0
- package/domains/art-tree/lessons/basic/freehand.js +19 -0
- package/domains/art-tree/lessons/basic/index.js +36 -0
- package/domains/art-tree/lessons/basic/lines.js +38 -0
- package/domains/art-tree/lessons/basic/parallel-and-intersecting.js +22 -0
- package/domains/art-tree/lessons/basic/polygons.js +25 -0
- package/domains/art-tree/lessons/basic/proportions-and-angles.js +20 -0
- package/domains/art-tree/lessons/basic/spiral.js +21 -0
- package/domains/art-tree/lessons/basic/squares.js +28 -0
- package/domains/art-tree/lessons/basic/strokes.js +23 -0
- package/domains/art-tree/lessons/basic/triangles.js +30 -0
- package/domains/art-tree/lessons/cross-sections/bottle-sections.js +26 -0
- package/domains/art-tree/lessons/cross-sections/glass-sections.js +24 -0
- package/domains/art-tree/lessons/cross-sections/head-sections.js +17 -0
- package/domains/art-tree/lessons/curves/curve-properties.js +50 -0
- package/domains/art-tree/lessons/curves/curve-topology.js +45 -0
- package/domains/art-tree/lessons/curves/curve-types.js +44 -0
- package/domains/art-tree/lessons/ellipses/coaxial-ellipses.js +29 -0
- package/domains/art-tree/lessons/ellipses/ellipse-anatomy.js +26 -0
- package/domains/art-tree/lessons/ellipses/ellipse-orientations.js +28 -0
- package/domains/art-tree/lessons/ellipses/ellipse-proportions.js +27 -0
- package/domains/art-tree/lessons/hidden/hidden-box.js +20 -0
- package/domains/art-tree/lessons/hidden/hidden-cup.js +19 -0
- package/domains/art-tree/lessons/hidden/hidden-head.js +18 -0
- package/domains/art-tree/lessons/index.js +42 -0
- package/domains/art-tree/{layer_lessons.js → lessons/layers/layer-step.js} +5 -16
- package/domains/art-tree/lessons/lighting/contact-shadow.js +33 -0
- package/domains/art-tree/lessons/lighting/light-direction.js +30 -0
- package/domains/art-tree/lessons/lighting/light-zones.js +30 -0
- package/domains/art-tree/lessons/materials/material-glass.js +21 -0
- package/domains/art-tree/lessons/materials/material-shiny.js +26 -0
- package/domains/art-tree/lessons/materials/material-texture.js +26 -0
- package/domains/art-tree/lessons/perspective/1point-perspective.js +30 -0
- package/domains/art-tree/lessons/perspective/2point-perspective.js +30 -0
- package/domains/art-tree/lessons/perspective/3point-perspective.js +45 -0
- package/domains/art-tree/lessons/perspective/foreshortening.js +38 -0
- package/domains/art-tree/lessons/sky/sun-shapes.js +25 -0
- package/domains/art-tree/lessons/sky/sunset-colors.js +27 -0
- package/domains/art-tree/lessons/sky/sunset-sky.js +32 -0
- package/domains/art-tree/{structure_lessons.js → lessons/structure/axis-orientation.js} +3 -53
- package/domains/art-tree/lessons/structure/complex-structure.js +21 -0
- package/domains/art-tree/lessons/structure/x-yzaxes.js +28 -0
- package/domains/art-tree/lessons/surfaces/chair-analysis.js +17 -0
- package/domains/art-tree/lessons/surfaces/cup-analysis.js +18 -0
- package/domains/art-tree/lessons/surfaces/edge-types.js +40 -0
- package/domains/art-tree/lessons/surfaces/surface-types.js +42 -0
- package/domains/art-tree/lessons/transforms/bend.js +27 -0
- package/domains/art-tree/{transform_lessons_2.js → lessons/transforms/combine.js} +3 -54
- package/domains/art-tree/lessons/transforms/cut.js +25 -0
- package/domains/art-tree/lessons/transforms/hollow.js +24 -0
- package/domains/art-tree/lessons/transforms/rotate.js +16 -0
- package/domains/art-tree/lessons/transforms/squash.js +31 -0
- package/domains/art-tree/lessons/transforms/stretch.js +31 -0
- package/domains/art-tree/lessons/transforms/taper-swell.js +33 -0
- package/domains/art-tree/{vocab_lessons.js → lessons/vocab/vocab-house.js} +5 -16
- package/domains/art-tree/lib/tool-register.js +104 -0
- package/domains/art-tree/lib/validators.js +78 -0
- package/domains/art-tree/shapes/grid.js +37 -0
- package/domains/art-tree/shapes/polyline.js +26 -0
- package/domains/art-tree/{3d_tools.js → tools/3d.js} +2 -2
- package/domains/art-tree/{advanced_tools.js → tools/advanced.js} +2 -2
- package/domains/art-tree/{analysis_tools.js → tools/analysis.js} +2 -2
- package/domains/art-tree/{tools.js → tools/basic.js} +3 -3
- package/domains/art-tree/{cross_section_tools.js → tools/cross-sections.js} +2 -2
- package/domains/art-tree/{curve_tools.js → tools/curves.js} +2 -2
- package/domains/art-tree/{ellipse_tools.js → tools/ellipses.js} +2 -2
- package/domains/art-tree/{hidden_tools.js → tools/hidden.js} +2 -2
- package/domains/art-tree/tools/index.js +53 -0
- package/domains/art-tree/{layer_tools.js → tools/layers.js} +2 -2
- package/domains/art-tree/{light_tools.js → tools/lighting.js} +2 -2
- package/domains/art-tree/{material_tools.js → tools/materials.js} +2 -2
- package/domains/art-tree/{perspective_tools.js → tools/perspective.js} +2 -2
- package/domains/art-tree/{sky_tools.js → tools/sky.js} +2 -2
- package/domains/art-tree/{structure_tools.js → tools/structure.js} +2 -2
- package/domains/art-tree/{surface_tools.js → tools/surfaces.js} +2 -2
- package/domains/art-tree/{transform_tools.js → tools/transforms.js} +3 -3
- package/domains/art-tree/{vocab_tools.js → tools/vocab.js} +2 -2
- package/package.json +1 -1
- package/rules/prerequisites.js +30 -30
- package/rules/rules.js +1 -1
- package/rules/workflow.js +28 -20
- package/tools/canvas-tools.js +2 -2
- package/tools/drawing-tools.js +23 -12
- package/tools/workspace-tools.js +5 -4
- package/domains/art-tree/3d_lessons.js +0 -114
- package/domains/art-tree/advanced_lessons.js +0 -124
- package/domains/art-tree/cross_section_lessons.js +0 -65
- package/domains/art-tree/curve_lessons.js +0 -138
- package/domains/art-tree/ellipse_lessons.js +0 -105
- package/domains/art-tree/hidden_lessons.js +0 -55
- package/domains/art-tree/lessons.js +0 -305
- package/domains/art-tree/light_lessons.js +0 -92
- package/domains/art-tree/material_lessons.js +0 -71
- package/domains/art-tree/perspective_lessons.js +0 -138
- package/domains/art-tree/sky_lessons_1.js +0 -82
- package/domains/art-tree/surface_lessons.js +0 -112
- package/domains/art-tree/transform_lessons_1.js +0 -108
- /package/domains/art-tree/{3d_shapes.js → shapes/3d.js} +0 -0
- /package/domains/art-tree/{advanced_shapes.js → shapes/advanced.js} +0 -0
- /package/domains/art-tree/{analysis_shapes.js → shapes/analysis.js} +0 -0
- /package/domains/art-tree/{shapes.js → shapes/basic.js} +0 -0
- /package/domains/art-tree/{cross_section_shapes.js → shapes/cross-sections.js} +0 -0
- /package/domains/art-tree/{curve_shapes.js → shapes/curves.js} +0 -0
- /package/domains/art-tree/{ellipse_shapes.js → shapes/ellipses.js} +0 -0
- /package/domains/art-tree/{hidden_shapes.js → shapes/hidden.js} +0 -0
- /package/domains/art-tree/{layer_shapes.js → shapes/layers.js} +0 -0
- /package/domains/art-tree/{light_shapes.js → shapes/lighting.js} +0 -0
- /package/domains/art-tree/{material_shapes.js → shapes/materials.js} +0 -0
- /package/domains/art-tree/{perspective_shapes.js → shapes/perspective.js} +0 -0
- /package/domains/art-tree/{sky_shapes_1.js → shapes/sky.js} +0 -0
- /package/domains/art-tree/{structure_shapes.js → shapes/structure.js} +0 -0
- /package/domains/art-tree/{surface_shapes.js → shapes/surfaces.js} +0 -0
- /package/domains/art-tree/{transform_shapes.js → shapes/transforms.js} +0 -0
- /package/domains/art-tree/{vocab_shapes.js → shapes/vocab.js} +0 -0
|
@@ -1,53 +1,7 @@
|
|
|
1
|
-
const shapes = require('./shapes');
|
|
2
|
-
const transformShapes = require('./transform_shapes');
|
|
3
|
-
const structureLessons = require('./structure_lessons');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Lesson: Rotate (Rotation)
|
|
7
|
-
* Analyzing how objects change when rotated around X, Y, Z axes.
|
|
8
|
-
* We can reuse the Axis Orientation lesson as it perfectly demonstrates rotation.
|
|
9
|
-
*/
|
|
10
|
-
function lessonRotate(canvasSize = 32, color = '#ff5722') {
|
|
11
|
-
// Reusing the axis orientation lesson which draws cylinders rotated along X, Y, Z
|
|
12
|
-
return structureLessons.lessonAxisOrientation(canvasSize, color);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
1
|
/**
|
|
16
|
-
*
|
|
17
|
-
* Sphere -> Truncated Sphere (exposing internal cross-section)
|
|
2
|
+
* Auto-extracted from transform_lessons_2.js
|
|
18
3
|
*/
|
|
19
|
-
|
|
20
|
-
const commands = [];
|
|
21
|
-
const cx = Math.floor(canvasSize / 2);
|
|
22
|
-
const cy = Math.floor(canvasSize / 2);
|
|
23
|
-
const r = Math.floor(canvasSize * 0.35);
|
|
24
|
-
|
|
25
|
-
// Original sphere (ghost)
|
|
26
|
-
commands.push(shapes.drawCircle(cx, cy, r, '#bdbdbd', false));
|
|
27
|
-
|
|
28
|
-
// Cut sphere
|
|
29
|
-
commands.push(...transformShapes.drawTruncatedSphere(cx, cy, r, color));
|
|
30
|
-
|
|
31
|
-
return commands;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Lesson: Hollow (Carve interior)
|
|
36
|
-
* Cylinder -> Pipe/Hole
|
|
37
|
-
*/
|
|
38
|
-
function lessonHollow(canvasSize = 32, color = '#3f51b5') {
|
|
39
|
-
const commands = [];
|
|
40
|
-
const cx = Math.floor(canvasSize / 2);
|
|
41
|
-
const cy = Math.floor(canvasSize / 2);
|
|
42
|
-
const outerR = Math.floor(canvasSize * 0.35);
|
|
43
|
-
const innerR = Math.floor(canvasSize * 0.25);
|
|
44
|
-
const h = Math.floor(canvasSize * 0.6);
|
|
45
|
-
|
|
46
|
-
// Hollow cylinder
|
|
47
|
-
commands.push(...transformShapes.drawHollowCylinder(cx, cy, outerR, innerR, h, color));
|
|
48
|
-
|
|
49
|
-
return commands;
|
|
50
|
-
}
|
|
4
|
+
const shapes = require('../../shapes');
|
|
51
5
|
|
|
52
6
|
/**
|
|
53
7
|
* Lesson: Combine (Merge forms)
|
|
@@ -94,9 +48,4 @@ function lessonCombine(canvasSize = 32, color = '#607d8b') {
|
|
|
94
48
|
return commands;
|
|
95
49
|
}
|
|
96
50
|
|
|
97
|
-
module.exports = {
|
|
98
|
-
lessonRotate,
|
|
99
|
-
lessonCut,
|
|
100
|
-
lessonHollow,
|
|
101
|
-
lessonCombine
|
|
102
|
-
};
|
|
51
|
+
module.exports = { lessonCombine };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_2.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Cut (Slice a form)
|
|
8
|
+
* Sphere -> Truncated Sphere (exposing internal cross-section)
|
|
9
|
+
*/
|
|
10
|
+
function lessonCut(canvasSize = 32, color = '#8bc34a') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
const r = Math.floor(canvasSize * 0.35);
|
|
15
|
+
|
|
16
|
+
// Original sphere (ghost)
|
|
17
|
+
commands.push(shapes.drawCircle(cx, cy, r, '#bdbdbd', false));
|
|
18
|
+
|
|
19
|
+
// Cut sphere
|
|
20
|
+
commands.push(...transformShapes.drawTruncatedSphere(cx, cy, r, color));
|
|
21
|
+
|
|
22
|
+
return commands;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = { lessonCut };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_2.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Hollow (Carve interior)
|
|
8
|
+
* Cylinder -> Pipe/Hole
|
|
9
|
+
*/
|
|
10
|
+
function lessonHollow(canvasSize = 32, color = '#3f51b5') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const cy = Math.floor(canvasSize / 2);
|
|
14
|
+
const outerR = Math.floor(canvasSize * 0.35);
|
|
15
|
+
const innerR = Math.floor(canvasSize * 0.25);
|
|
16
|
+
const h = Math.floor(canvasSize * 0.6);
|
|
17
|
+
|
|
18
|
+
// Hollow cylinder
|
|
19
|
+
commands.push(...transformShapes.drawHollowCylinder(cx, cy, outerR, innerR, h, color));
|
|
20
|
+
|
|
21
|
+
return commands;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { lessonHollow };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_2.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Rotate (Rotation)
|
|
8
|
+
* Analyzing how objects change when rotated around X, Y, Z axes.
|
|
9
|
+
* We can reuse the Axis Orientation lesson as it perfectly demonstrates rotation.
|
|
10
|
+
*/
|
|
11
|
+
function lessonRotate(canvasSize = 32, color = '#ff5722') {
|
|
12
|
+
// Reusing the axis orientation lesson which draws cylinders rotated along X, Y, Z
|
|
13
|
+
return structureLessons.lessonAxisOrientation(canvasSize, color);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = { lessonRotate };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Squash (Compress)
|
|
8
|
+
* Sphere -> Disk, Box -> Plate
|
|
9
|
+
*/
|
|
10
|
+
function lessonSquash(canvasSize = 32, color = '#ff9800') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const qX1 = Math.floor(canvasSize * 0.25);
|
|
13
|
+
const qX2 = Math.floor(canvasSize * 0.75);
|
|
14
|
+
const cy = Math.floor(canvasSize / 2);
|
|
15
|
+
const r = Math.floor(canvasSize * 0.15);
|
|
16
|
+
|
|
17
|
+
// 1. Squash: Sphere -> Disk
|
|
18
|
+
commands.push(shapes.drawCircle(qX1, cy, r, '#bdbdbd', false)); // Original
|
|
19
|
+
// Squashed into a flat ellipse/disk
|
|
20
|
+
commands.push(shapes.drawEllipse(qX1, cy, r * 1.2, Math.floor(r * 0.3), color, false));
|
|
21
|
+
|
|
22
|
+
// 2. Squash: Box -> Plate
|
|
23
|
+
const w = Math.floor(canvasSize * 0.2);
|
|
24
|
+
commands.push(shapes.drawRectangle(qX2 - w/2, cy - w/2, w, w, '#bdbdbd', false)); // Original
|
|
25
|
+
// Squashed into plate
|
|
26
|
+
commands.push(shapes.drawRectangle(qX2 - w, cy - Math.floor(w*0.2), w * 2, Math.floor(w*0.4), '#4caf50', false));
|
|
27
|
+
|
|
28
|
+
return commands;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { lessonSquash };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Stretch (Elongate)
|
|
8
|
+
* Sphere -> Egg, Box -> Bar
|
|
9
|
+
*/
|
|
10
|
+
function lessonStretch(canvasSize = 32, color = '#2196f3') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const qX1 = Math.floor(canvasSize * 0.25);
|
|
13
|
+
const qX2 = Math.floor(canvasSize * 0.75);
|
|
14
|
+
const cy = Math.floor(canvasSize / 2);
|
|
15
|
+
const r = Math.floor(canvasSize * 0.15);
|
|
16
|
+
|
|
17
|
+
// 1. Stretch: Sphere -> Egg
|
|
18
|
+
commands.push(shapes.drawCircle(qX1, cy, r, '#bdbdbd', false)); // Original sphere (ghost)
|
|
19
|
+
commands.push(...transformShapes.drawEgg(qX1, cy, r, color)); // Stretched into egg
|
|
20
|
+
|
|
21
|
+
// 2. Stretch: Box -> Bar (Tall)
|
|
22
|
+
const w = Math.floor(canvasSize * 0.15);
|
|
23
|
+
// Original box (ghost)
|
|
24
|
+
commands.push(shapes.drawRectangle(qX2 - w/2, cy - w/2, w, w, '#bdbdbd', false));
|
|
25
|
+
// Stretched bar
|
|
26
|
+
commands.push(shapes.drawRectangle(qX2 - w/2, cy - w * 1.5, w, w * 3, '#9c27b0', false));
|
|
27
|
+
|
|
28
|
+
return commands;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { lessonStretch };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from transform_lessons_1.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lesson: Taper & Swell (Narrow or bulge)
|
|
8
|
+
* Cylinder -> Bottle
|
|
9
|
+
*/
|
|
10
|
+
function lessonTaperSwell(canvasSize = 32, color = '#00bcd4') {
|
|
11
|
+
const commands = [];
|
|
12
|
+
const cx = Math.floor(canvasSize / 2);
|
|
13
|
+
const totalH = Math.floor(canvasSize * 0.8);
|
|
14
|
+
const topY = Math.floor(canvasSize * 0.1);
|
|
15
|
+
const bottomY = topY + totalH;
|
|
16
|
+
const r = Math.floor(canvasSize * 0.25);
|
|
17
|
+
|
|
18
|
+
// Original Cylinder (ghost)
|
|
19
|
+
commands.push(shapes.drawLine(cx - r, topY, cx - r, bottomY, '#bdbdbd'));
|
|
20
|
+
commands.push(shapes.drawLine(cx + r, topY, cx + r, bottomY, '#bdbdbd'));
|
|
21
|
+
|
|
22
|
+
// Tapered and Swelled form (Bottle)
|
|
23
|
+
const sections = [
|
|
24
|
+
{ y: topY, r: Math.floor(r * 0.3) }, // Neck (Tapered)
|
|
25
|
+
{ y: topY + Math.floor(totalH * 0.4), r: r },// Body (Swelled back to original radius)
|
|
26
|
+
{ y: bottomY, r: Math.floor(r * 0.8) } // Base (Slightly tapered)
|
|
27
|
+
];
|
|
28
|
+
commands.push(...csShapes.drawLoftedForm(cx, topY, bottomY, sections, color, true));
|
|
29
|
+
|
|
30
|
+
return commands;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = { lessonTaperSwell };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Auto-extracted from vocab_lessons.js
|
|
3
|
+
*/
|
|
4
|
+
const shapes = require('../../shapes');
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* Lesson: Visual Vocabulary - House Breakdown
|
|
@@ -15,18 +18,4 @@ function lessonVocabHouse(canvasSize = 64, step = 1) {
|
|
|
15
18
|
return vocabShapes.drawHouseBreakdown(cx, cy, canvasSize, validStep);
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
return [
|
|
20
|
-
{
|
|
21
|
-
id: 'vocab_house',
|
|
22
|
-
name: 'House Breakdown (5 Steps)',
|
|
23
|
-
description: 'Break down a house: Masses -> Structural -> Functional -> Identity -> Materials. Supply step=1..5',
|
|
24
|
-
fn: lessonVocabHouse
|
|
25
|
-
}
|
|
26
|
-
];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module.exports = {
|
|
30
|
-
lessonVocabHouse,
|
|
31
|
-
getVocabLessonCatalog
|
|
32
|
-
};
|
|
21
|
+
module.exports = { lessonVocabHouse };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* tool-register.js — Art Tree: Tool Registration Helpers
|
|
4
|
+
*
|
|
5
|
+
* Provides helper functions to reduce boilerplate when registering
|
|
6
|
+
* Art Tree MCP tools. Common patterns are abstracted here.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { z } = require('zod');
|
|
10
|
+
const { registerTool, sendCommand } = require('../../core/server');
|
|
11
|
+
const { hexColor, canvasSize } = require('./validators');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Register a lesson tool with standard pattern
|
|
15
|
+
* @param {McpServer} server - MCP server instance
|
|
16
|
+
* @param {string} name - Tool name
|
|
17
|
+
* @param {string} description - Tool description
|
|
18
|
+
* @param {Function} lessonFn - Function that returns array of commands
|
|
19
|
+
* @param {Object} [options] - Optional configuration
|
|
20
|
+
* @param {number} [options.canvasSizeMax=64] - Max canvas size
|
|
21
|
+
* @param {string} [options.defaultColor] - Default color (uses hexColor default if not provided)
|
|
22
|
+
*/
|
|
23
|
+
function registerLessonTool(server, name, description, lessonFn, options = {}) {
|
|
24
|
+
const { canvasSizeMax = 64, defaultColor } = options;
|
|
25
|
+
|
|
26
|
+
const schema = {
|
|
27
|
+
canvasSize: canvasSize.max(canvasSizeMax),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (defaultColor) {
|
|
31
|
+
schema.color = hexColor.default(defaultColor);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
registerTool(server, name, description, schema, async (params) => {
|
|
35
|
+
const commands = lessonFn(params.canvasSize, params.color || defaultColor);
|
|
36
|
+
await Promise.all(commands.map(cmd => sendCommand(cmd)));
|
|
37
|
+
return {
|
|
38
|
+
content: [{
|
|
39
|
+
type: 'text',
|
|
40
|
+
text: `✓ ${description.split(' — ')[0]} completed (${commands.length} strokes)`
|
|
41
|
+
}]
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Register a catalog tool that returns a list of available lessons
|
|
48
|
+
* @param {McpServer} server - MCP server instance
|
|
49
|
+
* @param {string} name - Tool name
|
|
50
|
+
* @param {string} description - Tool description
|
|
51
|
+
* @param {Function} getCatalogFn - Function that returns catalog array
|
|
52
|
+
* @param {string} catalogTitle - Title for the catalog output
|
|
53
|
+
*/
|
|
54
|
+
function registerCatalogTool(server, name, description, getCatalogFn, catalogTitle) {
|
|
55
|
+
registerTool(server, name, description, {}, () => {
|
|
56
|
+
const catalog = getCatalogFn();
|
|
57
|
+
const text = catalog.map(l =>
|
|
58
|
+
` • ${l.id}: ${l.name} — ${l.description}`
|
|
59
|
+
).join('\n');
|
|
60
|
+
return { content: [{ type: 'text', text: `📚 ${catalogTitle}:\n\n${text}` }] };
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Register a tool that executes a specific lesson step
|
|
66
|
+
* @param {McpServer} server - MCP server instance
|
|
67
|
+
* @param {string} name - Tool name
|
|
68
|
+
* @param {string} description - Tool description
|
|
69
|
+
* @param {Function} lessonStepFn - Function that takes step number and returns commands
|
|
70
|
+
* @param {Object} [options] - Optional configuration
|
|
71
|
+
* @param {number} [options.minStep=1] - Minimum step number
|
|
72
|
+
* @param {number} [options.maxStep=10] - Maximum step number
|
|
73
|
+
* @param {number} [options.canvasSizeMax=64] - Max canvas size
|
|
74
|
+
* @param {string} [options.defaultColor] - Default color
|
|
75
|
+
*/
|
|
76
|
+
function registerStepTool(server, name, description, lessonStepFn, options = {}) {
|
|
77
|
+
const { minStep = 1, maxStep = 10, canvasSizeMax = 64, defaultColor } = options;
|
|
78
|
+
|
|
79
|
+
const schema = {
|
|
80
|
+
canvasSize: canvasSize.max(canvasSizeMax),
|
|
81
|
+
step: z.number().int().min(minStep).max(maxStep).describe('Step number'),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (defaultColor) {
|
|
85
|
+
schema.color = hexColor.default(defaultColor);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
registerTool(server, name, description, schema, async (params) => {
|
|
89
|
+
const commands = lessonStepFn(params.canvasSize, params.step, params.color || defaultColor);
|
|
90
|
+
await Promise.all(commands.map(cmd => sendCommand(cmd)));
|
|
91
|
+
return {
|
|
92
|
+
content: [{
|
|
93
|
+
type: 'text',
|
|
94
|
+
text: `✓ ${description.split(' — ')[0]} - Step ${params.step} completed`
|
|
95
|
+
}]
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
registerLessonTool,
|
|
102
|
+
registerCatalogTool,
|
|
103
|
+
registerStepTool,
|
|
104
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* validators.js — Art Tree: Shared Zod Validators
|
|
4
|
+
*
|
|
5
|
+
* Common validation schemas used across all Art Tree tools.
|
|
6
|
+
* Centralizes repeated patterns to reduce code duplication.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { z } = require('zod');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Hex color validator - ensures valid 6-character hex color codes
|
|
13
|
+
*/
|
|
14
|
+
const hexColor = z.string()
|
|
15
|
+
.regex(/^#[0-9a-fA-F]{6}$/)
|
|
16
|
+
.describe('Hex color e.g. #ff0000');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Canvas size validator - ensures reasonable canvas dimensions
|
|
20
|
+
*/
|
|
21
|
+
const canvasSize = z.number()
|
|
22
|
+
.int()
|
|
23
|
+
.min(16)
|
|
24
|
+
.max(128)
|
|
25
|
+
.default(32)
|
|
26
|
+
.describe('Canvas dimension (16-128, default 32)');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Coordinate validator - ensures integer coordinates
|
|
30
|
+
*/
|
|
31
|
+
const coordinate = z.number()
|
|
32
|
+
.int()
|
|
33
|
+
.describe('Integer coordinate');
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Positive integer validator - for sizes, counts, etc.
|
|
37
|
+
*/
|
|
38
|
+
const positiveInt = z.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(1)
|
|
41
|
+
.describe('Positive integer (min 1)');
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Radius validator - ensures positive radius
|
|
45
|
+
*/
|
|
46
|
+
const radius = z.number()
|
|
47
|
+
.int()
|
|
48
|
+
.min(1)
|
|
49
|
+
.describe('Radius (min 1)');
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Boolean with default false
|
|
53
|
+
*/
|
|
54
|
+
const booleanFalse = z.boolean()
|
|
55
|
+
.default(false)
|
|
56
|
+
.describe('Boolean flag (default false)');
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Common tool parameter schemas
|
|
60
|
+
*/
|
|
61
|
+
const schemas = {
|
|
62
|
+
hexColor,
|
|
63
|
+
canvasSize,
|
|
64
|
+
coordinate,
|
|
65
|
+
positiveInt,
|
|
66
|
+
radius,
|
|
67
|
+
booleanFalse,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
hexColor,
|
|
72
|
+
canvasSize,
|
|
73
|
+
coordinate,
|
|
74
|
+
positiveInt,
|
|
75
|
+
radius,
|
|
76
|
+
booleanFalse,
|
|
77
|
+
schemas,
|
|
78
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* shapes/grid.js — Art Tree: Grid Shape Primitives
|
|
4
|
+
*
|
|
5
|
+
* Grid-related shape drawing functions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { drawLine } = require('./basic');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Draw a grid of squares (useful for pixel art foundation lessons).
|
|
12
|
+
* @param {number} startX - Top-left X
|
|
13
|
+
* @param {number} startY - Top-left Y
|
|
14
|
+
* @param {number} cols - Number of columns
|
|
15
|
+
* @param {number} rows - Number of rows
|
|
16
|
+
* @param {number} cellSize - Size of each cell
|
|
17
|
+
* @param {string} color - Grid line color
|
|
18
|
+
* @returns {Array<Object>} Array of command payloads
|
|
19
|
+
*/
|
|
20
|
+
function drawGrid(startX, startY, cols, rows, cellSize, color) {
|
|
21
|
+
const commands = [];
|
|
22
|
+
// Horizontal lines
|
|
23
|
+
for (let r = 0; r <= rows; r++) {
|
|
24
|
+
const y = startY + r * cellSize;
|
|
25
|
+
commands.push(drawLine(startX, y, startX + cols * cellSize, y, color));
|
|
26
|
+
}
|
|
27
|
+
// Vertical lines
|
|
28
|
+
for (let c = 0; c <= cols; c++) {
|
|
29
|
+
const x = startX + c * cellSize;
|
|
30
|
+
commands.push(drawLine(x, startY, x, startY + rows * cellSize, color));
|
|
31
|
+
}
|
|
32
|
+
return commands;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
drawGrid,
|
|
37
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* shapes/polyline.js — Art Tree: Polyline Shape Primitives
|
|
4
|
+
*
|
|
5
|
+
* Polyline-related shape drawing functions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { drawLine } = require('./basic');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Draw a continuous polyline from a list of points.
|
|
12
|
+
* @param {Array<{x: number, y: number}>} points - Array of vertices
|
|
13
|
+
* @param {string} color - Hex color
|
|
14
|
+
* @returns {Array<Object>} Array of command payloads
|
|
15
|
+
*/
|
|
16
|
+
function drawPolyline(points, color) {
|
|
17
|
+
const commands = [];
|
|
18
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
19
|
+
commands.push(drawLine(points[i].x, points[i].y, points[i+1].x, points[i+1].y, color));
|
|
20
|
+
}
|
|
21
|
+
return commands;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
drawPolyline,
|
|
26
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const lessons3d = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const lessons3d = require('../lessons/3d');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const advLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const advLessons = require('../lessons/advanced');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const analysisLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const analysisLessons = require('../lessons/analysis');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* sendCommand — they do NOT create their own drawing system.
|
|
10
10
|
*/
|
|
11
11
|
const { z } = require('zod');
|
|
12
|
-
const { registerTool, sendCommand } = require('
|
|
13
|
-
const shapes = require('
|
|
14
|
-
const lessons = require('
|
|
12
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
13
|
+
const shapes = require('../shapes/basic');
|
|
14
|
+
const lessons = require('../lessons/basic');
|
|
15
15
|
|
|
16
16
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
17
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const csLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const csLessons = require('../lessons/cross_section');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const curveLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const curveLessons = require('../lessons/curve');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const ellipseLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const ellipseLessons = require('../lessons/ellipse');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const hiddenLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const hiddenLessons = require('../lessons/hidden');
|
|
4
4
|
|
|
5
5
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
|
|
6
6
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* tools/index.js — Art Tree: MCP Tools Index
|
|
4
|
+
*
|
|
5
|
+
* Main entry point for registering all Art Tree MCP tools.
|
|
6
|
+
* Imports and registers all tool categories.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const basic = require('./basic');
|
|
10
|
+
const lessons = require('./lessons');
|
|
11
|
+
const advanced = require('./advanced');
|
|
12
|
+
const curves = require('./curves');
|
|
13
|
+
const ellipses = require('./ellipses');
|
|
14
|
+
const forms3d = require('./3d');
|
|
15
|
+
const structure = require('./structure');
|
|
16
|
+
const crossSections = require('./cross-sections');
|
|
17
|
+
const transforms = require('./transforms');
|
|
18
|
+
const surfaces = require('./surfaces');
|
|
19
|
+
const perspective = require('./perspective');
|
|
20
|
+
const hidden = require('./hidden');
|
|
21
|
+
const lighting = require('./lighting');
|
|
22
|
+
const materials = require('./materials');
|
|
23
|
+
const analysis = require('./analysis');
|
|
24
|
+
const layers = require('./layers');
|
|
25
|
+
const sky = require('./sky');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Register all Art Tree MCP tools on the server
|
|
29
|
+
* @param {McpServer} server
|
|
30
|
+
*/
|
|
31
|
+
function registerAll(server) {
|
|
32
|
+
basic.register(server);
|
|
33
|
+
lessons.register(server);
|
|
34
|
+
advanced.register(server);
|
|
35
|
+
curves.register(server);
|
|
36
|
+
ellipses.register(server);
|
|
37
|
+
forms3d.register(server);
|
|
38
|
+
structure.register(server);
|
|
39
|
+
crossSections.register(server);
|
|
40
|
+
transforms.register(server);
|
|
41
|
+
surfaces.register(server);
|
|
42
|
+
perspective.register(server);
|
|
43
|
+
hidden.register(server);
|
|
44
|
+
lighting.register(server);
|
|
45
|
+
materials.register(server);
|
|
46
|
+
analysis.register(server);
|
|
47
|
+
layers.register(server);
|
|
48
|
+
sky.register(server);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
registerAll,
|
|
53
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const layerLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const layerLessons = require('../lessons/layer');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Register all layer tools on the MCP server.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { z } = require('zod');
|
|
2
|
-
const { registerTool, sendCommand } = require('
|
|
3
|
-
const lightLessons = require('
|
|
2
|
+
const { registerTool, sendCommand } = require('../../../core/server');
|
|
3
|
+
const lightLessons = require('../lessons/light');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Register all lighting & shading tools on the MCP server.
|