From f087635e3157486cb1a534fd514132556228d73d Mon Sep 17 00:00:00 2001 From: James Ball Date: Thu, 16 Dec 2021 18:22:26 +0000 Subject: [PATCH] Save and load rendered files to osci project file --- src/main/java/sh/ball/gui/Controller.java | 91 +++++++++++++++---- .../java/sh/ball/parser/ParserFactory.java | 12 +-- .../java/sh/ball/parser/txt/TextParser.java | 4 + 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/main/java/sh/ball/gui/Controller.java b/src/main/java/sh/ball/gui/Controller.java index 991d0cc..038d0c1 100644 --- a/src/main/java/sh/ball/gui/Controller.java +++ b/src/main/java/sh/ball/gui/Controller.java @@ -13,15 +13,13 @@ import javafx.stage.DirectoryChooser; import javafx.util.Duration; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; import sh.ball.audio.*; import sh.ball.audio.effect.*; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.URL; +import java.nio.file.Files; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.*; @@ -89,6 +87,7 @@ public class Controller implements Initializable, FrequencyListener, MidiListene // frames private static final InputStream DEFAULT_OBJ = Controller.class.getResourceAsStream("/models/cube.obj"); private final ExecutorService executor = Executors.newSingleThreadExecutor(); + private final List openFiles = new ArrayList<>(); private final List frameSourcePaths = new ArrayList<>(); private List>> frameSources = new ArrayList<>(); private FrameProducer> producer; @@ -216,7 +215,15 @@ public class Controller implements Initializable, FrequencyListener, MidiListene new Thread(midiCommunicator).start(); this.audioPlayer = new ShapeAudioPlayer(ConglomerateAudioEngine::new, midiCommunicator); - FrameSource> frames = new ObjParser(DEFAULT_OBJ).parse(); + + // Clone DEFAULT_OBJ InputStream using a ByteArrayOutputStream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + assert DEFAULT_OBJ != null; + DEFAULT_OBJ.transferTo(baos); + InputStream objClone = new ByteArrayInputStream(baos.toByteArray()); + FrameSource> frames = new ObjParser(objClone).parse(); + + openFiles.add(baos.toByteArray()); frameSources.add(frames); frameSourcePaths.add("cube.obj"); currentFrameSource = 0; @@ -620,31 +627,42 @@ public class Controller implements Initializable, FrequencyListener, MidiListene objTitledPane.setDisable(!ObjParser.isObjFile(frameSourcePaths.get(index))); } + private void updateFiles(List files, List names) throws IOException, ParserConfigurationException, SAXException { + List>> oldFrameSources = frameSources; + frameSources = new ArrayList<>(); + frameSourcePaths.clear(); + openFiles.clear(); + jkLabel.setVisible(files.size() > 1); + + for (int i = 0; i < files.size(); i++) { + try { + frameSources.add(ParserFactory.getParser(names.get(i), files.get(i)).parse()); + frameSourcePaths.add(names.get(i)); + openFiles.add(files.get(i)); + } catch (IOException ignored) {} + } + + oldFrameSources.forEach(FrameSource::disable); + changeFrameSource(0); + } + // selects a new file or folder for files to be rendered from private void chooseFile(File chosenFile) { try { if (chosenFile.exists()) { - List>> oldFrameSources = frameSources; - frameSources = new ArrayList<>(); - frameSourcePaths.clear(); - + List files = new ArrayList<>(); + List names = new ArrayList<>(); if (chosenFile.isDirectory()) { - jkLabel.setVisible(true); for (File file : Objects.requireNonNull(chosenFile.listFiles())) { - try { - frameSources.add(ParserFactory.getParser(file.getAbsolutePath()).parse()); - frameSourcePaths.add(file.getName()); - } catch (IOException ignored) { - } + files.add(Files.readAllBytes(file.toPath())); + names.add(file.getName()); } } else { - jkLabel.setVisible(false); - frameSources.add(ParserFactory.getParser(chosenFile.getAbsolutePath()).parse()); - frameSourcePaths.add(chosenFile.getName()); + files.add(Files.readAllBytes(chosenFile.toPath())); + names.add(chosenFile.getName()); } - oldFrameSources.forEach(FrameSource::disable); - changeFrameSource(0); + updateFiles(files, names); } } catch (IOException | ParserConfigurationException | SAXException ioException) { ioException.printStackTrace(); @@ -668,6 +686,9 @@ public class Controller implements Initializable, FrequencyListener, MidiListene // increments and changes the frameSource after pressing 'j' public void nextFrameSet() { + if (frameSources.size() == 1) { + return; + } int index = currentFrameSource + 1; if (index >= frameSources.size()) { index = 0; @@ -677,6 +698,9 @@ public class Controller implements Initializable, FrequencyListener, MidiListene // decrements and changes the frameSource after pressing 'k' public void previousFrameSource() { + if (frameSources.size() == 1) { + return; + } int index = currentFrameSource - 1; if (index < 0) { index = frameSources.size() - 1; @@ -880,6 +904,20 @@ public class Controller implements Initializable, FrequencyListener, MidiListene objectRotationElement.appendChild(objectRotationZElement); root.appendChild(objectRotationElement); + Element filesElement = document.createElement("files"); + for (int i = 0; i < openFiles.size(); i++) { + Element fileElement = document.createElement("file"); + Element fileNameElement = document.createElement("name"); + fileNameElement.appendChild(document.createTextNode(frameSourcePaths.get(i))); + Element dataElement = document.createElement("data"); + String encodedData = Base64.getEncoder().encodeToString(openFiles.get(i)); + dataElement.appendChild(document.createTextNode(encodedData)); + fileElement.appendChild(fileNameElement); + fileElement.appendChild(dataElement); + filesElement.appendChild(fileElement); + } + root.appendChild(filesElement); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource domSource = new DOMSource(document); @@ -958,6 +996,19 @@ public class Controller implements Initializable, FrequencyListener, MidiListene Double.parseDouble(objectRotationZElement.getTextContent()) ); setObjRotate(rotation); + + Element filesElement = (Element) root.getElementsByTagName("files").item(0); + List files = new ArrayList<>(); + List fileNames = new ArrayList<>(); + NodeList fileElements = filesElement.getElementsByTagName("file"); + for (int i = 0; i < fileElements.getLength(); i++) { + Element fileElement = (Element) fileElements.item(i); + String fileData = fileElement.getElementsByTagName("data").item(0).getTextContent(); + files.add(Base64.getDecoder().decode(fileData)); + String fileName = fileElement.getElementsByTagName("name").item(0).getTextContent(); + fileNames.add(fileName); + } + updateFiles(files, fileNames); } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } diff --git a/src/main/java/sh/ball/parser/ParserFactory.java b/src/main/java/sh/ball/parser/ParserFactory.java index ff7cd7e..b1da0d8 100644 --- a/src/main/java/sh/ball/parser/ParserFactory.java +++ b/src/main/java/sh/ball/parser/ParserFactory.java @@ -1,26 +1,26 @@ package sh.ball.parser; -import org.xml.sax.SAXException; import sh.ball.audio.FrameSource; import sh.ball.parser.obj.ObjParser; import sh.ball.parser.svg.SvgParser; import sh.ball.parser.txt.TextParser; import sh.ball.shapes.Shape; -import javax.xml.parsers.ParserConfigurationException; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.util.List; public class ParserFactory { - public static FileParser>> getParser(String filePath) throws IOException, ParserConfigurationException, SAXException { + public static FileParser>> getParser(String filePath, byte[] fileData) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(fileData); if (ObjParser.isObjFile(filePath)) { - return new ObjParser(filePath); + return new ObjParser(bais); } else if (SvgParser.isSvgFile(filePath)) { - return new SvgParser(filePath); + return new SvgParser(bais); } else if (TextParser.isTxtFile(filePath)) { - return new TextParser(filePath); + return new TextParser(bais); } throw new IOException("No known parser that can parse " + new File(filePath).getName()); } diff --git a/src/main/java/sh/ball/parser/txt/TextParser.java b/src/main/java/sh/ball/parser/txt/TextParser.java index 8d817e6..4a151b6 100644 --- a/src/main/java/sh/ball/parser/txt/TextParser.java +++ b/src/main/java/sh/ball/parser/txt/TextParser.java @@ -33,6 +33,10 @@ public class TextParser extends FileParser>> { this.charToShape = new HashMap<>(); } + public TextParser(InputStream input) { + this(input, TextParser.class.getResourceAsStream(DEFAULT_FONT)); + } + public TextParser(String path) throws FileNotFoundException { this(new FileInputStream(path), TextParser.class.getResourceAsStream(DEFAULT_FONT)); checkFileExtension(path);