@pixel-normal-edit/mcp 2.0.10 → 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.
Files changed (136) hide show
  1. package/clear-firebase.js +37 -0
  2. package/core/command-bus.js +6 -3
  3. package/core/server.js +98 -3
  4. package/domains/art-tree/README.md +134 -0
  5. package/domains/art-tree/REORGANIZATION_PLAN.md +168 -0
  6. package/domains/art-tree/REORGANIZATION_SUMMARY.md +260 -0
  7. package/domains/art-tree/index.js +58 -58
  8. package/domains/art-tree/lessons/3d/box-properties.js +38 -0
  9. package/domains/art-tree/lessons/3d/cone-properties.js +31 -0
  10. package/domains/art-tree/lessons/3d/cylinder-properties.js +29 -0
  11. package/domains/art-tree/lessons/3d/sphere-properties.js +25 -0
  12. package/domains/art-tree/lessons/advanced/angles.js +30 -0
  13. package/domains/art-tree/lessons/advanced/distances.js +26 -0
  14. package/domains/art-tree/lessons/advanced/shape-ratios.js +25 -0
  15. package/domains/art-tree/lessons/advanced/shape-relationships.js +28 -0
  16. package/domains/art-tree/lessons/advanced/symmetry-and-axis.js +26 -0
  17. package/domains/art-tree/{analysis_lessons.js → lessons/analysis/object-analysis.js} +5 -16
  18. package/domains/art-tree/lessons/basic/circles.js +26 -0
  19. package/domains/art-tree/lessons/basic/composition.js +34 -0
  20. package/domains/art-tree/lessons/basic/curves.js +31 -0
  21. package/domains/art-tree/lessons/basic/ellipses.js +26 -0
  22. package/domains/art-tree/lessons/basic/freehand.js +19 -0
  23. package/domains/art-tree/lessons/basic/index.js +36 -0
  24. package/domains/art-tree/lessons/basic/lines.js +38 -0
  25. package/domains/art-tree/lessons/basic/parallel-and-intersecting.js +22 -0
  26. package/domains/art-tree/lessons/basic/polygons.js +25 -0
  27. package/domains/art-tree/lessons/basic/proportions-and-angles.js +20 -0
  28. package/domains/art-tree/lessons/basic/spiral.js +21 -0
  29. package/domains/art-tree/lessons/basic/squares.js +28 -0
  30. package/domains/art-tree/lessons/basic/strokes.js +23 -0
  31. package/domains/art-tree/lessons/basic/triangles.js +30 -0
  32. package/domains/art-tree/lessons/cross-sections/bottle-sections.js +26 -0
  33. package/domains/art-tree/lessons/cross-sections/glass-sections.js +24 -0
  34. package/domains/art-tree/lessons/cross-sections/head-sections.js +17 -0
  35. package/domains/art-tree/lessons/curves/curve-properties.js +50 -0
  36. package/domains/art-tree/lessons/curves/curve-topology.js +45 -0
  37. package/domains/art-tree/lessons/curves/curve-types.js +44 -0
  38. package/domains/art-tree/lessons/ellipses/coaxial-ellipses.js +29 -0
  39. package/domains/art-tree/lessons/ellipses/ellipse-anatomy.js +26 -0
  40. package/domains/art-tree/lessons/ellipses/ellipse-orientations.js +28 -0
  41. package/domains/art-tree/lessons/ellipses/ellipse-proportions.js +27 -0
  42. package/domains/art-tree/lessons/hidden/hidden-box.js +20 -0
  43. package/domains/art-tree/lessons/hidden/hidden-cup.js +19 -0
  44. package/domains/art-tree/lessons/hidden/hidden-head.js +18 -0
  45. package/domains/art-tree/lessons/index.js +42 -0
  46. package/domains/art-tree/{layer_lessons.js → lessons/layers/layer-step.js} +5 -16
  47. package/domains/art-tree/lessons/lighting/contact-shadow.js +33 -0
  48. package/domains/art-tree/lessons/lighting/light-direction.js +30 -0
  49. package/domains/art-tree/lessons/lighting/light-zones.js +30 -0
  50. package/domains/art-tree/lessons/materials/material-glass.js +21 -0
  51. package/domains/art-tree/lessons/materials/material-shiny.js +26 -0
  52. package/domains/art-tree/lessons/materials/material-texture.js +26 -0
  53. package/domains/art-tree/lessons/perspective/1point-perspective.js +30 -0
  54. package/domains/art-tree/lessons/perspective/2point-perspective.js +30 -0
  55. package/domains/art-tree/lessons/perspective/3point-perspective.js +45 -0
  56. package/domains/art-tree/lessons/perspective/foreshortening.js +38 -0
  57. package/domains/art-tree/lessons/sky/sun-shapes.js +25 -0
  58. package/domains/art-tree/lessons/sky/sunset-colors.js +27 -0
  59. package/domains/art-tree/lessons/sky/sunset-sky.js +32 -0
  60. package/domains/art-tree/{structure_lessons.js → lessons/structure/axis-orientation.js} +3 -53
  61. package/domains/art-tree/lessons/structure/complex-structure.js +21 -0
  62. package/domains/art-tree/lessons/structure/x-yzaxes.js +28 -0
  63. package/domains/art-tree/lessons/surfaces/chair-analysis.js +17 -0
  64. package/domains/art-tree/lessons/surfaces/cup-analysis.js +18 -0
  65. package/domains/art-tree/lessons/surfaces/edge-types.js +40 -0
  66. package/domains/art-tree/lessons/surfaces/surface-types.js +42 -0
  67. package/domains/art-tree/lessons/transforms/bend.js +27 -0
  68. package/domains/art-tree/{transform_lessons_2.js → lessons/transforms/combine.js} +3 -54
  69. package/domains/art-tree/lessons/transforms/cut.js +25 -0
  70. package/domains/art-tree/lessons/transforms/hollow.js +24 -0
  71. package/domains/art-tree/lessons/transforms/rotate.js +16 -0
  72. package/domains/art-tree/lessons/transforms/squash.js +31 -0
  73. package/domains/art-tree/lessons/transforms/stretch.js +31 -0
  74. package/domains/art-tree/lessons/transforms/taper-swell.js +33 -0
  75. package/domains/art-tree/{vocab_lessons.js → lessons/vocab/vocab-house.js} +5 -16
  76. package/domains/art-tree/lib/tool-register.js +104 -0
  77. package/domains/art-tree/lib/validators.js +78 -0
  78. package/domains/art-tree/shapes/grid.js +37 -0
  79. package/domains/art-tree/shapes/polyline.js +26 -0
  80. package/domains/art-tree/{3d_tools.js → tools/3d.js} +2 -2
  81. package/domains/art-tree/{advanced_tools.js → tools/advanced.js} +2 -2
  82. package/domains/art-tree/{analysis_tools.js → tools/analysis.js} +2 -2
  83. package/domains/art-tree/{tools.js → tools/basic.js} +3 -3
  84. package/domains/art-tree/{cross_section_tools.js → tools/cross-sections.js} +2 -2
  85. package/domains/art-tree/{curve_tools.js → tools/curves.js} +2 -2
  86. package/domains/art-tree/{ellipse_tools.js → tools/ellipses.js} +2 -2
  87. package/domains/art-tree/{hidden_tools.js → tools/hidden.js} +2 -2
  88. package/domains/art-tree/tools/index.js +53 -0
  89. package/domains/art-tree/{layer_tools.js → tools/layers.js} +2 -2
  90. package/domains/art-tree/{light_tools.js → tools/lighting.js} +2 -2
  91. package/domains/art-tree/{material_tools.js → tools/materials.js} +2 -2
  92. package/domains/art-tree/{perspective_tools.js → tools/perspective.js} +2 -2
  93. package/domains/art-tree/{sky_tools.js → tools/sky.js} +2 -2
  94. package/domains/art-tree/{structure_tools.js → tools/structure.js} +2 -2
  95. package/domains/art-tree/{surface_tools.js → tools/surfaces.js} +2 -2
  96. package/domains/art-tree/{transform_tools.js → tools/transforms.js} +3 -3
  97. package/domains/art-tree/{vocab_tools.js → tools/vocab.js} +2 -2
  98. package/package.json +1 -1
  99. package/rules/README.md +358 -285
  100. package/rules/index.js +9 -9
  101. package/rules/prerequisites.js +121 -64
  102. package/rules/rules.js +76 -35
  103. package/rules/workflow.js +270 -56
  104. package/tools/canvas-tools.js +2 -2
  105. package/tools/drawing-tools.js +23 -12
  106. package/tools/workspace-tools.js +5 -4
  107. package/domains/art-tree/3d_lessons.js +0 -114
  108. package/domains/art-tree/advanced_lessons.js +0 -124
  109. package/domains/art-tree/cross_section_lessons.js +0 -65
  110. package/domains/art-tree/curve_lessons.js +0 -138
  111. package/domains/art-tree/ellipse_lessons.js +0 -105
  112. package/domains/art-tree/hidden_lessons.js +0 -55
  113. package/domains/art-tree/lessons.js +0 -305
  114. package/domains/art-tree/light_lessons.js +0 -92
  115. package/domains/art-tree/material_lessons.js +0 -71
  116. package/domains/art-tree/perspective_lessons.js +0 -138
  117. package/domains/art-tree/sky_lessons_1.js +0 -82
  118. package/domains/art-tree/surface_lessons.js +0 -112
  119. package/domains/art-tree/transform_lessons_1.js +0 -108
  120. /package/domains/art-tree/{3d_shapes.js → shapes/3d.js} +0 -0
  121. /package/domains/art-tree/{advanced_shapes.js → shapes/advanced.js} +0 -0
  122. /package/domains/art-tree/{analysis_shapes.js → shapes/analysis.js} +0 -0
  123. /package/domains/art-tree/{shapes.js → shapes/basic.js} +0 -0
  124. /package/domains/art-tree/{cross_section_shapes.js → shapes/cross-sections.js} +0 -0
  125. /package/domains/art-tree/{curve_shapes.js → shapes/curves.js} +0 -0
  126. /package/domains/art-tree/{ellipse_shapes.js → shapes/ellipses.js} +0 -0
  127. /package/domains/art-tree/{hidden_shapes.js → shapes/hidden.js} +0 -0
  128. /package/domains/art-tree/{layer_shapes.js → shapes/layers.js} +0 -0
  129. /package/domains/art-tree/{light_shapes.js → shapes/lighting.js} +0 -0
  130. /package/domains/art-tree/{material_shapes.js → shapes/materials.js} +0 -0
  131. /package/domains/art-tree/{perspective_shapes.js → shapes/perspective.js} +0 -0
  132. /package/domains/art-tree/{sky_shapes_1.js → shapes/sky.js} +0 -0
  133. /package/domains/art-tree/{structure_shapes.js → shapes/structure.js} +0 -0
  134. /package/domains/art-tree/{surface_shapes.js → shapes/surfaces.js} +0 -0
  135. /package/domains/art-tree/{transform_shapes.js → shapes/transforms.js} +0 -0
  136. /package/domains/art-tree/{vocab_shapes.js → shapes/vocab.js} +0 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Auto-extracted from ellipse_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Ellipse Orientations (Horizontal, Vertical, Tilted)
