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