diff --git a/examples/basicProject/data/NewProject.xml b/examples/basicProject/data/NewProject.xml
index 177752b..daaca6e 100644
--- a/examples/basicProject/data/NewProject.xml
+++ b/examples/basicProject/data/NewProject.xml
@@ -7,16 +7,16 @@
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
@@ -29,13 +29,15 @@
-
-
-
-
+
+
+
+
-
+
+
+
@@ -43,15 +45,15 @@
-
-
-
-
+
+
+
+
-
+
@@ -59,13 +61,12 @@
-
-
-
-
+
+
+
+
-
diff --git a/examples/basicProject/data/ballet30fps.mp4 b/examples/basicProject/data/ballet30fps.mp4
new file mode 100644
index 0000000..05a415e
Binary files /dev/null and b/examples/basicProject/data/ballet30fps.mp4 differ
diff --git a/release.properties b/release.properties
index 657c234..be785a0 100644
--- a/release.properties
+++ b/release.properties
@@ -20,7 +20,7 @@ version=0
# Note: The prettyVersion value defined here can be overwritten by a GitHub release tag.
# If a release tag is present, the numeric part of the tag will be used as the version number.
# See docs/release.md for more details.
-prettyVersion = 0.1.0-alpha
+prettyVersion = 0.1.4-alpha
# List of authors. Links can be provided using the syntax [author name](url).
authors=[Daniel Corbani](https://danielcorbani.art.br/)
diff --git a/src/main/java/paletai/mapping/MediaItem.java b/src/main/java/paletai/mapping/MediaItem.java
index 227c388..47cc00d 100644
--- a/src/main/java/paletai/mapping/MediaItem.java
+++ b/src/main/java/paletai/mapping/MediaItem.java
@@ -1,16 +1,13 @@
package paletai.mapping;
+import controlP5.*;
import paletai.generators.LunaContentGenerator;
import processing.core.*;
import processing.data.XML;
import processing.video.*;
import processing.opengl.*;
-import java.io.File;
-import controlP5.CallbackEvent;
-import controlP5.CallbackListener;
-import controlP5.ControlP5;
-import controlP5.Group;
+import java.io.File;
/**
* A class for managing media items (images/videos) with homography
@@ -36,67 +33,116 @@
*/
public class MediaItem {
- // XML mediaXML;
- /** Parent Processing applet */
- private final PApplet p;
- /** Full path to media file */
- private String filePath;
- /** Base filename with scene index */
- public String fileName;
- /** Image object (for static images) */
- private PImage img;
- /** Thumbnail representation */
- public PImage thumbnail;
+ // XML mediaXML;
+ /**
+ * Parent Processing applet
+ */
+ private final PApplet p;
+ /**
+ * Full path to media file
+ */
+ private String filePath;
+ /**
+ * Base filename with scene index
+ */
+ public String fileName;
+ /**
+ * Image object (for static images)
+ */
+ private PImage img;
+ /**
+ * Thumbnail representation
+ */
+ public PImage thumbnail;
- /** Thumbnail display position */
- public float thumbnailX, thumbnailY;
+ /**
+ * Thumbnail display position
+ */
+ public float thumbnailX, thumbnailY;
- /** Video flag */
- private final boolean isVideo;
+ /**
+ * Video flag
+ */
+ private final boolean isVideo;
- /** Media loading status */
- private boolean loaded = false;
+ /**
+ * Media loading status
+ */
+ private boolean loaded = false;
- /** Video looping status */
- private boolean isLooping = false;
+ /**
+ * Video looping status
+ */
+ private boolean isLooping = false;
- /** Video object (for movies) */
- private Movie movie;
+ /**
+ * Video object (for movies)
+ */
+ private Movie movie;
- /** Graphics buffer for rendering */
- private PGraphics2D mediaCanvas;
+ /**
+ * Graphics buffer for rendering
+ */
+ private PGraphics2D mediaCanvas;
- /** Homography transformation handler */
- public VidMap vm; // Homography transformation
+ /**
+ * Homography transformation handler
+ */
+ public VidMap vm; // Homography transformation
- /** Original media dimensions */
- public int mediaWidth, mediaHeight;
+ /**
+ * Original media dimensions
+ */
+ public int mediaWidth, mediaHeight;
- /** Assigned screen index and media identifier */
- public int assignedScreen, mediaId;
+ /**
+ * Assigned screen index and media identifier
+ */
+ public int assignedScreen, mediaId;
- /** Display resolution for this media */
- int resolutionX, resolutionY;
+ /**
+ * Display resolution for this media
+ */
+ int resolutionX, resolutionY;
+
+ /**
+ * Calibration mode status
+ */
+ public boolean calibrate = false;
- /** Calibration mode status */
- public boolean calibrate = false;
+ /**
+ * Flag indicating whether thumbnail has been generated
+ */
+ boolean thumbnailGenerated = false;
- /** Flag indicating whether thumbnail has been generated */
- boolean thumbnailGenerated = false;
+ /**
+ * ControlP5 instance for UI controls
+ */
+ ControlP5 cp5;
- /** ControlP5 instance for UI controls */
- ControlP5 cp5;
+ /**
+ * Group containing media controls
+ */
+ Group controlGroup;
- /** Group containing media controls */
- Group controlGroup;
+ /**
+ * Controls visibility state
+ */
+ boolean controlsVisible = false;
- /** Controls visibility state */
- boolean controlsVisible = false;
+ /**
+ * Controls visibility state
+ */
+ boolean toBeDeleted = false;
- /** Content generator for generative media */
+ /**
+ * Content generator for generative media
+ */
public LunaContentGenerator generator;
- /** Flag indicating generative content */
+ /**
+ * Flag indicating generative content
+ */
private final boolean isGenerative;
/**
@@ -107,59 +153,64 @@ public class MediaItem {
public boolean copyHomographyRequested = false;
public boolean pasteHomographyRequested = false;
+ /**
+ * Font
+ */
+ private PFont mediaFont;
+
/**
* Constructs a new MediaItem from a file path.
*
- * @param p The parent PApplet instance
- * @param filePath Path to media file
+ * @param p The parent PApplet instance
+ * @param filePath Path to media file
* @param screenIndex The screen index this media is assigned to
- * @param mediaId Unique identifier for this media item
+ * @param mediaId Unique identifier for this media item
* @throws RuntimeException If media file cannot be loaded
*/
- public MediaItem(PApplet p, String filePath, int screenIndex, int mediaId) {
- this.p = p;
- this.filePath = filePath;
- this.fileName = extractFileName(filePath); // NEED TO CHECK THIS!!!!!
- this.isVideo = isVideoFile(filePath);
- this.assignedScreen = screenIndex;
- this.mediaId = mediaId;
- this.vm = new VidMap(p, fileName); // Pass fileName to vm
- initVariables();
+ public MediaItem(PApplet p, String filePath, int screenIndex, int mediaId) {
+ this.p = p;
+ this.filePath = filePath;
+ this.fileName = extractFileName(filePath); // NEED TO CHECK THIS!!!!!
+ this.isVideo = isVideoFile(filePath);
+ this.assignedScreen = screenIndex;
+ this.mediaId = mediaId;
+ this.vm = new VidMap(p, fileName); // Pass fileName to vm
+ initVariables();
isGenerative = false;
- }
+ }
/**
* Constructs a MediaItem from XML configuration.
* Recreates a media item from saved project data.
*
- * @param p The parent PApplet instance
+ * @param p The parent PApplet instance
* @param mediaXML XML element containing media configuration
*/
- public MediaItem(PApplet p, XML mediaXML) {
- // PApplet.println("Start MediaItem");
- this.p = p;
- this.filePath = mediaXML.getString("name");
- // PApplet.println("filePath " + filePath);
- this.fileName = extractFileName(filePath); // NEED TO CHECK THIS!!!!!
- // PApplet.println(fileName);
- this.isVideo = isVideoFile(filePath);
- // this.sceneIndex = sceneIndex;
- this.assignedScreen = mediaXML.getInt("Screen");
- this.mediaId = mediaXML.getInt("id");
- this.vm = new VidMap(p, fileName); // Pass fileName to vm
- initVariables();
- updateFromXML(mediaXML);
- loaded = true;
+ public MediaItem(PApplet p, XML mediaXML) {
+ // PApplet.println("Start MediaItem");
+ this.p = p;
+ this.filePath = mediaXML.getString("name");
+ // PApplet.println("filePath " + filePath);
+ this.fileName = extractFileName(filePath); // NEED TO CHECK THIS!!!!!
+ // PApplet.println(fileName);
+ this.isVideo = isVideoFile(filePath);
+ // this.sceneIndex = sceneIndex;
+ this.assignedScreen = mediaXML.getInt("Screen");
+ this.mediaId = mediaXML.getInt("id");
+ this.vm = new VidMap(p, fileName); // Pass fileName to vm
+ initVariables();
+ updateFromXML(mediaXML);
+ loaded = true;
isGenerative = false;
- }
+ }
/**
* Constructs a generative MediaItem from a content generator.
*
- * @param p The parent PApplet instance
- * @param generator The content generator to use
+ * @param p The parent PApplet instance
+ * @param generator The content generator to use
* @param screenIndex The screen index this media is assigned to
- * @param mediaId Unique identifier for this media item
+ * @param mediaId Unique identifier for this media item
*/
public MediaItem(PApplet p, LunaContentGenerator generator, int screenIndex, int mediaId) {
this.p = p;
@@ -178,9 +229,9 @@ public MediaItem(PApplet p, LunaContentGenerator generator, int screenIndex, int
* Constructs a generative MediaItem from XML configuration.
* Recreates a generative media item from saved project data.
*
- * @param p The parent PApplet instance
+ * @param p The parent PApplet instance
* @param generator The content generator to use
- * @param mediaXML XML element containing media configuration
+ * @param mediaXML XML element containing media configuration
*/
public MediaItem(PApplet p, LunaContentGenerator generator, XML mediaXML) {
this.p = p;
@@ -201,7 +252,7 @@ public MediaItem(PApplet p, LunaContentGenerator generator, XML mediaXML) {
*
* @return true if this is a generative media item, false for file-based media
*/
- boolean isGenerative(){
+ boolean isGenerative() {
return isGenerative;
}
@@ -212,23 +263,23 @@ boolean isGenerative(){
* @return XML element containing complete media configuration
* @see #arrayToXML(String, PVector[])
*/
- XML saveXML() {
- XML xml = new XML("MediaItem");
- xml.setString("name", fileName);
- xml.setInt("Screen", assignedScreen);
- xml.setInt("id", mediaId);
- xml.setInt("width", mediaWidth);
- xml.setInt("height", mediaHeight);
+ XML saveXML() {
+ XML xml = new XML("MediaItem");
+ xml.setString("name", fileName);
+ xml.setInt("Screen", assignedScreen);
+ xml.setInt("id", mediaId);
+ xml.setInt("width", mediaWidth);
+ xml.setInt("height", mediaHeight);
int intGen;
- if (isGenerative) intGen =1;
+ if (isGenerative) intGen = 1;
else intGen = 0;
- xml.setInt("isGenerator",intGen);
- if (vm.xyN[0] != null)
- xml.addChild(arrayToXML("xyN", vm.xyN));
- if (vm.uvN[0] != null)
- xml.addChild(arrayToXML("uvN", vm.uvN));
- return xml;
- }
+ xml.setInt("isGenerator", intGen);
+ if (vm.xyN[0] != null)
+ xml.addChild(arrayToXML("xyN", vm.xyN));
+ if (vm.uvN[0] != null)
+ xml.addChild(arrayToXML("uvN", vm.uvN));
+ return xml;
+ }
/**
* Converts a PVector array to XML format for serialization.
@@ -237,17 +288,17 @@ XML saveXML() {
* @param arr The PVector array to convert
* @return XML element containing the vector array data
*/
- XML arrayToXML(String tag, PVector[] arr) {
- XML arrayXML = new XML(tag);
- for (int i = 0; i < arr.length; i++) {
- XML v = new XML("point");
- v.setInt("index", i);
- v.setFloat("x", arr[i].x);
- v.setFloat("y", arr[i].y);
- arrayXML.addChild(v);
- }
- return arrayXML;
- }
+ XML arrayToXML(String tag, PVector[] arr) {
+ XML arrayXML = new XML(tag);
+ for (int i = 0; i < arr.length; i++) {
+ XML v = new XML("point");
+ v.setInt("index", i);
+ v.setFloat("x", arr[i].x);
+ v.setFloat("y", arr[i].y);
+ arrayXML.addChild(v);
+ }
+ return arrayXML;
+ }
/**
* Creates the UI control group for this media item.
@@ -257,116 +308,167 @@ XML arrayToXML(String tag, PVector[] arr) {
* @see ControlP5
* @see Group
*/
- private void createControlGroup() {
- cp5 = new ControlP5(p);
- // Create a group for this media item's controls
- controlGroup = cp5.addGroup("media_" + System.currentTimeMillis()) // Unique name
- .setPosition(thumbnailX, thumbnailY).setWidth(150) // Match thumbnail width
- .setHeight(50) // Slightly taller to fit controls
- .setBackgroundColor(p.color(50, 220)) // Semi-transparent background
- .setBackgroundHeight(20).disableCollapse().hideBar();
- // .hide(); // Start hidden
-
- // Add controls to the group
- cp5.addButton("calibrate" + controlGroup.getName()).setPosition(10, 10).setSize(60, 20)
- .setCaptionLabel("Mapping").setGroup(controlGroup).addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- // println("Bang released: " + event.getController().getName());
- // Your function call here
- toggleCalibration();
- }
- }
- });
-
- cp5.addButton("in/out" + controlGroup.getName()).setPosition(80, 10).setSize(60, 20).setCaptionLabel("in/out")
- .setGroup(controlGroup).addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- // println("Bang released: " + event.getController().getName());
- // Your function call here
- toggleInput();
- }
- }
- });
-
-
- cp5.addButton("copyHomography" + controlGroup.getName())
+ private void createControlGroup() {
+ cp5 = new ControlP5(p);
+ // Create a group for this media item's controls
+ controlGroup = cp5.addGroup("media_" + System.currentTimeMillis()) // Unique name
+ .setPosition(thumbnailX, thumbnailY).setWidth(150) // Match thumbnail width
+ .setHeight(50) // Slightly taller to fit controls
+ .setBackgroundColor(p.color(50, 220)) // Semi-transparent background
+ .setBackgroundHeight(20).disableCollapse().hideBar();
+ // .hide(); // Start hidden
+
+ // Add controls to the group
+ Button b1 = cp5.addButton("calibrate" + controlGroup.getName())
+ .setPosition(10, 10)
+ .setSize(60, 20)
+ .setCaptionLabel("Mapping")
+ .setGroup(controlGroup);
+ b1.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b1.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ // println("Bang released: " + event.getController().getName());
+ // Your function call here
+ toggleCalibration();
+ }
+ }
+ });
+
+ Button b2 = cp5.addButton("in/out" + controlGroup.getName())
+ .setPosition(80, 10)
+ .setSize(60, 20)
+ .setCaptionLabel("in/out")
+ .setGroup(controlGroup);
+ b2.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b2.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ // println("Bang released: " + event.getController().getName());
+ // Your function call here
+ toggleInput();
+ }
+ }
+ });
+
+
+ Button b3 = cp5.addButton("copyHomography" + controlGroup.getName())
.setPosition(10, 40) // Position below existing buttons
.setSize(60, 20)
.setCaptionLabel("Copy")
- .setGroup(controlGroup)
- .addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- copyHomographyRequested = true;
- }
- }
- });
+ .setGroup(controlGroup);
+ b3.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b3.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ copyHomographyRequested = true;
+ }
+ }
+ });
- cp5.addButton("pasteHomography" + controlGroup.getName())
+ Button b4 = cp5.addButton("pasteHomography" + controlGroup.getName())
.setPosition(80, 40)
.setSize(60, 20)
.setCaptionLabel("Paste")
- .setGroup(controlGroup)
- .addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- pasteHomographyRequested = true;
- }
- }
- });
+ .setGroup(controlGroup);
+ b4.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b4.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ pasteHomographyRequested = true;
+ }
+ }
+ });
+
+ Button b8 = cp5.addButton("deleteThisMedia" + controlGroup.getName())
+ .setPosition(130, 100)
+ .setSize(20, 20)
+ .setCaptionLabel("x")
+ .setGroup(controlGroup);
+ b8.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b8.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ //pasteHomographyRequested = true;
+ toBeDeleted = true;
+ PApplet.println("media deleted");
+ }
+ }
+ });
// Video controls
- if (isVideo) {
- cp5.addButton("play" + controlGroup.getName()).setPosition(10, 80).setSize(30, 20).setCaptionLabel("Play")
- .setGroup(controlGroup).addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- // println("Bang released: " + event.getController().getName());
- // Your function call here
- playMedia();
- }
- }
- });
- cp5.addButton("stop" + controlGroup.getName()).setPosition(45, 80).setSize(30, 20).setCaptionLabel("Stop")
- .setGroup(controlGroup).addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- // println("Bang released: " + event.getController().getName());
- // Your function call here
- stopMedia();
- }
- }
- });
- cp5.addButton("loop" + controlGroup.getName()).setPosition(80, 80).setSize(30, 20).setCaptionLabel("Loop")
- .setGroup(controlGroup).addCallback(new CallbackListener() {
- public void controlEvent(CallbackEvent event) {
- if (event.getAction() == ControlP5.ACTION_RELEASE) {
- // println("Bang released: " + event.getController().getName());
- // Your function call here
- loopMedia();
- }
- }
- });
- }
- }
+ if (isVideo) {
+ Button b5 = cp5.addButton("play" + controlGroup.getName())
+ .setPosition(10, 80)
+ .setSize(30, 20)
+ .setCaptionLabel("Play")
+ .setGroup(controlGroup);
+ b5.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b5.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ // println("Bang released: " + event.getController().getName());
+ // Your function call here
+ playMedia();
+ }
+ }
+ });
+ Button b6 = cp5.addButton("stop" + controlGroup.getName())
+ .setPosition(45, 80)
+ .setSize(30, 20)
+ .setCaptionLabel("Stop")
+ .setGroup(controlGroup);
+ b6.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b6.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ // println("Bang released: " + event.getController().getName());
+ // Your function call here
+ stopMedia();
+ }
+ }
+ });
+ Button b7 = cp5.addButton("loop" + controlGroup.getName())
+ .setPosition(80, 80)
+ .setSize(30, 20)
+ .setCaptionLabel("Loop")
+ .setGroup(controlGroup);
+ b7.getCaptionLabel().setFont(mediaFont).toUpperCase(false); // font
+ b7.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ // println("Bang released: " + event.getController().getName());
+ // Your function call here
+ loopMedia();
+ }
+ }
+ });
+ }
+ }
/**
* Shows the media item's control group.
* Makes the calibration and playback controls visible.
*/
- public void showControls() {
- controlGroup.show();
- }
+ public void deleteControls() {
+ controlGroup.remove();
+ }
+
+ /**
+ * Shows the media item's control group.
+ * Makes the calibration and playback controls visible.
+ */
+ public void showControls() {
+ controlGroup.show();
+ }
/**
* Hides the media item's control group.
* Removes the calibration and playback controls from display.
*/
- public void hideControls() {
- controlGroup.hide();
- }
+ public void hideControls() {
+ controlGroup.hide();
+ }
/**
* Sets the thumbnail position and updates control group placement.
@@ -375,44 +477,45 @@ public void hideControls() {
* @param x The x-coordinate for thumbnail placement
* @param y The y-coordinate for thumbnail placement
*/
- public void setThumbnailPosition(int x, int y) {
- this.thumbnailX = x;
- this.thumbnailY = y;
- // PApplet.println("Thumnail position: " + thumbnailX + "," + thumbnailY);
- controlGroup.setPosition(x, y); // Position above thumbnail
- }
+ public void setThumbnailPosition(int x, int y) {
+ this.thumbnailX = x;
+ this.thumbnailY = y;
+ // PApplet.println("Thumnail position: " + thumbnailX + "," + thumbnailY);
+ controlGroup.setPosition(x, y); // Position above thumbnail
+ }
/**
* Initializes media variables and creates thumbnails.
* Loads media files, creates thumbnails, and sets up initial dimensions.
* For generative content, prepares the generator system.
*/
- void initVariables() {
- // PApplet.println("initVariables");
- if (isVideo) {
- // PApplet.println("is video");
- this.movie = new Movie(p, filePath);
- movie.play(); // Preload the movie (optional)
- mediaWidth = movie.width;
- mediaHeight = movie.height;
- thumbnail = p.createImage(150, 100, PConstants.RGB);
-
- } else if (isGenerative){
+ void initVariables() {
+ // PApplet.println("initVariables");
+ mediaFont = p.createFont("NeueMachina-Regular.otf", 10, true);
+ if (isVideo) {
+ // PApplet.println("is video");
+ this.movie = new Movie(p, filePath);
+ movie.play(); // Preload the movie (optional)
+ mediaWidth = movie.width;
+ mediaHeight = movie.height;
+ thumbnail = p.createImage(150, 100, PConstants.RGB);
+
+ } else if (isGenerative) {
// PApplet.println("MediaItem is picture");
// mediaWidth = 0;
// mediaHeight = 0;
thumbnail = p.createImage(150, 100, PConstants.RGB);
- } else{
- // PApplet.println("MediaItem is picture");
- img = p.loadImage(filePath);
- mediaWidth = img.width;
- mediaHeight = img.height;
- thumbnail = p.createImage(150, 100, PConstants.RGB);
- }
- thumbnailX = 0;// (thumbnail.width+50)*mediaId;
- thumbnailY = 0;
- createControlGroup();
- }
+ } else {
+ // PApplet.println("MediaItem is picture");
+ img = p.loadImage(filePath);
+ mediaWidth = img.width;
+ mediaHeight = img.height;
+ thumbnail = p.createImage(150, 100, PConstants.RGB);
+ }
+ thumbnailX = 0;// (thumbnail.width+50)*mediaId;
+ thumbnailY = 0;
+ createControlGroup();
+ }
/**
* Updates media item configuration from XML data.
@@ -421,15 +524,15 @@ void initVariables() {
* @param xml XML element containing saved media configuration
* @see #arrayFromXML(XML)
*/
- void updateFromXML(XML xml) {
+ void updateFromXML(XML xml) {
PApplet.println(fileName);
- PVector[] xyNew = arrayFromXML(xml.getChild("xyN"));
- PVector[] uvNew = arrayFromXML(xml.getChild("uvN"));
+ PVector[] xyNew = arrayFromXML(xml.getChild("xyN"));
+ PVector[] uvNew = arrayFromXML(xml.getChild("uvN"));
//PApplet.printArray(uvNew);
- vm.xyN = arrayFromXML(xml.getChild("xyN"));
- vm.uvN = arrayFromXML(xml.getChild("uvN"));
- updateHomography(xyNew, uvNew);
- }
+ vm.xyN = arrayFromXML(xml.getChild("xyN"));
+ vm.uvN = arrayFromXML(xml.getChild("uvN"));
+ updateHomography(xyNew, uvNew);
+ }
/**
* Converts XML data back to a PVector array.
@@ -438,35 +541,35 @@ void updateFromXML(XML xml) {
* @param arrayXML XML element containing point data
* @return PVector array reconstructed from XML
*/
- PVector[] arrayFromXML(XML arrayXML) {
- XML[] points = arrayXML.getChildren("point");
- PVector[] arr = new PVector[points.length];
- for (int i = 0; i < points.length; i++) {
- // PApplet.println(points[i].getName());
- float x = points[i].getFloat("x");
- float y = points[i].getFloat("y");
- // float z = points[i].hasAttribute("z") ? points[i].getFloat("z") : 0;
- arr[i] = new PVector(x, y);
- // PApplet.println(arr[i]);
- }
- return arr;
- }
+ PVector[] arrayFromXML(XML arrayXML) {
+ XML[] points = arrayXML.getChildren("point");
+ PVector[] arr = new PVector[points.length];
+ for (int i = 0; i < points.length; i++) {
+ // PApplet.println(points[i].getName());
+ float x = points[i].getFloat("x");
+ float y = points[i].getFloat("y");
+ // float z = points[i].hasAttribute("z") ? points[i].getFloat("z") : 0;
+ arr[i] = new PVector(x, y);
+ // PApplet.println(arr[i]);
+ }
+ return arr;
+ }
/**
* Updates an existing XML node with new PVector values.
* Modifies the XML structure to reflect current homography points.
*
* @param arrayXML The XML element to update
- * @param arr The new PVector array values
+ * @param arr The new PVector array values
*/
- void updateArrayXML(XML arrayXML, PVector[] arr) {
- XML[] points = arrayXML.getChildren("point");
- for (int i = 0; i < arr.length && i < points.length; i++) {
- // println(arrayXML.getName() + " " + points[i]);
- points[i].setFloat("x", arr[i].x);
- points[i].setFloat("y", arr[i].y);
- }
- }
+ void updateArrayXML(XML arrayXML, PVector[] arr) {
+ XML[] points = arrayXML.getChildren("point");
+ for (int i = 0; i < arr.length && i < points.length; i++) {
+ // println(arrayXML.getName() + " " + points[i]);
+ points[i].setFloat("x", arr[i].x);
+ points[i].setFloat("y", arr[i].y);
+ }
+ }
/**
* Assigns this media item to a display with specific dimensions.
@@ -474,90 +577,90 @@ void updateArrayXML(XML arrayXML, PVector[] arr) {
* transformation for the target display. For generative content, calls
* the generator's setup method.
*
- * @param w The width of the target display
- * @param h The height of the target display
+ * @param w The width of the target display
+ * @param h The height of the target display
* @param screenIndex The index of the screen to assign to
* @see LunaContentGenerator#setup(int, int)
* @see VidMap#assignToDisplay(int, int)
*/
- public void assignToDisplay(int w, int h, int screenIndex) {
- // PApplet.println("MediaItem Assigned to Display: " + screenIndex);
- PApplet.println("=== assignToDisplay ===");
- PApplet.println("Received dimensions: " + w + "x" + h);
- PApplet.println("Screen index: " + screenIndex);
-
- this.resolutionX = w;
- this.resolutionY = h;
- this.mediaCanvas = (PGraphics2D) p.createGraphics(resolutionX, resolutionY, PConstants.P2D);
-
- PApplet.println("mediaCanvas created: " + mediaCanvas.width + "x" + mediaCanvas.height);
-
- this.mediaCanvas.beginDraw();
- this.mediaCanvas.clear();
- this.mediaCanvas.endDraw();
- this.assignedScreen = screenIndex;
- if (isGenerative){
- PApplet.println("Calling generator.setup(" + resolutionX + ", " + resolutionY + ")");
- this.generator.setup(resolutionX,resolutionY);
+ public void assignToDisplay(int w, int h, int screenIndex) {
+ // PApplet.println("MediaItem Assigned to Display: " + screenIndex);
+ //PApplet.println("=== assignToDisplay ===");
+ //PApplet.println("Received dimensions: " + w + "x" + h);
+ //PApplet.println("Screen index: " + screenIndex);
+
+ this.resolutionX = w;
+ this.resolutionY = h;
+ this.mediaCanvas = (PGraphics2D) p.createGraphics(resolutionX, resolutionY, PConstants.P2D);
+
+ //PApplet.println("mediaCanvas created: " + mediaCanvas.width + "x" + mediaCanvas.height);
+
+ this.mediaCanvas.beginDraw();
+ this.mediaCanvas.clear();
+ this.mediaCanvas.endDraw();
+ this.assignedScreen = screenIndex;
+ if (isGenerative) {
+ //PApplet.println("Calling generator.setup(" + resolutionX + ", " + resolutionY + ")");
+ this.generator.setup(resolutionX, resolutionY);
mediaWidth = resolutionX;
mediaHeight = resolutionY;
- PApplet.println("Generator setup complete");
+ //PApplet.println("Generator setup complete");
}
- vm.assignToDisplay(resolutionX, resolutionY);
- }
+ vm.assignToDisplay(resolutionX, resolutionY);
+ }
/**
* Checks if media is successfully loaded and ready for display.
*
* @return true if media is ready for display, false otherwise
*/
- public boolean isLoaded() {
- return loaded;
- }
+ public boolean isLoaded() {
+ return loaded;
+ }
/**
* Adjusts media display to maintain aspect ratio.
* Automatically updates homography points to fit media properly within
* the display canvas while preserving the original aspect ratio.
*
- * @param mediaWidth Original media width
+ * @param mediaWidth Original media width
* @param mediaHeight Original media height
* @see VidMap#updateHomographyFromPixel(PVector[], PVector[])
*/
- public void applyAspectRatioCorrection(int mediaWidth, int mediaHeight) {
- // PApplet.println("applyAspectRatioCorrection");
- float screenAspect = (float) mediaCanvas.width / mediaCanvas.height;
- // System.out.println("screenAspect = " + screenAspect); //1.3334
- float mediaAspect = (float) mediaWidth / mediaHeight;
- // System.out.println("mediaAspect = " + mediaAspect); //0.5625
- float newWidth, newHeight;
- float offsetX = 0, offsetY = 0;
-
- if (mediaAspect > screenAspect) {
- // Fit to width
- newWidth = mediaCanvas.width;
- newHeight = mediaCanvas.width / mediaAspect;
- offsetY = (mediaCanvas.height - newHeight) / 2;
- } else {
- // Fit to height
- newHeight = mediaCanvas.height;
- newWidth = mediaCanvas.height * mediaAspect;
- offsetX = (mediaCanvas.width - newWidth) / 2;
- }
-
- // Update homography points
- PVector[] uvP = { new PVector(offsetX, offsetY), new PVector(offsetX + newWidth, offsetY),
- new PVector(offsetX + newWidth, offsetY + newHeight), new PVector(offsetX, offsetY + newHeight) };
-
- PVector[] xyP = { new PVector(0, 0), new PVector(mediaCanvas.width, 0),
- new PVector(mediaCanvas.width, mediaCanvas.height), new PVector(0, mediaCanvas.height) };
-
- vm.updateHomographyFromPixel(xyP, uvP);
+ public void applyAspectRatioCorrection(int mediaWidth, int mediaHeight) {
+ // PApplet.println("applyAspectRatioCorrection");
+ float screenAspect = (float) mediaCanvas.width / mediaCanvas.height;
+ // System.out.println("screenAspect = " + screenAspect); //1.3334
+ float mediaAspect = (float) mediaWidth / mediaHeight;
+ // System.out.println("mediaAspect = " + mediaAspect); //0.5625
+ float newWidth, newHeight;
+ float offsetX = 0, offsetY = 0;
+
+ if (mediaAspect > screenAspect) {
+ // Fit to width
+ newWidth = mediaCanvas.width;
+ newHeight = mediaCanvas.width / mediaAspect;
+ offsetY = (mediaCanvas.height - newHeight) / 2;
+ } else {
+ // Fit to height
+ newHeight = mediaCanvas.height;
+ newWidth = mediaCanvas.height * mediaAspect;
+ offsetX = (mediaCanvas.width - newWidth) / 2;
+ }
+
+ // Update homography points
+ PVector[] uvP = {new PVector(offsetX, offsetY), new PVector(offsetX + newWidth, offsetY),
+ new PVector(offsetX + newWidth, offsetY + newHeight), new PVector(offsetX, offsetY + newHeight)};
+
+ PVector[] xyP = {new PVector(0, 0), new PVector(mediaCanvas.width, 0),
+ new PVector(mediaCanvas.width, mediaCanvas.height), new PVector(0, mediaCanvas.height)};
+
+ vm.updateHomographyFromPixel(xyP, uvP);
// if (loaded) {
// // updateFromXML(fromXML);
// }
- }
- // **🔹 vm Wrapper Methods**
+ }
+ // **🔹 vm Wrapper Methods**
/**
* Updates the homography transformation with new coordinate points.
@@ -567,9 +670,9 @@ public void applyAspectRatioCorrection(int mediaWidth, int mediaHeight) {
* @param uvNew New source points for transformation
* @see VidMap#updateHomography(PVector[], PVector[])
*/
- public void updateHomography(PVector[] xyNew, PVector[] uvNew) {
- vm.updateHomography(xyNew, uvNew);
- }
+ public void updateHomography(PVector[] xyNew, PVector[] uvNew) {
+ vm.updateHomography(xyNew, uvNew);
+ }
/**
* Toggles calibration mode for this media item.
@@ -577,10 +680,10 @@ public void updateHomography(PVector[] xyNew, PVector[] uvNew) {
*
* @see VidMap#toggleCalibration()
*/
- public void toggleCalibration() {
- vm.toggleCalibration();
- this.calibrate = vm.calibrate;
- }
+ public void toggleCalibration() {
+ vm.toggleCalibration();
+ this.calibrate = vm.calibrate;
+ }
/**
* Turns off calibration mode for this media item.
@@ -588,10 +691,10 @@ public void toggleCalibration() {
*
* @see VidMap#offCalibration()
*/
- public void offCalibration() {
- vm.offCalibration();
- this.calibrate = vm.calibrate;
- }
+ public void offCalibration() {
+ vm.offCalibration();
+ this.calibrate = vm.calibrate;
+ }
/**
* Turns on calibration mode for this media item.
@@ -599,10 +702,10 @@ public void offCalibration() {
*
* @see VidMap#onCalibration()
*/
- public void onCalibration() {
- vm.onCalibration();
- this.calibrate = vm.calibrate;
- }
+ public void onCalibration() {
+ vm.onCalibration();
+ this.calibrate = vm.calibrate;
+ }
/**
* Toggles input checking for homography points.
@@ -610,10 +713,10 @@ public void onCalibration() {
*
* @see VidMap#checkInput
*/
- public void toggleInput() {
- vm.checkInput = !vm.checkInput;
- // System.out.println("checkInput = " + vm.checkInput);
- }
+ public void toggleInput() {
+ vm.checkInput = !vm.checkInput;
+ // System.out.println("checkInput = " + vm.checkInput);
+ }
/**
* Checks hover state for homography points at specified coordinates.
@@ -623,9 +726,9 @@ public void toggleInput() {
* @param y The y-coordinate to check
* @see VidMap#checkHover(float, float)
*/
- public void checkHover(float x, float y) {
- vm.checkHover(x, y);
- }
+ public void checkHover(float x, float y) {
+ vm.checkHover(x, y);
+ }
/**
* Moves the hover point to specified coordinates.
@@ -635,9 +738,9 @@ public void checkHover(float x, float y) {
* @param y The target y-coordinate
* @see VidMap#moveHoverPoint(float, float)
*/
- public void moveHoverPoint(float x, float y) {
- vm.moveHoverPoint(x, y);
- }
+ public void moveHoverPoint(float x, float y) {
+ vm.moveHoverPoint(x, y);
+ }
/**
* Handles mouse release events for homography point interaction.
@@ -645,9 +748,9 @@ public void moveHoverPoint(float x, float y) {
*
* @see VidMap#mouseReleased()
*/
- public void mouseReleased() {
- vm.mouseReleased();
- }
+ public void mouseReleased() {
+ vm.mouseReleased();
+ }
/**
* Resets the homography transformation to default state.
@@ -656,10 +759,10 @@ public void mouseReleased() {
* @see VidMap#resetHomography()
* @see #applyAspectRatioCorrection(int, int)
*/
- public void resetHomography() {
- vm.resetHomography();
- applyAspectRatioCorrection(mediaWidth, mediaHeight);
- }
+ public void resetHomography() {
+ vm.resetHomography();
+ applyAspectRatioCorrection(mediaWidth, mediaHeight);
+ }
/**
* Extracts the filename from a full file path.
@@ -667,10 +770,10 @@ public void resetHomography() {
* @param path The full file path
* @return The filename without directory path
*/
- private String extractFileName(String path) {
- File file = new File(path);
- return file.getName();
- }
+ private String extractFileName(String path) {
+ File file = new File(path);
+ return file.getName();
+ }
/**
* Checks if a file is a supported video format.
@@ -679,10 +782,10 @@ private String extractFileName(String path) {
* @param filename The filename to check
* @return true if the file is a supported video format
*/
- private boolean isVideoFile(String filename) {
- filename = filename.toLowerCase();
- return filename.endsWith(".mp4") || filename.endsWith(".avi") || filename.endsWith(".mov");
- }
+ private boolean isVideoFile(String filename) {
+ filename = filename.toLowerCase();
+ return filename.endsWith(".mp4") || filename.endsWith(".avi") || filename.endsWith(".mov");
+ }
/**
* Generates a thumbnail image for this media item.
@@ -694,29 +797,29 @@ private boolean isVideoFile(String filename) {
* @see #thumbnailGenerated
* @see LunaContentGenerator#getGraphics()
*/
- public void generateThumbnail() {
+ public void generateThumbnail() {
if (isGenerative) {
thumbnail = p.createImage(mediaCanvas.width, mediaCanvas.height, PConstants.RGB);
thumbnail.copy(this.generator.getGraphics(), 0, 0, this.generator.getGraphics().width, this.generator.getGraphics().height, 0, 0, thumbnail.width, thumbnail.height);
thumbnail.loadPixels();
thumbnail.resize(150, 100);
} else if (!isVideo) {
- img.loadPixels();
- thumbnail = p.createImage(img.width, img.height, PConstants.RGB);
- thumbnail.copy(img, 0, 0, img.width, img.height, 0, 0, thumbnail.width, thumbnail.height);
- thumbnail.loadPixels();
- thumbnail.resize(150, 100);
- } else if (isVideo && movie != null) {
- // Check if video has pixels available
- movie.loadPixels();
- thumbnail = p.createImage(movie.width, movie.height, PConstants.RGB);
- thumbnail.copy(movie, 0, 0, movie.width, movie.height, 0, 0, thumbnail.width, thumbnail.height);
- thumbnail.loadPixels();
- thumbnail.resize(150, 100);
- // PApplet.println(thumbnail.width);
- }
- thumbnailGenerated = true;
- }
+ img.loadPixels();
+ thumbnail = p.createImage(img.width, img.height, PConstants.RGB);
+ thumbnail.copy(img, 0, 0, img.width, img.height, 0, 0, thumbnail.width, thumbnail.height);
+ thumbnail.loadPixels();
+ thumbnail.resize(150, 100);
+ } else if (isVideo && movie != null) {
+ // Check if video has pixels available
+ movie.loadPixels();
+ thumbnail = p.createImage(movie.width, movie.height, PConstants.RGB);
+ thumbnail.copy(movie, 0, 0, movie.width, movie.height, 0, 0, thumbnail.width, thumbnail.height);
+ thumbnail.loadPixels();
+ thumbnail.resize(150, 100);
+ // PApplet.println(thumbnail.width);
+ }
+ thumbnailGenerated = true;
+ }
/**
* Sets the preview area dimensions for homography point display.
@@ -728,9 +831,9 @@ public void generateThumbnail() {
* @param ph Preview area height
* @see VidMap#setPreviewArea(float, float, float, float)
*/
- public void setPreviewArea(float px, float py, float pw, float ph) {
- vm.setPreviewArea(px, py, pw, ph);
- }
+ public void setPreviewArea(float px, float py, float pw, float ph) {
+ vm.setPreviewArea(px, py, pw, ph);
+ }
/**
* Renders the media with homography transformation.
@@ -745,35 +848,35 @@ public void setPreviewArea(float px, float py, float pw, float ph) {
* @see LunaContentGenerator#getGraphics()
* @see VidMap#render(PGraphics2D)
*/
- public void render() {
- mediaCanvas.beginDraw();
- mediaCanvas.background(0); // Clear previous frame
-
- if (isVideo && movie != null) { // Check for null FIRST
- if (movie.available()) {
- movie.read();
- if (mediaHeight == 0) {
- mediaWidth = movie.width;
- mediaHeight = movie.height;
- if (!loaded)
- applyAspectRatioCorrection(mediaWidth, mediaHeight);
- loaded = true;
- }
- if (movie.time() > 0.5f && !thumbnailGenerated) {
- generateThumbnail();
- //PApplet.println("Video thumbnail generated");
- }
-
- if (movie.time() > (movie.duration()-0.1) && !isLooping) {
+ public void render() {
+ mediaCanvas.beginDraw();
+ mediaCanvas.background(0); // Clear previous frame
+
+ if (isVideo && movie != null) { // Check for null FIRST
+ if (movie.available()) {
+ movie.read();
+ if (mediaHeight == 0) {
+ mediaWidth = movie.width;
+ mediaHeight = movie.height;
+ if (!loaded)
+ applyAspectRatioCorrection(mediaWidth, mediaHeight);
+ loaded = true;
+ }
+ if (movie.time() > 0.5f && !thumbnailGenerated) {
+ generateThumbnail();
+ //PApplet.println("Video thumbnail generated");
+ }
+
+ if (movie.time() > (movie.duration() - 0.1) && !isLooping) {
stopMedia();
//PApplet.println("Video thumbnail generated");
}
- }
+ }
- // Only try to draw if movie is not null
- mediaCanvas.image(movie, 0, 0, mediaCanvas.width, mediaCanvas.height);
+ // Only try to draw if movie is not null
+ mediaCanvas.image(movie, 0, 0, mediaCanvas.width, mediaCanvas.height);
- } else if (isGenerative) {
+ } else if (isGenerative) {
//PApplet.println("Generative");
this.generator.update();
//generator.draw(mediaCanvas,t);
@@ -784,46 +887,46 @@ public void render() {
//PApplet.println("Video thumbnail generated");
}
}
- } else if (!isVideo){
- // Handle non-video or stopped video case
- if (!thumbnailGenerated) {
- generateThumbnail();
- }
- if (img != null) {
- mediaCanvas.image(img, 0, 0, mediaCanvas.width, mediaCanvas.height);
- }
- }
+ } else if (!isVideo) {
+ // Handle non-video or stopped video case
+ if (!thumbnailGenerated) {
+ generateThumbnail();
+ }
+ if (img != null) {
+ mediaCanvas.image(img, 0, 0, mediaCanvas.width, mediaCanvas.height);
+ }
+ }
- mediaCanvas.endDraw();
+ mediaCanvas.endDraw();
- if (vm != null) {
- vm.render(mediaCanvas);
- }
- }
+ if (vm != null) {
+ vm.render(mediaCanvas);
+ }
+ }
/**
* Toggles video playback state.
* Plays if paused, pauses if playing. No effect on static images or generative content.
*/
- public void togglePlayback() {
- if (isVideo) {
- if (movie.isPlaying()) {
- movie.pause();
- } else {
- playMedia();
- }
- }
- }
+ public void togglePlayback() {
+ if (isVideo) {
+ if (movie.isPlaying()) {
+ movie.pause();
+ } else {
+ playMedia();
+ }
+ }
+ }
/**
* Toggles video loop mode.
* Switches between single playback and continuous looping for video content.
*/
- public void toggleLoop() {
- isLooping = !isLooping;
- // System.out.println("isLooping = " + isLooping);
- }
+ public void toggleLoop() {
+ isLooping = !isLooping;
+ // System.out.println("isLooping = " + isLooping);
+ }
/**
* Starts media playback.
@@ -831,14 +934,14 @@ public void toggleLoop() {
* Stops any existing playback before starting new playback.
* No effect on static images or generative content.
*/
- public void playMedia() {
- if (isVideo) {
- stopMedia(); // clean up old one first
- movie = new Movie(p, filePath);
+ public void playMedia() {
+ if (isVideo) {
+ stopMedia(); // clean up old one first
+ movie = new Movie(p, filePath);
movie.play();
isLooping = false;
- }
- }
+ }
+ }
/**
* Starts media playback in loop mode.
@@ -861,49 +964,49 @@ public void loopMedia() {
* Crucial for GStreamer cleanup to release native pipeline resources.
* No effect on static images or generative content.
*/
- public void stopMedia() {
- if (isVideo && movie != null) {
- //PApplet.println("Stop Media");
- movie.stop();
- movie.dispose(); // force GStreamer cleanup. It is crucial to force GStreamer to release the
- // native pipeline before reusing
- movie = null;
- // movie = new Movie(p, filePath);
- mediaCanvas.beginDraw();
- mediaCanvas.clear();
- mediaCanvas.endDraw();
- //PApplet.println("finished Stop Media");
- }
- }
+ public void stopMedia() {
+ if (isVideo && movie != null) {
+ //PApplet.println("Stop Media");
+ movie.stop();
+ movie.dispose(); // force GStreamer cleanup. It is crucial to force GStreamer to release the
+ // native pipeline before reusing
+ movie = null;
+ // movie = new Movie(p, filePath);
+ mediaCanvas.beginDraw();
+ mediaCanvas.clear();
+ mediaCanvas.endDraw();
+ //PApplet.println("finished Stop Media");
+ }
+ }
/**
* Mutes video audio playback.
* Sets video volume to zero if the video is not currently playing.
* No effect on static images or generative content.
*/
- public void muteMedia() {
- if (isVideo && movie != null && !movie.isPlaying()) {
- movie.volume(0);
- }
- }
+ public void muteMedia() {
+ if (isVideo && movie != null && !movie.isPlaying()) {
+ movie.volume(0);
+ }
+ }
/**
* Returns the full file path of the media.
*
* @return The complete file path, or null for generative content
*/
- public String getFilePath() {
- return filePath;
- }
+ public String getFilePath() {
+ return filePath;
+ }
/**
* Returns the filename of the media.
*
* @return The filename without path, or generator name for generative content
*/
- public String getFileName() {
- return fileName;
- }
+ public String getFileName() {
+ return fileName;
+ }
/**
* Returns the thumbnail image for this media item.
@@ -911,18 +1014,18 @@ public String getFileName() {
* @return The thumbnail PImage, or null if not generated
* @see #thumbnailGenerated
*/
- public PImage getThumbnail() {
- return thumbnail;
- }
+ public PImage getThumbnail() {
+ return thumbnail;
+ }
/**
* Checks if this media item is a video file.
*
* @return true if this is a video media item
*/
- public boolean isVideo() {
- return isVideo;
- }
+ public boolean isVideo() {
+ return isVideo;
+ }
/**
* Returns the transformed media canvas with homography applied.
@@ -931,7 +1034,7 @@ public boolean isVideo() {
* @return PGraphics2D containing the transformed media output
* @see VidMap#getMediaCanvas()
*/
- public PGraphics2D getMediaCanvas() {
- return vm.getMediaCanvas();
- }
+ public PGraphics2D getMediaCanvas() {
+ return vm.getMediaCanvas();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/paletai/mapping/Project.java b/src/main/java/paletai/mapping/Project.java
index e3579cd..9e22d6e 100644
--- a/src/main/java/paletai/mapping/Project.java
+++ b/src/main/java/paletai/mapping/Project.java
@@ -88,11 +88,15 @@ public class Project {
int screenButtonsArea = 30;
/** Flags for UI state management */
- boolean addSelectScreenBool = false, removeScreenBol;
+ boolean addSelectScreenBool = false, removeScreenBol = false;
boolean addSceneBool = false, removeSceneBol = false;
/** Preview area dimensions for screen panel */
- float previewAreaX, previewAreaY, previewAreaWidth, previewAreaHeight, previewWidth, previewHeight, previewX, previewY;
+ float previewAreaX, previewAreaY, previewAreaWidth, previewAreaHeight,
+ previewWidth, previewHeight, previewX, previewY;
+
+ /** Flags for Preview show management */
+ boolean showPreview = true;
/** Scene transition management */
private int nextScene = -1;
@@ -195,11 +199,16 @@ void scanMediaFiles() {
File dataDir = new File(mainApplet.sketchPath("data"));
if (dataDir.exists() && dataDir.isDirectory()) {
File[] files = dataDir.listFiles();
- for (File file : files) {
- if (isMediaFile(file.getName())) {
- mediaFiles.add(file.getName());
- }
- }
+ if (files != null) {
+ for (File file : files) {
+ if (isMediaFile(file.getName())) {
+ mediaFiles.add(file.getName());
+ }
+ }
+ } else {
+ // Optional: log a warning
+ PApplet.println("Warning: Could not read files from data directory");
+ }
}
}
@@ -418,7 +427,7 @@ void DelCurScreen() {
// Select the appropriate scene
selectScreen(currentScreen);
- PApplet.println("Delete Screen " + currentScreen);
+ //PApplet.println("Delete Screen " + currentScreen);
}
@@ -564,7 +573,7 @@ void initializeButtons() {
*/
void createAssignDisplayButtons() {
int DisplayButtonX = hx2 - 10 * r;
- int DisplayButtonHeight = 30;
+ int DisplayButtonHeight = 40;
// group container
if (displaysList != null) displaysList.remove();
@@ -650,8 +659,33 @@ void createScreenButtons() {
.disableCollapse();
//.hideBar();
- PFont myFont = mainApplet.createFont("Arial", 14, true);
-
+ PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true);
+ //PFont myFont = mainApplet.createFont("Arial", 14, true);
+
+ // ---- Add Screen button ----
+ Button showBtn = cp5.addButton("Show Screen")
+ .setPosition(hx2 - hx1 - 80 - 4*r, r)
+ .setSize(80, screenButtonsArea) // wider so label fits nicely
+ .setCaptionLabel("toggle Preview")
+ .setGroup(screenList);
+
+ showBtn.getCaptionLabel()
+ .toUpperCase(false)
+ .setFont(myFont)
+ .align(ControlP5.CENTER, ControlP5.CENTER);
+ showBtn.setColorBackground(mainApplet.color(60, 120, 60));
+ showBtn.setColorForeground(mainApplet.color(90, 160, 90));
+ showBtn.setColorActive(mainApplet.color(120, 200, 120));
+ showBtn.setColorLabel(mainApplet.color(255));
+
+ showBtn.addCallback(new CallbackListener() {
+ public void controlEvent(CallbackEvent event) {
+ if (event.getAction() == ControlP5.ACTION_RELEASE) {
+ showPreview = !showPreview;
+ }
+ }
+ });
+
// ---- Add Screen button ----
Button addBtn = cp5.addButton("Add Screen")
.setPosition(r, r)
@@ -676,7 +710,7 @@ public void controlEvent(CallbackEvent event) {
}
});
- // ---- Add Screen button ----
+ // ---- Del Screen button ----
Button delBtn = cp5.addButton("Del Screen")
.setPosition(r+50, r)
.setSize(40, screenButtonsArea) // wider so label fits nicely
@@ -731,10 +765,14 @@ public void controlEvent(CallbackEvent event) {
void addSelectScreenButton(int index) {
// PApplet.println("Entered addSelectScreenButtons");
String optionName = "" + index;
- screenRadio.addItem(optionName, index).setSize(30, 20).setColorActive(mainApplet.color(0, 150, 255))
- .setColorBackground(mainApplet.color(100)).setColorForeground(mainApplet.color(60));
-
- PFont myFont = mainApplet.createFont("Arial", 14, true);
+ screenRadio.addItem(optionName, index)
+ .setSize(30, 20)
+ .setColorActive(mainApplet.color(0, 150, 255))
+ .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);
// Style the new radio button's label
screenRadio.getItem(optionName)
@@ -791,14 +829,16 @@ void createSceneButtons() {
sceneList = cp5.addGroup("Scenes")
.setPosition(r, mainHeight - 8 * r)
.setBackgroundHeight(200)
- .disableCollapse();
+ .disableCollapse().hideBar();
+
// load a font (you could make this global so it’s reused)
- PFont myFont = mainApplet.createFont("Arial", 14, true);
+ //PFont myFont = mainApplet.createFont("Arial", 14, true);
+ PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true);
sceneList.getCaptionLabel()
.setFont(myFont)
.setColor(120)
- .setColorBackground(44);
+ .setColorBackground(44).hide();
// ---- Add Scene button ----
@@ -896,7 +936,9 @@ void addSelectSceneButton(int index) {
Toggle t = sceneRadio.getItem(optionName);
// ---- Styling label ----
- PFont myFont = mainApplet.createFont("Arial", 20, true); // load once globally if you prefer
+ PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 20, true);
+ //PFont myFont = mainApplet.createFont("Arial", 20, true); // load once globally if you prefer
+//
t.getCaptionLabel().setFont(myFont);
t.setColorLabel(mainApplet.color(255)); // label text color (white)
t.getCaptionLabel()
@@ -963,11 +1005,12 @@ void createMediaButtons() {
mediaList.hideBar();
// Load a custom font (adjust name/size to your liking)
- PFont myFont = mainApplet.createFont("Arial", 12, true);
+ PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 16, true);
+ //PFont myFont = mainApplet.createFont("Arial", 12, true);
for (int i = 0; i < mediaFiles.size(); i++) {
String name = mediaFiles.get(i);
- int buttonHeight = 30; // custom height
+ int buttonHeight = 40; // custom height
int buttonWidth = hx1 - 2 * r; // custom width
int buttonY = i * buttonHeight;
@@ -989,6 +1032,7 @@ void createMediaButtons() {
public void controlEvent(CallbackEvent event) {
if (event.getAction() == ControlP5.ACTION_RELEASE) {
addMedia(name);
+ PApplet.println("media " + name + " added");
}
}
});
@@ -1012,11 +1056,13 @@ void createGeneratorButtons() {
.setBackgroundHeight(hy2 - hy1 - 2 * r)
.disableCollapse();
- generatorList.getCaptionLabel().setVisible(false).toUpperCase(false);
+ PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 14, true);
+ generatorList.getCaptionLabel().setFont(myFont).setVisible(false).toUpperCase(false);
generatorList.hideBar();
// Load a custom font (adjust name/size to your liking)
- PFont myFont = mainApplet.createFont("Arial", 12, true);
+ //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);
@@ -1111,11 +1157,13 @@ public void render(int mousex, int mousey) {
* @see #drawTimelinePanel(int)
*/
void drawUI() {
+ PFont myFont = mainApplet.createFont("NeueMachina-Regular.otf", 20, true);
canvaUI.beginDraw();
canvaUI.background(33);
// title
canvaUI.textSize(20);
+ canvaUI.textFont(myFont);
canvaUI.fill(200);
canvaUI.textAlign(PConstants.CENTER, PConstants.CENTER);
canvaUI.text(projectName, (float) mainWidth / 2, (float) hy1 / 2);
@@ -1198,7 +1246,7 @@ void drawStagePanel(int index) {
// Draw (with border)
canvaUI.fill(0);
canvaUI.rect(previewX - 2, previewY - 2, previewWidth + 4, previewHeight + 4);
- canvaUI.image(screen.getScreen(), previewX, previewY, previewWidth, previewHeight);
+ if(showPreview) canvaUI.image(screen.getScreen(), previewX, previewY, previewWidth, previewHeight);
canvaUI.fill(200, 100);
canvaUI.textSize(48);
canvaUI.textAlign(PConstants.CENTER, PConstants.CENTER);
@@ -1268,7 +1316,7 @@ public void keyreleased(char k, int kc) {
// sceneRadio.activate(currentScene);
// selectScene(currentScene);
startTransition(currentScene + 1);
- PApplet.println("Next scene : currentScene + 1");
+ //PApplet.println("Next scene : currentScene + 1");
}
}
diff --git a/src/main/java/paletai/mapping/Scene.java b/src/main/java/paletai/mapping/Scene.java
index 284cd2d..86fa507 100644
--- a/src/main/java/paletai/mapping/Scene.java
+++ b/src/main/java/paletai/mapping/Scene.java
@@ -88,8 +88,12 @@ void setThumbnailPosition(int x, int y) {
void render() {
if (isActive) {
for (MediaItem media : mediaItems) {
- media.render();
+ media.render();
}
+
+ for (int i = 0; i