|
| 1 | +/** |
| 2 | + * BlueprintEditor.pde - Visual Logic Workspace |
| 3 | + * |
| 4 | + * Version: v0.4.9 |
| 5 | + * Responsibilities: |
| 6 | + * - Provides an interactive 'Node Graph' canvas for visual programming. |
| 7 | + * - Handles infinite panning, zooming, and grid rendering. |
| 8 | + * - Manages node lifecycle: spawning, dragging, connecting, and deletion. |
| 9 | + * - Implements the 'Compile' bridge to the PDES Scripting system. |
| 10 | + * - Supports 'Hot-Reload' of logic during engine play sessions. |
| 11 | + */ |
1 | 12 | class BlueprintEditor { |
2 | 13 | Blueprint activeBlueprint = null; |
3 | 14 | boolean visible = false; |
@@ -30,7 +41,7 @@ class BlueprintEditor { |
30 | 41 | float menuScrollY = 0; // v1.2: Menu scroll offset |
31 | 42 |
|
32 | 43 | // v1.0: Categorized Node Menu |
33 | | - String[] menuCategories = { "— Action —", "— Logic —", "— Math —", "— Data —", "— Event —", "— Value —" }; |
| 44 | + String[] menuCategories = { "�Action �, "�Logic �, "�Math �, "�Data �, "�Event �, "�Value � }; |
34 | 45 | String[][] menuItems = { |
35 | 46 | { "Action: Wait", "Action: Log", "Action: Print", "Action: Set Position", "Action: Spawn Entity", "Action: Set Visibility", "Action: Light Settings", "Action: Set Background", "Action: Camera Teleport", "Action: Get Visibility" }, |
36 | 47 | { "Logic: Branch", "Logic: Compare", "Logic: Counter", "Logic: AND", "Logic: OR", "Logic: NOT" }, |
@@ -74,6 +85,16 @@ class BlueprintEditor { |
74 | 85 | return null; |
75 | 86 | } |
76 | 87 |
|
| 88 | + /** |
| 89 | + * render() - Blueprint Canvas Pass |
| 90 | + * |
| 91 | + * [ALGORITHM] Layer-based UI Composition |
| 92 | + * Draws the visual graph in clear depth stages: |
| 93 | + * 1. Background Grid (infinite parallax). |
| 94 | + * 2. Bezier Connections (wire layer). |
| 95 | + * 3. VLB Nodes (interactive blocks). |
| 96 | + * 4. Overlays (Compiling status, Menu, Headers). |
| 97 | + */ |
77 | 98 | void render() { |
78 | 99 | if (!visible || activeBlueprint == null) return; |
79 | 100 |
|
@@ -153,7 +174,7 @@ class BlueprintEditor { |
153 | 174 | float pulse = sin((millis() - compileFlashTime) * 0.005f) * 0.3f + 0.7f; |
154 | 175 | fill(lerpColor(color(45, 140, 45), color(80, 255, 80), pulse)); |
155 | 176 | rect(runX, 10, 100, 25, 4); |
156 | | - fill(255); textSize(11); textAlign(CENTER, CENTER); text("✓ Compiled!", runX + 50, 22); |
| 177 | + fill(255); textSize(11); textAlign(CENTER, CENTER); text("�Compiled!", runX + 50, 22); |
157 | 178 | } else { |
158 | 179 | if (mouseX > runX && mouseX < runX + 100 && mouseY > 10 && mouseY < 35) fill(60, 180, 60); else fill(45, 70, 45); |
159 | 180 | rect(runX, 10, 100, 25, 4); |
@@ -349,7 +370,15 @@ class BlueprintEditor { |
349 | 370 | bezier(x1, y1, x1 + ctrlOffset, y1, x2 - ctrlOffset, y2, x2, y2); |
350 | 371 | } |
351 | 372 |
|
352 | | - // === MOUSE PRESSED === |
| 373 | + /** |
| 374 | + * handleMousePressed() / Dragged() / Released() |
| 375 | + * |
| 376 | + * [ALGORITHM] Graph Interaction Workflow |
| 377 | + * - Left-Click: Node selection or Pin drag start (wiring). |
| 378 | + * - Box Select: Dragging on empty space to group-select nodes. |
| 379 | + * - Right-Drag: Viewport panning. |
| 380 | + * - Context Menu: Right-click on empty space to spawn nodes. |
| 381 | + */ |
353 | 382 | void handleMousePressed() { |
354 | 383 | if (!visible || activeBlueprint == null) return; |
355 | 384 |
|
@@ -450,7 +479,7 @@ class BlueprintEditor { |
450 | 479 | if (cwx > n.x && cwx < n.x + n.w && cwy > n.y && cwy < n.y + n.h) { |
451 | 480 | // v1.4: If clicking an already-selected node, keep multi-selection for group drag |
452 | 481 | if (n.selected) { |
453 | | - // Already selected — just set as drag target, don't clear others |
| 482 | + // Already selected �just set as drag target, don't clear others |
454 | 483 | draggingNode = n; |
455 | 484 | } else { |
456 | 485 | if (!p3deditor.this.keyPressed || (p3deditor.this.key != 17 && p3deditor.this.keyCode != p3deditor.this.CONTROL)) { |
@@ -661,17 +690,24 @@ class BlueprintEditor { |
661 | 690 | editingPinText = ""; |
662 | 691 | } |
663 | 692 |
|
664 | | - // v1.7: Sync Expression Pins based on variables in the "Expression" pin |
| 693 | + /** |
| 694 | + * [ALGORITHM] syncExpressionPins() - Dynamic Reflection |
| 695 | + * |
| 696 | + * This critical algorithm parses a mathematical expression string (e.g. "sin(val) * 10") |
| 697 | + * and automatically generates input pins for every undefined variable ("val") |
| 698 | + * found in the string. It preserves existing connections during the sync, |
| 699 | + * enabling seamless 'Expressive Programming'. |
| 700 | + */ |
665 | 701 | void syncExpressionPins(VLBNode n) { |
666 | 702 | VLBPin exprPin = n.findPin("Expression", true); |
667 | 703 | if (exprPin == null) return; |
668 | 704 |
|
669 | 705 | String expr = exprPin.sVal; |
670 | | - java.util.HashSet<String> vars = new java.util.HashSet<String>(); |
671 | | - java.util.regex.Matcher m = java.util.regex.Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*").matcher(expr); |
| 706 | + HashSet<String> vars = new HashSet<String>(); |
| 707 | + Matcher m = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*").matcher(expr); |
672 | 708 |
|
673 | 709 | // Reserved words to ignore (functions and constants) |
674 | | - java.util.List<String> reserved = java.util.Arrays.asList( |
| 710 | + List<String> reserved = Arrays.asList( |
675 | 711 | "sin", "cos", "tan", "sqrt", "abs", "rand", "min", "max", "PI", "E", "time", "dt" |
676 | 712 | ); |
677 | 713 |
|
|
0 commit comments