Add Choose Folder button so multiple files can be opened

pull/35/head
James Ball 2021-07-10 18:38:48 +01:00
rodzic 5084a11313
commit 81e261a27e
3 zmienionych plików z 87 dodań i 27 usunięć

Wyświetl plik

@ -5,6 +5,7 @@ import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.*;
import javafx.stage.DirectoryChooser;
import javafx.util.Duration;
import sh.ball.audio.*;
import sh.ball.audio.effect.*;
@ -14,10 +15,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
@ -47,14 +45,13 @@ import sh.ball.shapes.Vector2;
public class Controller implements Initializable, FrequencyListener, Listener {
private static final InputStream DEFAULT_OBJ = Controller.class.getResourceAsStream("/models/cube.obj");
private final FileChooser fileChooser = new FileChooser();
private final DirectoryChooser folderChooser = new DirectoryChooser();
private final AudioPlayer<List<Shape>> audioPlayer;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final RotateEffect rotateEffect;
private final TranslateEffect translateEffect;
private final WobbleEffect wobbleEffect;
@ -63,9 +60,13 @@ public class Controller implements Initializable, FrequencyListener, Listener {
private int sampleRate;
private FrequencyAnalyser<List<Shape>> analyser;
private final AudioDevice defaultDevice;
private FrameProducer<List<Shape>> producer;
private boolean recording = false;
private FrameProducer<List<Shape>> producer;
private final List<FrameSet<List<Shape>>> frameSets = new ArrayList<>();
private final List<String> frameSetPaths = new ArrayList<>();
private int currentFrameSet;
private Stage stage;
@FXML
@ -73,6 +74,8 @@ public class Controller implements Initializable, FrequencyListener, Listener {
@FXML
private Button chooseFileButton;
@FXML
private Button chooseFolderButton;
@FXML
private Label fileLabel;
@FXML
private Button recordButton;
@ -130,6 +133,8 @@ public class Controller implements Initializable, FrequencyListener, Listener {
public Controller(AudioPlayer<List<Shape>> audioPlayer) throws IOException {
this.audioPlayer = audioPlayer;
FrameSet<List<Shape>> frames = new ObjParser(DEFAULT_OBJ).parse();
frameSets.add(frames);
currentFrameSet = 0;
frames.addListener(this);
this.producer = new FrameProducer<>(audioPlayer, frames);
this.defaultDevice = audioPlayer.getDefaultDevice();
@ -244,6 +249,13 @@ public class Controller implements Initializable, FrequencyListener, Listener {
}
});
chooseFolderButton.setOnAction(e -> {
File file = folderChooser.showDialog(stage);
if (file != null) {
chooseFile(file);
}
});
recordButton.setOnAction(event -> toggleRecord());
updateObjectRotateSpeed();
@ -365,7 +377,9 @@ public class Controller implements Initializable, FrequencyListener, Listener {
}
}
private void changeFrameSet(FrameSet<List<Shape>> frames) {
private void changeFrameSet() {
FrameSet<List<Shape>> frames = frameSets.get(currentFrameSet);
producer.stop();
frames.addListener(this);
producer = new FrameProducer<>(audioPlayer, frames);
@ -380,22 +394,41 @@ public class Controller implements Initializable, FrequencyListener, Listener {
});
Timeline timeline = new Timeline(kf1, kf2);
Platform.runLater(timeline::play);
fileLabel.setText(frameSetPaths.get(currentFrameSet));
objTitledPane.setDisable(!ObjParser.isObjFile(frameSetPaths.get(currentFrameSet)));
}
private void chooseFile(File file) {
private void chooseFile(File chosenFile) {
try {
producer.stop();
String path = file.getAbsolutePath();
changeFrameSet(ParserFactory.getParser(path).parse());
if (chosenFile.exists()) {
String path = chosenFile.getAbsolutePath();
frameSets.clear();
frameSetPaths.clear();
if (file.exists() && !file.isDirectory()) {
fileLabel.setText(path);
objTitledPane.setDisable(!ObjParser.isObjFile(path));
} else {
objTitledPane.setDisable(true);
if (chosenFile.isDirectory()) {
for (File file : chosenFile.listFiles()) {
try {
frameSets.add(ParserFactory.getParser(file.getAbsolutePath()).parse());
frameSetPaths.add(file.getAbsolutePath());
} catch (IOException ignored) {}
}
} else {
frameSets.add(ParserFactory.getParser(path).parse());
frameSetPaths.add(path);
}
currentFrameSet = 0;
changeFrameSet();
}
} catch (IOException | ParserConfigurationException | SAXException ioException) {
ioException.printStackTrace();
// display error to user (for debugging purposes)
String oldPath = fileLabel.getText();
KeyFrame kf1 = new KeyFrame(Duration.seconds(0), e -> fileLabel.setText(ioException.getMessage()));
KeyFrame kf2 = new KeyFrame(Duration.seconds(5), e -> fileLabel.setText(oldPath));
Timeline timeline = new Timeline(kf1, kf2);
Platform.runLater(timeline::play);
}
}
@ -403,6 +436,22 @@ public class Controller implements Initializable, FrequencyListener, Listener {
this.stage = stage;
}
public void nextFrameSet() {
currentFrameSet++;
if (currentFrameSet >= frameSets.size()) {
currentFrameSet = 0;
}
changeFrameSet();
}
public void previousFrameSet() {
currentFrameSet--;
if (currentFrameSet < 0) {
currentFrameSet = frameSets.size() - 1;
}
changeFrameSet();
}
protected boolean mouseRotate() {
return rotateCheckBox.isSelected();
}

Wyświetl plik

@ -33,20 +33,30 @@ public class Gui extends Application {
stage.setTitle("osci-render");
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("/css/main.css").toExternalForm());
scene.addEventHandler(KeyEvent.KEY_PRESSED, (event -> {
switch (event.getCode()) {
case K -> controller.previousFrameSet();
case J -> controller.nextFrameSet();
}
}));
scene.addEventFilter(MouseEvent.MOUSE_MOVED, event -> {
if (controller.mouseRotate()) {
controller.setObjRotate(new Vector3(
3 * Math.PI * (event.getSceneY() / scene.getHeight()),
3 * Math.PI * (event.getSceneX() / scene.getWidth()),
3 * Math.PI * (event.getSceneX() / scene.getWidth()),
0
));
}
});
scene.addEventHandler(KeyEvent.KEY_PRESSED, t -> {
if (t.getCode() == KeyCode.ESCAPE) {
controller.disableMouseRotate();
}
});
stage.setScene(scene);
stage.setResizable(false);

Wyświetl plik

@ -10,18 +10,19 @@
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="498.0" prefWidth="837.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
<AnchorPane id="control-pane" layoutX="422.0" layoutY="10.0" prefHeight="195.0" prefWidth="402.0">
<AnchorPane prefHeight="539.0" prefWidth="837.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
<AnchorPane id="control-pane" layoutX="423.0" layoutY="14.0" prefHeight="232.0" prefWidth="402.0">
<children>
<Button fx:id="chooseFileButton" layoutX="14.0" layoutY="53.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="114.0" text="Choose File" />
<Label fx:id="fileLabel" layoutX="146.0" layoutY="58.0" maxWidth="270.0" prefHeight="18.0" prefWidth="246.0" text="cube.obj" />
<Button fx:id="recordButton" layoutX="14.0" layoutY="93.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="114.0" text="Record" />
<Label fx:id="recordLabel" layoutX="146.0" layoutY="98.0" maxWidth="270.0" prefHeight="18.0" prefWidth="245.0" />
<Label id="frequency" fx:id="frequencyLabel" layoutX="14.0" layoutY="131.0" prefHeight="58.0" prefWidth="376.0" text="L/R Frequency:&#10; &#10;" />
<Label fx:id="fileLabel" layoutX="144.0" layoutY="57.0" maxWidth="270.0" prefHeight="18.0" prefWidth="246.0" text="cube.obj" />
<Button fx:id="recordButton" layoutX="14.0" layoutY="129.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="114.0" text="Record" />
<Label fx:id="recordLabel" layoutX="145.0" layoutY="140.0" maxWidth="270.0" prefHeight="18.0" prefWidth="245.0" />
<Label id="frequency" fx:id="frequencyLabel" layoutX="13.0" layoutY="166.0" prefHeight="58.0" prefWidth="376.0" text="L/R Frequency:&#10; &#10;" />
<ComboBox fx:id="deviceComboBox" layoutX="14.0" layoutY="11.0" prefHeight="26.0" prefWidth="376.0" />
<Button fx:id="chooseFolderButton" layoutX="14.0" layoutY="91.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="114.0" text="Choose Folder" />
</children>
</AnchorPane>
<TitledPane animated="false" collapsible="false" layoutX="422.0" layoutY="213.0" prefHeight="272.0" prefWidth="402.0" text="Effects">
<TitledPane animated="false" collapsible="false" layoutX="423.0" layoutY="252.0" prefHeight="272.0" prefWidth="402.0" text="Effects">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="246.0" prefWidth="442.0">
<children>
@ -39,7 +40,7 @@
</AnchorPane>
</content>
</TitledPane>
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" layoutX="11.0" layoutY="275.0" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="210.0" prefWidth="402.0" text="3D .obj file settings">
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" layoutX="12.0" layoutY="280.0" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="244.0" prefWidth="402.0" text="3D .obj file settings">
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="359.0">
<Slider fx:id="focalLengthSlider" blockIncrement="0.01" layoutX="116.0" layoutY="15.0" majorTickUnit="0.2" max="2.0" min="1.0E-5" prefHeight="38.0" prefWidth="270.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="30.0" layoutY="14.0" text="Focal length" />
@ -55,7 +56,7 @@
<CheckBox fx:id="rotateCheckBox" layoutX="90.0" layoutY="147.0" mnemonicParsing="false" text="Rotate with Mouse (Esc to disable)" />
</AnchorPane>
</TitledPane>
<TitledPane collapsible="false" layoutX="11.0" layoutY="9.0" prefHeight="257.0" prefWidth="402.0" text="Image settings">
<TitledPane collapsible="false" layoutX="12.0" layoutY="14.0" prefHeight="257.0" prefWidth="402.0" text="Image settings">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0">
<Slider fx:id="rotateSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="90.0" majorTickUnit="1.0" max="10.0" prefHeight="38.0" prefWidth="270.0" showTickLabels="true" showTickMarks="true" />