Skip to content

Commit de9e069

Browse files
Blueprint Debugging, Default Nodes, and Menu Polish (v0.4.2)
1 parent b75ec11 commit de9e069

17 files changed

Lines changed: 2188 additions & 84 deletions

p3deditor/Blueprint.pde

Lines changed: 405 additions & 0 deletions
Large diffs are not rendered by default.

p3deditor/BlueprintEditor.pde

Lines changed: 753 additions & 0 deletions
Large diffs are not rendered by default.

p3deditor/CommandInterpreter.pde

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ class CommandInterpreter {
6262
else if (rawCmd.equals("tp") || rawCmd.equals("set_pos")) {
6363
if (parts.size() < 5) return "Error: tp <name> <x> <y> <z>";
6464
Entity e = findEntity(parts.get(1));
65-
if (e == null) return "Error: Entity not found: " + parts.get(1);
6665
e.transform.position.set(float(parts.get(2)), float(parts.get(3)), float(parts.get(4)));
66+
// v1.8 debug: Log execution to check values
67+
p3deditor.this.ui.debugConsole.addLog("PDES Trace: tp " + e.name + " to " + parts.get(2) + " (actual: " + e.transform.position.x + ")", 1);
6768
return "SUCCESS: Teleported " + e.name;
6869
}
6970
else if (rawCmd.equals("color") || rawCmd.equals("set_color")) {
@@ -104,29 +105,63 @@ class CommandInterpreter {
104105
e.material.roughness = float(parts.get(2));
105106
return "SUCCESS: Set roughness of " + e.name + " to " + e.material.roughness;
106107
}
108+
else if (rawCmd.equals("intensity")) {
109+
if (parts.size() < 3) return "Error: intensity <name> <val>";
110+
Entity e = findEntity(parts.get(1));
111+
if (e == null) return "Error: Entity not found: " + parts.get(1);
112+
e.lightIntensity = float(parts.get(2));
113+
return "SUCCESS: Set intensity of " + e.name + " to " + e.lightIntensity;
114+
}
115+
else if (rawCmd.equals("range")) {
116+
if (parts.size() < 3) return "Error: range <name> <val>";
117+
Entity e = findEntity(parts.get(1));
118+
if (e == null) return "Error: Entity not found: " + parts.get(1);
119+
e.lightRange = float(parts.get(2));
120+
return "SUCCESS: Set range of " + e.name + " to " + e.lightRange;
121+
}
122+
else if (rawCmd.equals("visible") || rawCmd.equals("hide")) {
123+
if (parts.size() < 2) return "Error: visible <name> [0|1]";
124+
Entity e = findEntity(parts.get(1));
125+
if (e == null) return "Error: Entity not found: " + parts.get(1);
126+
if (parts.size() >= 3) {
127+
e.visible = parts.get(2).equals("1") || parts.get(2).equalsIgnoreCase("true");
128+
} else {
129+
e.visible = !e.visible;
130+
}
131+
return "SUCCESS: " + e.name + " visibility is now " + e.visible;
132+
}
107133
else if (rawCmd.equals("delete") || rawCmd.equals("remove")) {
108134
if (parts.size() < 2) return "Error: delete <name>";
109135
Entity e = findEntity(parts.get(1));
110136
if (e == null) return "Error: Entity not found: " + parts.get(1);
111137
scene.entities.remove(e);
112138
return "SUCCESS: Deleted " + e.name;
113139
}
114-
else if (rawCmd.equals("create") || rawCmd.equals("add")) {
115-
if (parts.size() < 2) return "Error: create <type> (Cube, Sphere, Plane, Light)";
140+
else if (rawCmd.equals("create") || rawCmd.equals("add") || rawCmd.equals("spawn")) {
141+
if (parts.size() < 2) return "Error: create <type> [name] [x] [y] [z]";
116142
String type = parts.get(1).toLowerCase();
117-
if (type.equals("cube")) { scene.addEntity("Cube", "Cube"); }
118-
else if (type.equals("sphere")) { scene.addEntity("Sphere", "Sphere"); }
119-
else if (type.equals("plane")) { scene.addEntity("Plane", "Plane"); }
143+
String name = (parts.size() >= 3) ? parts.get(2) : "";
144+
float x = (parts.size() >= 4) ? float(parts.get(3)) : 0;
145+
float y = (parts.size() >= 5) ? float(parts.get(4)) : 0;
146+
float z = (parts.size() >= 6) ? float(parts.get(5)) : 0;
147+
148+
Entity e = null;
149+
if (type.equals("cube")) e = scene.addEntity(name.isEmpty()?"Cube":name, "Cube");
150+
else if (type.equals("sphere")) e = scene.addEntity(name.isEmpty()?"Sphere":name, "Sphere");
151+
else if (type.equals("plane")) e = scene.addEntity(name.isEmpty()?"Plane":name, "Plane");
120152
else if (type.equals("light") || type.equals("pointlight")) {
121-
// Safety Check: Total PointLights limited to 5
122153
int existingLights = 0;
123-
for (Entity e : scene.entities) if (e.type.equals("PointLight")) existingLights++;
124-
if (existingLights >= 5) return "Error: Maximum 5 point lights reached (Stability Guard)";
125-
126-
scene.addEntity("Light", "PointLight");
154+
for (Entity el : scene.entities) if (el.type.equals("PointLight")) existingLights++;
155+
if (existingLights >= 5) return "Error: Maximum 5 point lights reached";
156+
e = scene.addEntity(name.isEmpty()?"Light":name, "PointLight");
157+
} else {
158+
return "Error: Unknown type: " + type;
127159
}
128-
else return "Error: Unknown type: " + type;
129-
return "SUCCESS: Created " + type;
160+
161+
if (e != null && parts.size() >= 4) {
162+
e.transform.position.set(x, y, z);
163+
}
164+
return "SUCCESS: Created " + (e!=null?e.name:type) + " at (" + x + "," + y + "," + z + ")";
130165
}
131166
else if (rawCmd.equals("rename") || rawCmd.equals("name")) {
132167
if (parts.size() < 3) return "Error: rename <oldName> <newName>";
@@ -191,6 +226,12 @@ class CommandInterpreter {
191226
scene.saveSnapshot();
192227
scene.isRuntime = true;
193228
scene.clearSelection();
229+
// v1.3: Auto-compile all entity blueprints (all event types)
230+
for (Entity e : scene.entities) {
231+
if (e.blueprint != null && e.blueprint.nodes.size() > 1) {
232+
e.blueprint.compileAllEvents();
233+
}
234+
}
194235
for (Entity e : scene.entities) {
195236
scene.triggerEvent(e, "Start");
196237
}

p3deditor/DebugConsole.pde

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ class DebugConsole {
7878
if (!active) return;
7979

8080
p3deditor.this.pushStyle();
81+
p3deditor.this.hint(p3deditor.this.DISABLE_DEPTH_TEST);
82+
p3deditor.this.resetShader();
8183
// 1. Semi-transparent glass overlay (top half)
82-
p3deditor.this.fill(20, 20, 25, 230);
84+
p3deditor.this.fill(25, 25, 28, 230); // 230 for transparency test
8385
p3deditor.this.noStroke();
8486
p3deditor.this.rect(0, 0, p3deditor.this.width, p3deditor.this.height/2);
8587
p3deditor.this.stroke(100);

p3deditor/Entity.pde

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ class Entity {
88
Material material = new Material();
99
Entity parent = null;
1010
ArrayList<Entity> children = new ArrayList<Entity>();
11+
Blueprint blueprint; // v0.9.0 Visual Logic Blueprint
12+
String blueprintPDES = ""; // v0.9.4: Cached PDES logic (legacy/Start)
13+
HashMap<String, String> blueprintEventPDES = new HashMap<String, String>(); // v1.3: Per-event PDES
14+
15+
public boolean visible = true; // v1.5: Rendering toggle
1116

1217
// Point Light Specific Properties
1318
float lightIntensity = 1.0f;
@@ -41,6 +46,7 @@ class Entity {
4146
this.col = color(c.getRed(), c.getGreen(), c.getBlue());
4247
}
4348
this.material.albedo = this.col;
49+
this.blueprint = new Blueprint(this);
4450
}
4551

4652
void setParent(Entity newParent, boolean preserveWorld) {
@@ -80,6 +86,7 @@ class Entity {
8086
}
8187

8288
void render(PApplet app) {
89+
if (!visible) return;
8390
app.pushStyle();
8491
app.pushMatrix();
8592

p3deditor/SceneManager.pde

Lines changed: 167 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ class SceneManager {
2727
void restoreSnapshot() {
2828
if (sceneSnapshot == null) return;
2929

30+
// v1.1: Preserve blueprints before restoring snapshot
31+
HashMap<Integer, Blueprint> savedBlueprints = new HashMap<Integer, Blueprint>();
32+
for (Entity e : entities) {
33+
savedBlueprints.put(e.id, e.blueprint);
34+
}
35+
3036
entities.clear();
3137
selectedEntities.clear();
3238
nextEntityId = snapshotNextId;
@@ -37,6 +43,13 @@ class SceneManager {
3743
JSONObject json = sceneSnapshot.getJSONObject(i);
3844
Entity e = new Entity(json.getInt("id"), json.getString("name"), json.getString("type"));
3945
e.fromJSON(json);
46+
47+
// v1.1: Restore saved blueprint
48+
if (savedBlueprints.containsKey(e.id)) {
49+
e.blueprint = savedBlueprints.get(e.id);
50+
e.blueprint.owner = e; // Update owner reference
51+
}
52+
4053
entities.add(e);
4154
idMap.put(e.id, e);
4255
}
@@ -51,23 +64,51 @@ class SceneManager {
5164
}
5265
}
5366

54-
println("Scene Snapshot Restored");
67+
println("Scene Snapshot Restored (Blueprints preserved)");
5568
}
5669

5770
Entity findEntityById(int id) {
5871
for (Entity e : entities) if (e.id == id) return e;
5972
return null;
6073
}
6174

62-
void addEntity(String name, String type) {
75+
Entity addEntity(String name, String type) {
6376
Entity e = new Entity(nextEntityId++, name, type);
6477
entities.add(e);
6578
selectEntity(e, false);
6679
undoManager.push(new AddEntityCommand(this, e));
80+
return e;
6781
}
6882

6983
void triggerEvent(Entity e, String type) {
7084
if (e == null) return;
85+
86+
// v1.3: Multi-event Blueprint PDES support
87+
// Map runtime event names to Blueprint event keys
88+
String vlbKey = null;
89+
if (type.equals("Start")) vlbKey = "OnStart";
90+
else if (type.equals("Update")) vlbKey = "OnUpdate";
91+
else if (type.equals("onClick")) vlbKey = "OnMouseClick";
92+
else if (type.equals("OnKeyPress")) vlbKey = "OnKeyPress";
93+
else if (type.equals("OnBeginOverlap")) vlbKey = "OnBeginOverlap";
94+
else if (type.equals("OnEndOverlap")) vlbKey = "OnEndOverlap";
95+
96+
if (vlbKey != null && e.blueprintEventPDES.containsKey(vlbKey)) {
97+
String pdes = e.blueprintEventPDES.get(vlbKey);
98+
if (pdes != null && !pdes.isEmpty()) {
99+
if (!type.equals("Update")) {
100+
p3deditor.this.ui.debugConsole.addLog("> Event [" + vlbKey + "] on '" + e.name + "' running VLB Logic", 2);
101+
}
102+
p3deditor.this.scriptManager.runScript("VLB_" + vlbKey + "_" + e.name, pdes, e);
103+
}
104+
}
105+
106+
// Legacy: Also support old single-PDES field for Start
107+
if (type.equals("Start") && !e.blueprintEventPDES.containsKey("OnStart") && e.blueprintPDES != null && !e.blueprintPDES.isEmpty()) {
108+
p3deditor.this.ui.debugConsole.addLog("> Event [Start] on '" + e.name + "' running VLB Logic (legacy)", 2);
109+
p3deditor.this.scriptManager.runScript("VLB_" + e.name, e.blueprintPDES, e);
110+
}
111+
71112
ArrayList<String> scripts = e.eventHandlers.get(type);
72113
if (scripts != null) {
73114
for (String scriptPath : scripts) {
@@ -91,7 +132,7 @@ class SceneManager {
91132

92133
ArrayList<Entity> lights = new ArrayList<Entity>();
93134
for (Entity e : entities) {
94-
if (e.type.equals("PointLight")) lights.add(e);
135+
if (e.type.equals("PointLight") && e.visible) lights.add(e);
95136
if (lights.size() >= 5) break;
96137
}
97138

@@ -214,6 +255,51 @@ class SceneManager {
214255
t.setFloat("sz", e.transform.scale.z);
215256
ej.setJSONObject("transform", t);
216257

258+
// v1.1: Serialize Blueprint
259+
JSONObject bpj = new JSONObject();
260+
JSONArray nodesArr = new JSONArray();
261+
for (int ni = 0; ni < e.blueprint.nodes.size(); ni++) {
262+
VLBNode nd = e.blueprint.nodes.get(ni);
263+
JSONObject nj = new JSONObject();
264+
nj.setInt("id", nd.id);
265+
nj.setString("title", nd.title);
266+
nj.setString("type", nd.type);
267+
nj.setFloat("x", nd.x);
268+
nj.setFloat("y", nd.y);
269+
// Serialize pin default values
270+
JSONArray pinsArr = new JSONArray();
271+
ArrayList<VLBPin> allPins = new ArrayList<VLBPin>();
272+
allPins.addAll(nd.inputs); allPins.addAll(nd.outputs);
273+
for (int pi = 0; pi < allPins.size(); pi++) {
274+
VLBPin pin = allPins.get(pi);
275+
JSONObject pj = new JSONObject();
276+
pj.setString("label", pin.label);
277+
pj.setBoolean("isInput", pin.isInput);
278+
pj.setFloat("val", pin.val);
279+
pj.setString("sVal", pin.sVal);
280+
pinsArr.setJSONObject(pi, pj);
281+
}
282+
nj.setJSONArray("pins", pinsArr);
283+
nodesArr.setJSONObject(ni, nj);
284+
}
285+
bpj.setJSONArray("nodes", nodesArr);
286+
287+
// Serialize connections
288+
JSONArray connsArr = new JSONArray();
289+
for (int ci = 0; ci < e.blueprint.connections.size(); ci++) {
290+
VLBConnection conn = e.blueprint.connections.get(ci);
291+
JSONObject cj = new JSONObject();
292+
cj.setInt("fromNodeId", conn.from.parent.id);
293+
cj.setString("fromPinLabel", conn.from.label);
294+
cj.setBoolean("fromIsInput", conn.from.isInput);
295+
cj.setInt("toNodeId", conn.pinTo.parent.id);
296+
cj.setString("toPinLabel", conn.pinTo.label);
297+
cj.setBoolean("toIsInput", conn.pinTo.isInput);
298+
connsArr.setJSONObject(ci, cj);
299+
}
300+
bpj.setJSONArray("connections", connsArr);
301+
ej.setJSONObject("blueprint", bpj);
302+
217303
entArr.setJSONObject(i, ej);
218304
}
219305
root.setJSONArray("entities", entArr);
@@ -252,6 +338,84 @@ class SceneManager {
252338
e.transform.rotation.set(t.getFloat("rx"), t.getFloat("ry"), t.getFloat("rz"));
253339
e.transform.scale.set(t.getFloat("sx"), t.getFloat("sy"), t.getFloat("sz"));
254340

341+
// v1.1: Deserialize Blueprint
342+
if (!ej.isNull("blueprint")) {
343+
JSONObject bpj = ej.getJSONObject("blueprint");
344+
e.blueprint.nodes.clear();
345+
e.blueprint.connections.clear();
346+
347+
// Build a mapping from node factory type names to recreate nodes
348+
JSONArray nodesArr = bpj.getJSONArray("nodes");
349+
for (int ni = 0; ni < nodesArr.size(); ni++) {
350+
JSONObject nj = nodesArr.getJSONObject(ni);
351+
String nTitle = nj.getString("title");
352+
String nType = nj.getString("type");
353+
int nId = nj.getInt("id");
354+
float nx = nj.getFloat("x");
355+
float ny = nj.getFloat("y");
356+
357+
// Try factory first
358+
String factoryKey = nType + ": " + nTitle;
359+
VLBNode nd = createVLBNode(factoryKey, nId, nx, ny);
360+
if (nd == null) {
361+
// Fallback: create manually (e.g. Event: OnStart)
362+
nd = new VLBNode(nId, nTitle, nType, nx, ny);
363+
// Rebuild pins from saved data
364+
if (nj.hasKey("pins")) {
365+
JSONArray pinsArr = nj.getJSONArray("pins");
366+
for (int pi = 0; pi < pinsArr.size(); pi++) {
367+
JSONObject pj = pinsArr.getJSONObject(pi);
368+
boolean isInput = pj.getBoolean("isInput");
369+
VLBPin pin = nd.addPin(pj.getString("label"), isInput, true, "flow");
370+
pin.val = pj.getFloat("val");
371+
pin.sVal = pj.getString("sVal");
372+
}
373+
}
374+
}
375+
376+
// Restore pin values from saved data
377+
if (nj.hasKey("pins")) {
378+
JSONArray pinsArr = nj.getJSONArray("pins");
379+
for (int pi = 0; pi < pinsArr.size(); pi++) {
380+
JSONObject pj = pinsArr.getJSONObject(pi);
381+
String pLabel = pj.getString("label");
382+
boolean pIsInput = pj.getBoolean("isInput");
383+
VLBPin matchPin = nd.findPin(pLabel, pIsInput);
384+
if (matchPin != null) {
385+
matchPin.val = pj.getFloat("val");
386+
matchPin.sVal = pj.getString("sVal");
387+
}
388+
}
389+
}
390+
e.blueprint.nodes.add(nd);
391+
}
392+
393+
// Restore connections
394+
if (bpj.hasKey("connections")) {
395+
JSONArray connsArr = bpj.getJSONArray("connections");
396+
for (int ci = 0; ci < connsArr.size(); ci++) {
397+
JSONObject cj = connsArr.getJSONObject(ci);
398+
int fromNodeId = cj.getInt("fromNodeId");
399+
String fromPinLabel = cj.getString("fromPinLabel");
400+
boolean fromIsInput = cj.getBoolean("fromIsInput");
401+
int toNodeId = cj.getInt("toNodeId");
402+
String toPinLabel = cj.getString("toPinLabel");
403+
boolean toIsInput = cj.getBoolean("toIsInput");
404+
405+
VLBPin fromPin = null, toPin = null;
406+
for (VLBNode nd : e.blueprint.nodes) {
407+
if (nd.id == fromNodeId) fromPin = nd.findPin(fromPinLabel, fromIsInput);
408+
if (nd.id == toNodeId) toPin = nd.findPin(toPinLabel, toIsInput);
409+
}
410+
if (fromPin != null && toPin != null) {
411+
e.blueprint.connections.add(new VLBConnection(fromPin, toPin));
412+
fromPin.connectedTo = toPin;
413+
toPin.connectedTo = fromPin;
414+
}
415+
}
416+
}
417+
}
418+
255419
entities.add(e);
256420
parentIds.add(ej.isNull("parentId") ? -1 : ej.getInt("parentId"));
257421
}

0 commit comments

Comments
 (0)