8
+ */
9
+ function lessonEllipseOrientations(canvasSize = 32, color = '#2196f3') {
10
+ const commands = [];
11
+ const midY = Math.floor(canvasSize / 2);
12
+ const qX = Math.floor(canvasSize / 4);
13
+ const rLong = Math.floor(canvasSize * 0.2);
14
+ const rShort = Math.floor(canvasSize * 0.1);
15
+
16
+ // Horizontal (Left)
17
+ commands.push(shapes.drawEllipse(qX, midY, rLong, rShort, color, false));
18
+
19
+ // Vertical (Middle)
20
+ commands.push(shapes.drawEllipse(qX * 2, midY, rShort, rLong, '#e91e63', false));
21
+
22
+ // Tilted (Right) - 45 degrees
23
+ commands.push(...ellipseShapes.drawRotatedEllipse(qX * 3, midY, rLong, rShort, Math.PI / 4, '#4caf50'));
24
+
25
+ return commands;
26
+ }
27
+
28
+ module.exports = { lessonEllipseOrientations };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Auto-extracted from ellipse_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Ellipse Proportions (Wide vs Narrow)
8
+ */
9
+ function lessonEllipseProportions(canvasSize = 32, color = '#ff9800') {
10
+ const commands = [];
11
+ const midY = Math.floor(canvasSize / 2);
12
+ const qX = Math.floor(canvasSize / 4);
13
+ const rx = Math.floor(canvasSize * 0.2);
14
+
15
+ // Wide Ellipse (Closer to a circle)
16
+ commands.push(shapes.drawEllipse(qX, midY, rx, Math.floor(rx * 0.8), color, false));
17
+
18
+ // Medium Ellipse
19
+ commands.push(shapes.drawEllipse(qX * 2, midY, rx, Math.floor(rx * 0.4), '#9c27b0', false));
20
+
21
+ // Narrow Ellipse (Almost a line)
22
+ commands.push(shapes.drawEllipse(qX * 3, midY, rx, Math.floor(rx * 0.1), '#f44336', false));
23
+
24
+ return commands;
25
+ }
26
+
27
+ module.exports = { lessonEllipseProportions };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Auto-extracted from hidden_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Hidden Box (6-sided box)
8
+ * You see 3 faces, but you must understand all 6.
9
+ */
10
+ function lessonHiddenBox(canvasSize = 32, visibleColor = '#2196f3', hiddenColor = '#e0e0e0') {
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize / 2);
13
+ const w = Math.floor(canvasSize * 0.4);
14
+ const h = Math.floor(canvasSize * 0.4);
15
+ const d = Math.floor(canvasSize * 0.4);
16
+
17
+ return hiddenShapes.drawXRayBox(cx, cy, w, h, d, visibleColor, hiddenColor);
18
+ }
19
+
20
+ module.exports = { lessonHiddenBox };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Auto-extracted from hidden_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Hidden Cup (Cup and inner bottom)
8
+ * You don't see the full inside bottom, but must understand how the wall goes down.
9
+ */
10
+ function lessonHiddenCup(canvasSize = 32, visibleColor = '#4caf50', hiddenColor = '#e0e0e0') {
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize / 2);
13
+ const r = Math.floor(canvasSize * 0.25);
14
+ const h = Math.floor(canvasSize * 0.5);
15
+
16
+ return hiddenShapes.drawXRayCup(cx, cy, r, h, visibleColor, hiddenColor);
17
+ }
18
+
19
+ module.exports = { lessonHiddenCup };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Auto-extracted from hidden_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Hidden Head (Human head and skull)
8
+ * You don't see the whole skull, but must understand the structure behind it.
9
+ */
10
+ function lessonHiddenHead(canvasSize = 32, visibleColor = '#ff5722', hiddenColor = '#e0e0e0') {
11
+ const cx = Math.floor(canvasSize / 2);
12
+ const cy = Math.floor(canvasSize * 0.4);
13
+ const r = Math.floor(canvasSize * 0.25);
14
+
15
+ return hiddenShapes.drawXRayHead(cx, cy, r, visibleColor, hiddenColor);
16
+ }
17
+
18
+ module.exports = { lessonHiddenHead };
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lessons/index.js — Art Tree: Lessons Index
4
+ *
5
+ * Exports all lesson functions and catalog getters organized by category.
6
+ */
7
+
8
+ const basic = require('./basic');
9
+ const advanced = require('./advanced');
10
+ const curves = require('./curves');
11
+ const ellipses = require('./ellipses');
12
+ const forms3d = require('./3d');
13
+ const structure = require('./structure');
14
+ const crossSections = require('./cross-sections');
15
+ const transforms = require('./transforms');
16
+ const surfaces = require('./surfaces');
17
+ const perspective = require('./perspective');
18
+ const hidden = require('./hidden');
19
+ const lighting = require('./lighting');
20
+ const materials = require('./materials');
21
+ const analysis = require('./analysis');
22
+ const layers = require('./layers');
23
+ const sky = require('./sky');
24
+
25
+ module.exports = {
26
+ ...basic,
27
+ ...advanced,
28
+ ...curves,
29
+ ...ellipses,
30
+ ...forms3d,
31
+ ...structure,
32
+ ...crossSections,
33
+ ...transforms,
34
+ ...surfaces,
35
+ ...perspective,
36
+ ...hidden,
37
+ ...lighting,
38
+ ...materials,
39
+ ...analysis,
40
+ ...layers,
41
+ ...sky,
42
+ };
@@ -1,4 +1,7 @@
1
- const layerShapes = require('./layer_shapes');
1
+ /**
2
+ * Auto-extracted from layer_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
2
5
 
3
6
  /**
4
7
  * Lesson: Layer Structure (Tư duy Layer)
@@ -15,18 +18,4 @@ function lessonLayerStep(canvasSize = 32, layerIndex = 1) {
15
18
  return layerShapes.drawLayeredCup(cx, cy, canvasSize, validLayer);
16
19
  }
17
20
 
18
- function getLayerLessonCatalog() {
19
- return [
20
- {
21
- id: 'layer_step',
22
- name: '7-Layer Painting Structure',
23
- description: 'View the contents of a specific layer of a Cup (1=Ref, 2=Sketch, 3=Construction, 4=Lineart, 5=Color, 6=Shadow, 7=Light)',
24
- fn: lessonLayerStep
25
- }
26
- ];
27
- }
28
-
29
- module.exports = {
30
- lessonLayerStep,
31
- getLayerLessonCatalog
32
- };
21
+ module.exports = { lessonLayerStep };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Auto-extracted from light_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Contact Shadow (Point of contact shadow)
8
+ * The darkest area where an object touches the ground.
9
+ */
10
+ function lessonContactShadow(canvasSize = 32) {
11
+ const commands = [];
12
+ const cx = Math.floor(canvasSize / 2);
13
+ const cy = Math.floor(canvasSize / 2);
14
+ const r = Math.floor(canvasSize * 0.3);
15
+
16
+ // Ground line
17
+ commands.push(shapes.drawLine(0, cy + r, canvasSize, cy + r, '#9e9e9e'));
18
+
19
+ // Sphere outline
20
+ commands.push(shapes.drawCircle(cx, cy, r, '#bdbdbd', false));
21
+
22
+ // Cast shadow (faint)
23
+ commands.push(shapes.drawEllipse(cx + Math.floor(r*0.5), cy + r, Math.floor(r*1.2), Math.floor(r*0.2), '#757575', true));
24
+
25
+ // CONTACT SHADOW (Pitch black, right at the touching point)
26
+ // Draw a very small, very dark ellipse directly under the center
27
+ commands.push(shapes.drawEllipse(cx, cy + r, Math.floor(r * 0.4), 2, '#000000', true));
28
+ commands.push(shapes.drawEllipse(cx, cy + r, Math.floor(r * 0.2), 1, '#000000', true));
29
+
30
+ return commands;
31
+ }
32
+
33
+ module.exports = { lessonContactShadow };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auto-extracted from light_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Light Direction & Intensity (Light direction and plane values)
8
+ * Shows a box with planes facing/turning away from light.
9
+ */
10
+ function lessonLightDirection(canvasSize = 32) {
11
+ const commands = [];
12
+ const cx = Math.floor(canvasSize / 2);
13
+ const cy = Math.floor(canvasSize / 2);
14
+ const w = Math.floor(canvasSize * 0.25);
15
+ const h = Math.floor(canvasSize * 0.25);
16
+
17
+ // Light from top-left
18
+ const lightAngle = -Math.PI * 0.8;
19
+
20
+ const lx = cx - Math.floor(canvasSize * 0.35);
21
+ const ly = cy - Math.floor(canvasSize * 0.35);
22
+ commands.push(...lightShapes.drawLightSource(lx, ly, Math.floor(canvasSize * 0.05)));
23
+
24
+ // Draw shaded box
25
+ commands.push(...lightShapes.drawShadedBox(cx, cy, w, h, lightAngle));
26
+
27
+ return commands;
28
+ }
29
+
30
+ module.exports = { lessonLightDirection };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auto-extracted from light_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: 6 Zones of Light (Sphere)
8
+ * Highlight, Light, Halftone, Core shadow, Reflected light, Cast shadow.
9
+ */
10
+ function lessonLightZones(canvasSize = 32) {
11
+ const commands = [];
12
+ const cx = Math.floor(canvasSize / 2);
13
+ const cy = Math.floor(canvasSize / 2);
14
+ const r = Math.floor(canvasSize * 0.25);
15
+
16
+ // Light from top-left (approx -45 degrees or -135 degrees mathematically)
17
+ const lightAngle = -Math.PI * 0.75;
18
+
19
+ // Draw light source
20
+ const lx = cx + Math.floor(r * 2 * Math.cos(lightAngle));
21
+ const ly = cy + Math.floor(r * 2 * Math.sin(lightAngle));
22
+ commands.push(...lightShapes.drawLightSource(lx, ly, Math.floor(canvasSize * 0.05)));
23
+
24
+ // Draw shaded sphere
25
+ commands.push(...lightShapes.drawShadedSphere(cx, cy, r, lightAngle));
26
+
27
+ return commands;
28
+ }
29
+
30
+ module.exports = { lessonLightZones };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Auto-extracted from material_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Transparent (Glass)
8
+ * Demonstrates Fresnel effect, sharp reflections, and light transmission.
9
+ */
10
+ function lessonMaterialGlass(canvasSize = 32) {
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
+ commands.push(...materialShapes.drawGlassSphere(cx, cy, r));
17
+
18
+ return commands;
19
+ }
20
+
21
+ module.exports = { lessonMaterialGlass };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Auto-extracted from material_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Shiny vs Matte (Metal vs Plastic/Rubber)
8
+ * Compares high contrast sharp highlights vs low contrast diffused highlights.
9
+ */
10
+ function lessonMaterialShiny(canvasSize = 32) {
11
+ const commands = [];
12
+ const cx1 = Math.floor(canvasSize * 0.3);
13
+ const cx2 = Math.floor(canvasSize * 0.7);
14
+ const cy = Math.floor(canvasSize / 2);
15
+ const r = Math.floor(canvasSize * 0.2);
16
+
17
+ // 1. Metal Sphere (Left)
18
+ commands.push(...materialShapes.drawMetalSphere(cx1, cy, r));
19
+
20
+ // 2. Matte/Plastic Sphere (Right)
21
+ commands.push(...materialShapes.drawMatteSphere(cx2, cy, r, '#e65100'));
22
+
23
+ return commands;
24
+ }
25
+
26
+ module.exports = { lessonMaterialShiny };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Auto-extracted from material_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Texture (Wood vs Stone)
8
+ * Compares organic lines vs rough cracks.
9
+ */
10
+ function lessonMaterialTexture(canvasSize = 32) {
11
+ const commands = [];
12
+ const cx1 = Math.floor(canvasSize * 0.3);
13
+ const cx2 = Math.floor(canvasSize * 0.7);
14
+ const cy = Math.floor(canvasSize / 2);
15
+ const r = Math.floor(canvasSize * 0.2);
16
+
17
+ // 1. Wood Sphere (Left)
18
+ commands.push(...materialShapes.drawTexturedSphere(cx1, cy, r, 'wood'));
19
+
20
+ // 2. Stone Sphere (Right)
21
+ commands.push(...materialShapes.drawTexturedSphere(cx2, cy, r, 'stone'));
22
+
23
+ return commands;
24
+ }
25
+
26
+ module.exports = { lessonMaterialTexture };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auto-extracted from perspective_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: 1-Point Perspective
8
+ */
9
+ function lesson1PointPerspective(canvasSize = 32, color = '#2196f3') {
10
+ const commands = [];
11
+ const horizonY = Math.floor(canvasSize * 0.4);
12
+ const vpX = Math.floor(canvasSize * 0.5);
13
+ const vpY = horizonY;
14
+
15
+ // Horizon & VP
16
+ commands.push(...perspShapes.drawHorizon(canvasSize, horizonY));
17
+ commands.push(...perspShapes.drawVP(vpX, vpY));
18
+
19
+ // Box below horizon (seeing top face)
20
+ const w = Math.floor(canvasSize * 0.2);
21
+ const h = Math.floor(canvasSize * 0.15);
22
+ commands.push(...perspShapes.draw1PointBox(vpX, vpY, Math.floor(canvasSize * 0.2), horizonY + Math.floor(canvasSize * 0.2), w, h, 0.4, color));
23
+
24
+ // Box above horizon (seeing bottom face)
25
+ commands.push(...perspShapes.draw1PointBox(vpX, vpY, Math.floor(canvasSize * 0.6), horizonY - Math.floor(canvasSize * 0.3), w, h, 0.4, '#e91e63'));
26
+
27
+ return commands;
28
+ }
29
+
30
+ module.exports = { lesson1PointPerspective };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auto-extracted from perspective_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: 2-Point Perspective
8
+ */
9
+ function lesson2PointPerspective(canvasSize = 32, color = '#4caf50') {
10
+ const commands = [];
11
+ const horizonY = Math.floor(canvasSize * 0.5);
12
+ const vp1X = Math.floor(canvasSize * 0.1);
13
+ const vp2X = Math.floor(canvasSize * 0.9);
14
+
15
+ // Horizon & VPs
16
+ commands.push(...perspShapes.drawHorizon(canvasSize, horizonY));
17
+ commands.push(...perspShapes.drawVP(vp1X, horizonY));
18
+ commands.push(...perspShapes.drawVP(vp2X, horizonY));
19
+
20
+ // 2-Point Box straddling the horizon
21
+ const startX = Math.floor(canvasSize * 0.4);
22
+ const startY = Math.floor(canvasSize * 0.3);
23
+ const h = Math.floor(canvasSize * 0.4);
24
+
25
+ commands.push(...perspShapes.draw2PointBox(vp1X, horizonY, vp2X, horizonY, startX, startY, h, 0.3, 0.4, color));
26
+
27
+ return commands;
28
+ }
29
+
30
+ module.exports = { lesson2PointPerspective };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auto-extracted from perspective_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: 3-Point Perspective (Bird's eye view)
8
+ */
9
+ function lesson3PointPerspective(canvasSize = 32, color = '#ff9800') {
10
+ const commands = [];
11
+ const horizonY = Math.floor(canvasSize * 0.2);
12
+ const vp1X = Math.floor(canvasSize * 0.1);
13
+ const vp2X = Math.floor(canvasSize * 0.9);
14
+ const vp3X = Math.floor(canvasSize * 0.5);
15
+ const vp3Y = Math.floor(canvasSize * 1.5); // VP3 far below (Bird's eye)
16
+
17
+ // Horizon & VPs
18
+ commands.push(...perspShapes.drawHorizon(canvasSize, horizonY));
19
+ commands.push(...perspShapes.drawVP(vp1X, horizonY));
20
+ commands.push(...perspShapes.drawVP(vp2X, horizonY));
21
+ // VP3 is usually off-canvas, but we draw a line to it to show direction
22
+
23
+ // We approximate a 3-point box by drawing converging vertical lines to VP3
24
+ const topY = Math.floor(canvasSize * 0.4);
25
+ const h = Math.floor(canvasSize * 0.4);
26
+
27
+ // Center edge converging to VP3
28
+ commands.push(shapes.drawLine(vp3X, topY, vp3X, topY+h, color)); // simplified
29
+ commands.push(shapes.drawLine(vp3X, topY+h, vp3X, vp3Y, '#e0e0e0')); // Guide to VP3
30
+
31
+ // Left and Right top edges to VP1, VP2
32
+ commands.push(shapes.drawLine(vp3X, topY, vp1X, horizonY, '#e0e0e0'));
33
+ commands.push(shapes.drawLine(vp3X, topY, vp2X, horizonY, '#e0e0e0'));
34
+
35
+ // Draw the rest of the box structure to simulate 3-point
36
+ const lX = vp3X - Math.floor(canvasSize * 0.15);
37
+ const rX = vp3X + Math.floor(canvasSize * 0.2);
38
+ // Vertical edges also converge to VP3 slightly (foreshortening)
39
+ commands.push(shapes.drawLine(lX, topY + Math.floor(canvasSize * 0.1), lX + 2, topY + h, color));
40
+ commands.push(shapes.drawLine(rX, topY + Math.floor(canvasSize * 0.15), rX - 3, topY + h - 5, color));
41
+
42
+ return commands;
43
+ }
44
+
45
+ module.exports = { lesson3PointPerspective };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Auto-extracted from perspective_lessons.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson: Foreshortening (Depth foreshortening)
8
+ * Drawing a cylinder pointing directly at the viewer
9
+ */
10
+ function lessonForeshortening(canvasSize = 32, color = '#9c27b0') {
11
+ const commands = [];
12
+ const cx = Math.floor(canvasSize / 2);
13
+ const cy = Math.floor(canvasSize / 2);
14
+
15
+ // Draw overlapping circles getting larger (coming towards viewer)
16
+ const numCircles = 5;
17
+ const maxR = Math.floor(canvasSize * 0.4);
18
+ const minR = Math.floor(canvasSize * 0.15);
19
+
20
+ for(let i=0; i<numCircles; i++) {
21
+ const t = i / (numCircles - 1); // 0 to 1
22
+ // Radius grows exponentially to simulate perspective
23
+ const r = minR + (maxR - minR) * (t * t);
24
+ // Y position shifts slightly to show overlap
25
+ const y = cy - Math.floor(canvasSize * 0.2) + Math.floor(canvasSize * 0.4 * t);
26
+
27
+ // Draw the circle
28
+ commands.push(shapes.drawCircle(cx, y, Math.floor(r), color, false));
29
+ }
30
+
31
+ // Draw bounding lines converging
32
+ commands.push(shapes.drawLine(cx - minR, cy - Math.floor(canvasSize * 0.2), cx - maxR, cy + Math.floor(canvasSize * 0.2), '#bdbdbd'));
33
+ commands.push(shapes.drawLine(cx + minR, cy - Math.floor(canvasSize * 0.2), cx + maxR, cy + Math.floor(canvasSize * 0.2), '#bdbdbd'));
34
+
35
+ return commands;
36
+ }
37
+
38
+ module.exports = { lessonForeshortening };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Auto-extracted from sky_lessons_1.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 1: Sun Shapes (Hình dạng mặt trời)
8
+ * Compares Basic, Soft, and Rays
9
+ */
10
+ function lessonSunShapes(canvasSize = 32) {
11
+ const commands = [];
12
+ const y = Math.floor(canvasSize / 2);
13
+ const r = Math.floor(canvasSize * 0.15);
14
+
15
+ // Left: Basic
16
+ commands.push(...skyShapes1.drawSunBasic(Math.floor(canvasSize * 0.2), y, r));
17
+ // Center: Soft
18
+ commands.push(...skyShapes1.drawSunSoft(Math.floor(canvasSize * 0.5), y, r));
19
+ // Right: Rays
20
+ commands.push(...skyShapes1.drawSunRays(Math.floor(canvasSize * 0.8), y, r));
21
+
22
+ return commands;
23
+ }
24
+
25
+ module.exports = { lessonSunShapes };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Auto-extracted from sky_lessons_1.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 2: Sunset Colors (Màu sắc buổi chiều)
8
+ * Shows the progression of colors from blue to yellow
9
+ */
10
+ function lessonSunsetColors(canvasSize = 32) {
11
+ const commands = [];
12
+
13
+ // The classic sunset gradient: Blue -> Purple -> Pink -> Orange -> Yellow (top to bottom)
14
+ const sunsetPalette = [
15
+ '#3f51b5', // Blue
16
+ '#9c27b0', // Purple
17
+ '#e91e63', // Pink
18
+ '#ff9800', // Orange
19
+ '#ffeb3b' // Yellow
20
+ ];
21
+
22
+ commands.push(...skyShapes1.drawSkyGradient(0, 0, canvasSize, canvasSize, sunsetPalette));
23
+
24
+ return commands;
25
+ }
26
+
27
+ module.exports = { lessonSunsetColors };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Auto-extracted from sky_lessons_1.js
3
+ */
4
+ const shapes = require('../../shapes');
5
+
6
+ /**
7
+ * Lesson 3: Sunset Sky (Bầu trời hoàng hôn)
8
+ * Combines the gradient sky with a soft sun setting at the bottom
9
+ */
10
+ function lessonSunsetSky(canvasSize = 32) {
11
+ const commands = [];
12
+
13
+ // 1. Draw the Sky
14
+ const sunsetPalette = [
15
+ '#1a237e', // Dark Blue
16
+ '#512da8', // Deep Purple
17
+ '#c2185b', // Magenta
18
+ '#ff5722', // Deep Orange
19
+ '#ffb300' // Amber
20
+ ];
21
+ commands.push(...skyShapes1.drawSkyGradient(0, 0, canvasSize, canvasSize, sunsetPalette));
22
+
23
+ // 2. Draw the Sun (Soft glowing sun near the bottom)
24
+ const cx = Math.floor(canvasSize / 2);
25
+ const cy = Math.floor(canvasSize * 0.8);
26
+ const r = Math.floor(canvasSize * 0.15);
27
+ commands.push(...skyShapes1.drawSunSoft(cx, cy, r));
28
+
29
+ return commands;
30
+ }
31
+
32
+ module.exports = { lessonSunsetSky };
@@ -1,44 +1,7 @@
1
- const shapes = require('./shapes');
2
- const structureShapes = require('./structure_shapes');
3
- const shapes3d = require('./3d_shapes');
4
- const ellipseShapes = require('./ellipse_shapes');
5
-
6
- /**
7
- * Lesson: XYZ Axes (Vertical, Horizontal, Depth)
8
- */
9
- function lessonXYZAxes(canvasSize = 32, color = '#2196f3') {
10
- const commands = [];
11
- const cx = Math.floor(canvasSize / 2);
12
- const cy = Math.floor(canvasSize / 2);
13
- const length = Math.floor(canvasSize * 0.4);
14
-
15
- // Draw the axes
16
- commands.push(...structureShapes.drawXYZAxes(cx, cy, length));
17
-
18
- // Draw a simple box aligned with these axes to show how objects follow them
19
- const w = Math.floor(length * 0.5);
20
- const h = Math.floor(length * 0.5);
21
- const d = Math.floor(length * 0.5);
22
- // Using a lighter color for the reference box
23
- commands.push(...shapes3d.drawWireframeBox(cx + Math.floor(w/2), cy - Math.floor(h/2), w, h, d, '#e0e0e0'));
24
-
25
- return commands;
26
- }
27
-
28
1
  /**
29
- * Lesson: Complex Structure Analysis (e.g. A Bottle)
2
+ * Auto-extracted from structure_lessons.js
30
3
  */
31
- function lessonComplexStructure(canvasSize = 32, color = '#9c27b0') {
32
- const commands = [];
33
- const cx = Math.floor(canvasSize / 2);
34
- const cy = Math.floor(canvasSize / 2);
35
- const totalHeight = Math.floor(canvasSize * 0.8);
36
-
37
- // Draw bottle structure showing cross-sections and central axis
38
- commands.push(...structureShapes.drawBottleAnatomy(cx, cy, totalHeight, color));
39
-
40
- return commands;
41
- }
4
+ const shapes = require('../../shapes');
42
5
 
43
6
  /**
44
7
  * Lesson: Axis Orientation (Object pointing along different axes)
@@ -86,17 +49,4 @@ function lessonAxisOrientation(canvasSize = 32, color = '#00bcd4') {
86
49
  return commands;
87
50
  }
88
51
 
89
- function getStructureLessonCatalog() {
90
- return [
91
- { id: 'structure_xyz', name: 'XYZ Axes', description: 'Understanding 3D space directions (Vertical, Horizontal, Depth)', fn: lessonXYZAxes },
92
- { id: 'structure_bottle', name: 'Complex Structure (Bottle)', description: 'Analyzing an object using a central axis and multiple cross-sections', fn: lessonComplexStructure },
93
- { id: 'structure_orientation', name: 'Axis Orientation', description: 'Identifying which axis an object is oriented along', fn: lessonAxisOrientation },
94
- ];
95
- }
96
-
97
- module.exports = {
98
- lessonXYZAxes,
99
- lessonComplexStructure,
100
- lessonAxisOrientation,
101
- getStructureLessonCatalog
102
- };
52
+ module.exports = { lessonAxisOrientation };