2020-12-04 20:30:46 +00:00
|
|
|
package sh.ball.gui;
|
2020-11-22 14:39:38 +00:00
|
|
|
|
2021-04-16 17:56:17 +00:00
|
|
|
import sh.ball.MovableRenderer;
|
2020-12-04 20:30:46 +00:00
|
|
|
import sh.ball.audio.AudioPlayer;
|
|
|
|
import sh.ball.audio.FrameProducer;
|
2021-04-16 23:03:43 +00:00
|
|
|
|
2020-11-22 21:07:48 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
2020-11-22 18:03:20 +00:00
|
|
|
import java.net.URL;
|
2020-11-22 21:07:48 +00:00
|
|
|
import java.util.List;
|
2020-11-23 22:56:50 +00:00
|
|
|
import java.util.Map;
|
2020-11-22 18:03:20 +00:00
|
|
|
import java.util.ResourceBundle;
|
2021-04-16 23:03:43 +00:00
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
|
2020-11-24 20:49:30 +00:00
|
|
|
import javafx.beans.InvalidationListener;
|
2020-11-22 18:03:20 +00:00
|
|
|
import javafx.fxml.FXML;
|
|
|
|
import javafx.fxml.Initializable;
|
2020-11-22 21:07:48 +00:00
|
|
|
import javafx.scene.control.Button;
|
2020-11-23 22:56:50 +00:00
|
|
|
import javafx.scene.control.Label;
|
2020-11-22 18:03:20 +00:00
|
|
|
import javafx.scene.control.Slider;
|
2020-11-23 22:56:50 +00:00
|
|
|
import javafx.scene.control.TextField;
|
2020-11-25 21:03:06 +00:00
|
|
|
import javafx.scene.control.TitledPane;
|
2020-11-22 21:07:48 +00:00
|
|
|
import javafx.stage.FileChooser;
|
|
|
|
import javafx.stage.Stage;
|
2021-04-16 23:03:43 +00:00
|
|
|
|
2020-11-22 21:07:48 +00:00
|
|
|
import javax.xml.parsers.ParserConfigurationException;
|
2021-04-16 23:03:43 +00:00
|
|
|
|
2020-11-22 21:07:48 +00:00
|
|
|
import org.xml.sax.SAXException;
|
2021-04-17 11:14:49 +00:00
|
|
|
import sh.ball.engine.Vector3;
|
|
|
|
import sh.ball.parser.obj.ObjFrameSettings;
|
2021-04-16 23:03:43 +00:00
|
|
|
import sh.ball.parser.obj.ObjParser;
|
|
|
|
import sh.ball.parser.ParserFactory;
|
|
|
|
import sh.ball.parser.txt.TextParser;
|
2020-12-04 20:30:46 +00:00
|
|
|
import sh.ball.shapes.Shape;
|
|
|
|
import sh.ball.shapes.Vector2;
|
2020-11-22 18:03:20 +00:00
|
|
|
|
|
|
|
public class Controller implements Initializable {
|
|
|
|
|
2021-04-16 23:03:43 +00:00
|
|
|
private static final String DEFAULT_FILE = TextParser.class.getResource("/models/cube.obj").getPath();
|
2020-11-22 21:07:48 +00:00
|
|
|
|
|
|
|
private final FileChooser fileChooser = new FileChooser();
|
2021-04-16 17:56:17 +00:00
|
|
|
private final MovableRenderer<List<Shape>, Vector2> renderer = new AudioPlayer();
|
2021-04-16 23:03:43 +00:00
|
|
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
|
|
|
|
private FrameProducer<List<Shape>> producer = new FrameProducer<>(
|
|
|
|
renderer,
|
2021-04-17 11:14:49 +00:00
|
|
|
ParserFactory.getParser(DEFAULT_FILE)
|
2021-04-16 23:03:43 +00:00
|
|
|
);
|
2020-11-23 22:56:50 +00:00
|
|
|
|
2020-11-22 21:07:48 +00:00
|
|
|
private Stage stage;
|
|
|
|
|
|
|
|
@FXML
|
2020-11-23 22:56:50 +00:00
|
|
|
private Button chooseFileButton;
|
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Label fileLabel;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private TextField translationXTextField;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private TextField translationYTextField;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Slider weightSlider;
|
2020-11-24 20:49:30 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Label weightLabel;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Slider rotateSpeedSlider;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Label rotateSpeedLabel;
|
2020-11-22 18:03:20 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Slider translationSpeedSlider;
|
2020-11-22 18:03:20 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Label translationSpeedLabel;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Slider scaleSlider;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private Label scaleLabel;
|
2020-11-23 22:56:50 +00:00
|
|
|
@FXML
|
2020-11-25 21:28:37 +00:00
|
|
|
private TitledPane objTitledPane;
|
2020-11-25 21:03:06 +00:00
|
|
|
@FXML
|
2020-11-23 22:56:50 +00:00
|
|
|
private Slider focalLengthSlider;
|
|
|
|
@FXML
|
|
|
|
private Label focalLengthLabel;
|
2020-11-25 21:28:37 +00:00
|
|
|
@FXML
|
|
|
|
private TextField cameraXTextField;
|
|
|
|
@FXML
|
|
|
|
private TextField cameraYTextField;
|
|
|
|
@FXML
|
|
|
|
private TextField cameraZTextField;
|
2020-11-22 18:03:20 +00:00
|
|
|
|
2021-04-16 23:03:43 +00:00
|
|
|
public Controller() throws ParserConfigurationException, SAXException, IOException {
|
|
|
|
}
|
|
|
|
|
2020-11-23 22:56:50 +00:00
|
|
|
private Map<Slider, SliderUpdater<Double>> initializeSliderMap() {
|
|
|
|
return Map.of(
|
2021-04-16 23:03:43 +00:00
|
|
|
weightSlider,
|
|
|
|
new SliderUpdater<>(weightLabel::setText, renderer::setQuality),
|
|
|
|
rotateSpeedSlider,
|
|
|
|
new SliderUpdater<>(rotateSpeedLabel::setText, renderer::setRotationSpeed),
|
|
|
|
translationSpeedSlider,
|
|
|
|
new SliderUpdater<>(translationSpeedLabel::setText, renderer::setTranslationSpeed),
|
|
|
|
scaleSlider,
|
2021-04-17 11:14:49 +00:00
|
|
|
new SliderUpdater<>(scaleLabel::setText, renderer::setScale),
|
|
|
|
focalLengthSlider,
|
|
|
|
new SliderUpdater<>(focalLengthLabel::setText, this::setFocalLength)
|
2020-11-23 22:56:50 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-11-22 18:03:20 +00:00
|
|
|
@Override
|
|
|
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
2020-11-23 22:56:50 +00:00
|
|
|
Map<Slider, SliderUpdater<Double>> sliders = initializeSliderMap();
|
|
|
|
|
|
|
|
for (Slider slider : sliders.keySet()) {
|
|
|
|
slider.valueProperty().addListener((source, oldValue, newValue) ->
|
2021-04-16 23:03:43 +00:00
|
|
|
sliders.get(slider).update(slider.getValue())
|
2020-11-23 22:56:50 +00:00
|
|
|
);
|
|
|
|
}
|
2020-11-22 21:07:48 +00:00
|
|
|
|
2020-11-24 20:49:30 +00:00
|
|
|
InvalidationListener translationUpdate = observable ->
|
2021-04-16 23:03:43 +00:00
|
|
|
renderer.setTranslation(new Vector2(
|
|
|
|
tryParse(translationXTextField.getText()),
|
|
|
|
tryParse(translationYTextField.getText())
|
|
|
|
));
|
2020-11-24 20:49:30 +00:00
|
|
|
|
|
|
|
translationXTextField.textProperty().addListener(translationUpdate);
|
|
|
|
translationYTextField.textProperty().addListener(translationUpdate);
|
|
|
|
|
2021-04-17 11:14:49 +00:00
|
|
|
InvalidationListener cameraPosUpdate = observable ->
|
|
|
|
producer.setFrameSettings(new ObjFrameSettings(new Vector3(
|
|
|
|
tryParse(cameraXTextField.getText()),
|
|
|
|
tryParse(cameraYTextField.getText()),
|
|
|
|
tryParse(cameraZTextField.getText())
|
|
|
|
)));
|
|
|
|
|
|
|
|
cameraXTextField.textProperty().addListener(cameraPosUpdate);
|
|
|
|
cameraYTextField.textProperty().addListener(cameraPosUpdate);
|
|
|
|
cameraZTextField.textProperty().addListener(cameraPosUpdate);
|
2020-11-25 21:28:37 +00:00
|
|
|
|
2020-11-23 22:56:50 +00:00
|
|
|
chooseFileButton.setOnAction(e -> {
|
2021-04-17 11:14:49 +00:00
|
|
|
File file = fileChooser.showOpenDialog(stage);
|
|
|
|
if (file != null) {
|
|
|
|
chooseFile(file);
|
2020-11-24 20:49:30 +00:00
|
|
|
}
|
2020-11-22 21:07:48 +00:00
|
|
|
});
|
|
|
|
|
2021-04-16 23:03:43 +00:00
|
|
|
executor.submit(producer);
|
2021-04-16 17:56:17 +00:00
|
|
|
new Thread(renderer).start();
|
2020-11-22 21:07:48 +00:00
|
|
|
}
|
|
|
|
|
2021-04-17 11:14:49 +00:00
|
|
|
private void setFocalLength(double focalLength) {
|
|
|
|
producer.setFrameSettings(new ObjFrameSettings(focalLength));
|
|
|
|
}
|
|
|
|
|
2020-11-24 20:49:30 +00:00
|
|
|
private double tryParse(String value) {
|
|
|
|
try {
|
|
|
|
return Double.parseDouble(value);
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-25 21:28:37 +00:00
|
|
|
private void chooseFile(File file) {
|
2020-11-25 21:03:06 +00:00
|
|
|
try {
|
2021-04-16 23:03:43 +00:00
|
|
|
producer.stop();
|
2020-11-25 21:28:37 +00:00
|
|
|
String path = file.getAbsolutePath();
|
2021-04-16 23:03:43 +00:00
|
|
|
producer = new FrameProducer<>(
|
|
|
|
renderer,
|
|
|
|
ParserFactory.getParser(path)
|
|
|
|
);
|
|
|
|
executor.submit(producer);
|
|
|
|
|
2020-11-25 21:28:37 +00:00
|
|
|
if (file.exists() && !file.isDirectory()) {
|
|
|
|
fileLabel.setText(path);
|
|
|
|
objTitledPane.setDisable(!ObjParser.isObjFile(path));
|
|
|
|
} else {
|
|
|
|
objTitledPane.setDisable(true);
|
|
|
|
}
|
2020-11-25 21:03:06 +00:00
|
|
|
} catch (IOException | ParserConfigurationException | SAXException ioException) {
|
|
|
|
ioException.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-22 21:07:48 +00:00
|
|
|
public void setStage(Stage stage) {
|
|
|
|
this.stage = stage;
|
2020-11-22 18:03:20 +00:00
|
|
|
}
|
2020-11-22 14:39:38 +00:00
|
|
|
}
|