From bb384ee0f701e38d94325d6e955d171f2d27bade Mon Sep 17 00:00:00 2001 From: virtualarchitectures Date: Wed, 8 Apr 2026 01:09:52 +0100 Subject: [PATCH 1/4] Restored commented sketchbook location --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6bdc908..915b67e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -84,7 +84,7 @@ if(currentOS.isMacOsX) { } // If you need to set the sketchbook location manually, uncomment out the following // line and set sketchbookLocation to the correct location -sketchbookLocation = "C:/Users/danie/OneDrive/Documentos/Processing" +// sketchbookLocation = "$userHome/Documents/Processing" // Repositories where dependencies will be fetched from. From baec63d0f85955ea26c5fe16408322d33761f89f Mon Sep 17 00:00:00 2001 From: virtualarchitectures Date: Wed, 8 Apr 2026 01:10:31 +0100 Subject: [PATCH 2/4] Added scene looping toggle --- src/main/java/paletai/mapping/Project.java | 38 ++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/main/java/paletai/mapping/Project.java b/src/main/java/paletai/mapping/Project.java index 59e84e2..339aadf 100644 --- a/src/main/java/paletai/mapping/Project.java +++ b/src/main/java/paletai/mapping/Project.java @@ -107,6 +107,9 @@ public class Project { private int transitionDuration = 2000; // 2 second transition private float transitionProgress = 0; + /** Whether spacebar loops back from the last scene to the first */ + private boolean loopScenes = false; + /** Available content generators discovered through reflection */ private ArrayList availableGenerators; @@ -920,6 +923,30 @@ public void controlEvent(CallbackEvent event) { } }); + // ---- Loop toggle button ---- + Toggle loopToggle = cp5.addToggle("Loop Scenes") + .setPosition(r + 120, r) + .setSize(40, screenButtonsArea) + .setCaptionLabel("Loop") + .setValue(loopScenes) + .setGroup(sceneList); + + loopToggle.getCaptionLabel() + .setFont(myFont) + .align(ControlP5.CENTER, ControlP5.CENTER); + loopToggle.setColorBackground(mainApplet.color(60, 60, 120)); + loopToggle.setColorForeground(mainApplet.color(90, 90, 160)); + loopToggle.setColorActive(mainApplet.color(100, 100, 220)); + loopToggle.setColorLabel(mainApplet.color(255)); + + loopToggle.addCallback(new CallbackListener() { + public void controlEvent(CallbackEvent event) { + if (event.getAction() == ControlP5.ACTION_RELEASE) { + loopScenes = loopToggle.getState(); + } + } + }); + // ---- Scene selector (radio button) ---- if (sceneRadio != null) sceneRadio.remove(); @@ -1361,12 +1388,11 @@ public void moveHoverPoint(float mousex, float mousey) { public void keyreleased(char k, int kc) { saveToFile(); if (k == ' ' && !isTransitioning) { -// sceneRadio.deactivate(currentScene); -// currentScene = PApplet.constrain(currentScene+1,0,scenes.size()-1); -// sceneRadio.activate(currentScene); -// selectScene(currentScene); - startTransition(currentScene + 1); - //PApplet.println("Next scene : currentScene + 1"); + int target = currentScene + 1; + if (target >= scenes.size() && loopScenes) { + target = 0; + } + startTransition(target); } } From 8397a5b3a552438d2fb9b0d581e6d65519bc79b9 Mon Sep 17 00:00:00 2001 From: virtualarchitectures Date: Wed, 8 Apr 2026 01:57:12 +0100 Subject: [PATCH 3/4] Added scene autoplay --- src/main/java/paletai/mapping/Project.java | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/main/java/paletai/mapping/Project.java b/src/main/java/paletai/mapping/Project.java index 339aadf..2213e70 100644 --- a/src/main/java/paletai/mapping/Project.java +++ b/src/main/java/paletai/mapping/Project.java @@ -110,6 +110,11 @@ public class Project { /** Whether spacebar loops back from the last scene to the first */ private boolean loopScenes = false; + /** Autoplay state and configuration */ + private boolean autoPlay = false; + private float autoPlayDelay = 5.0f; // seconds between scene advances + private int autoPlayLastTime = 0; // millis() timestamp of last advance + /** Available content generators discovered through reflection */ private ArrayList availableGenerators; @@ -947,6 +952,58 @@ public void controlEvent(CallbackEvent event) { } }); + // ---- Autoplay toggle ---- + Toggle autoPlayToggle = cp5.addToggle("Autoplay") + .setPosition(r + 180, r) + .setSize(40, screenButtonsArea) + .setCaptionLabel("Auto") + .setValue(autoPlay) + .setGroup(sceneList); + + autoPlayToggle.getCaptionLabel() + .setFont(myFont) + .align(ControlP5.CENTER, ControlP5.CENTER); + autoPlayToggle.setColorBackground(mainApplet.color(80, 60, 120)); + autoPlayToggle.setColorForeground(mainApplet.color(110, 90, 160)); + autoPlayToggle.setColorActive(mainApplet.color(150, 100, 220)); + autoPlayToggle.setColorLabel(mainApplet.color(255)); + + autoPlayToggle.addCallback(new CallbackListener() { + public void controlEvent(CallbackEvent event) { + if (event.getAction() == ControlP5.ACTION_RELEASE) { + autoPlay = autoPlayToggle.getState(); + autoPlayLastTime = mainApplet.millis(); // reset timer on toggle + } + } + }); + + // ---- Autoplay delay numberbox ---- + Numberbox delayBox = cp5.addNumberbox("Delay (s)") + .setPosition(r + 230, r) + .setSize(50, screenButtonsArea) + .setValue(autoPlayDelay) + .setMin(1) + .setMax(60) + .setScrollSensitivity(0.1f) + .setGroup(sceneList); + + delayBox.getCaptionLabel().hide(); + delayBox.getValueLabel() + .setFont(myFont) + .align(ControlP5.CENTER, ControlP5.CENTER); + delayBox.setColorBackground(mainApplet.color(50)); + delayBox.setColorForeground(mainApplet.color(80)); + delayBox.setColorActive(mainApplet.color(110)); + delayBox.setColorLabel(mainApplet.color(255)); + + delayBox.addCallback(new CallbackListener() { + public void controlEvent(CallbackEvent event) { + if (event.getAction() == ControlP5.ACTION_BROADCAST) { + autoPlayDelay = delayBox.getValue(); + } + } + }); + // ---- Scene selector (radio button) ---- if (sceneRadio != null) sceneRadio.remove(); @@ -1210,6 +1267,17 @@ public void render(int mousex, int mousey) { scenes.get(currentScene).render(); } + // Autoplay: advance scene when delay has elapsed + if (autoPlay && !isTransitioning) { + if (mainApplet.millis() - autoPlayLastTime >= autoPlayDelay * 1000) { + int target = currentScene + 1; + if (target >= scenes.size() && loopScenes) { + target = 0; + } + startTransition(target); + } + } + // Update screens with appropriate media list based on transition state if (isTransitioning) { // During transition, screens need access to both scenes' media @@ -1436,6 +1504,7 @@ private void completeTransition() { nextScene = -1; isTransitioning = false; transitionProgress = 0; + autoPlayLastTime = mainApplet.millis(); // reset autoplay timer from end of transition sceneRadio.activate(currentScene); } From 80e4b61391d080f3a058d4bc623a0180cebc7fdb Mon Sep 17 00:00:00 2001 From: virtualarchitectures Date: Thu, 30 Apr 2026 23:48:00 +0100 Subject: [PATCH 4/4] Fixed a memory leak by caching UI fonts --- src/main/java/paletai/mapping/Project.java | 39 ++++++++++------------ 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/main/java/paletai/mapping/Project.java b/src/main/java/paletai/mapping/Project.java index 2213e70..0daa4e8 100644 --- a/src/main/java/paletai/mapping/Project.java +++ b/src/main/java/paletai/mapping/Project.java @@ -125,6 +125,11 @@ public class Project { private PVector[] copiedUV = null; private String copiedConfigName = ""; + /** Cached fonts — created once to avoid per-frame and per-call allocation */ + PFont uiFont14; + PFont uiFont16; + PFont uiFont20; + /** * Constructs a new Project instance with the specified name. * Initializes displays, scans for media files and generators, loads configuration, @@ -143,6 +148,9 @@ public Project(PApplet p, String name) { mainApplet = p; projectName = (name == null || name.trim().isEmpty()) ? "untitled" : name.trim(); cp5 = new ControlP5(mainApplet); // must be called before creating buttons; + uiFont14 = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); + uiFont16 = mainApplet.createFont("NeueMachina-Regular.otf", 16, true); + uiFont20 = mainApplet.createFont("NeueMachina-Regular.otf", 20, true); initializeDisplays(); mainApplet.image(canvaUI, 0, 0); scanMediaFiles(); @@ -624,8 +632,7 @@ void createAssignDisplayButtons() { .disableCollapse() .hideBar(); - // font (could be declared once globally instead) - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); + PFont myFont = uiFont14; // add one button per available display for (int i = 0; i < availableDisplays.size(); i++) { @@ -693,15 +700,14 @@ void assignDisplay(Rectangle b) { */ void createScreenButtons() { if (screenList != null) screenList.remove(); - + screenList = cp5.addGroup("Screen List") .setPosition(hx1 + r, hy2 - 2 * r - screenButtonsArea) .setBackgroundHeight(screenButtonsArea) .disableCollapse(); //.hideBar(); - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); - //PFont myFont = mainApplet.createFont("Arial", 14, true); + PFont myFont = uiFont14; // ---- Add Screen button ---- Button showBtn = cp5.addButton("Show Screen") @@ -812,9 +818,8 @@ void addSelectScreenButton(int index) { .setColorBackground(mainApplet.color(100)) .setColorForeground(mainApplet.color(60)).hideBar(); - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); - //PFont myFont = mainApplet.createFont("Arial", 14, true); - + PFont myFont = uiFont14; + // Style the new radio button's label screenRadio.getItem(optionName) .getCaptionLabel() @@ -874,8 +879,7 @@ void createSceneButtons() { // load a font (you could make this global so it’s reused) - //PFont myFont = mainApplet.createFont("Arial", 14, true); - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); + PFont myFont = uiFont14; sceneList.getCaptionLabel() .setFont(myFont) .setColor(120) @@ -1053,8 +1057,7 @@ void addSelectSceneButton(int index) { Toggle t = sceneRadio.getItem(optionName); // ---- Styling label ---- - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 20, true); - //PFont myFont = mainApplet.createFont("Arial", 20, true); // load once globally if you prefer + PFont myFont = uiFont20; // t.getCaptionLabel().setFont(myFont); t.setColorLabel(mainApplet.color(255)); // label text color (white) @@ -1121,9 +1124,7 @@ void createMediaButtons() { mediaList.getCaptionLabel().setVisible(false); mediaList.hideBar(); - // Load a custom font (adjust name/size to your liking) - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 16, true); - //PFont myFont = mainApplet.createFont("Arial", 12, true); + PFont myFont = uiFont16; for (int i = 0; i < mediaFiles.size(); i++) { String name = mediaFiles.get(i); @@ -1173,14 +1174,10 @@ void createGeneratorButtons() { .setBackgroundHeight(hy2 - hy1 - 2 * r) .disableCollapse(); - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); + PFont myFont = uiFont14; generatorList.getCaptionLabel().setFont(myFont).setVisible(false).toUpperCase(false); generatorList.hideBar(); - // Load a custom font (adjust name/size to your liking) - //PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true); - //PFont myFont = mainApplet.createFont("Arial", 12, true); - for (int i = 0; i < availableGenerators.size(); i++) { LunaContentGenerator generator = availableGenerators.get(i); String name = generator.getName(); @@ -1302,7 +1299,7 @@ public void render(int mousex, int mousey) { * @see #drawTimelinePanel(int) */ void drawUI() { - PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 20, true); + PFont myFont = uiFont20; canvaUI.beginDraw(); canvaUI.background(33);