Fix merge conflicts with master

pull/53/head
James Ball 2022-03-25 17:12:41 +00:00
commit 000f7a2154
11 zmienionych plików z 314 dodań i 132 usunięć

Wyświetl plik

@ -6,7 +6,7 @@
<groupId>sh.ball</groupId>
<artifactId>osci-render</artifactId>
<version>1.19.3</version>
<version>1.20.3</version>
<name>osci-render</name>

Wyświetl plik

@ -4,11 +4,11 @@ import java.util.Objects;
public class MidiNote {
public static double MAX_VELOCITY = 127;
public static short MAX_CC = 0x78;
public static short MAX_CHANNEL = 15;
public static short NUM_CHANNELS = (short) (MAX_CHANNEL + 1);
public static short ALL_NOTES_OFF = 0x7B;
public static final int MAX_VELOCITY = 127;
public static final short MAX_CC = 0x78;
public static final short MAX_CHANNEL = 15;
public static final short NUM_CHANNELS = (short) (MAX_CHANNEL + 1);
public static final short ALL_NOTES_OFF = 0x7B;
public static final double MIDDLE_C = 261.6255798;
public static final int PITCH_BEND_DATA_LENGTH = 7;
public static final int PITCH_BEND_MAX = 16383;

Wyświetl plik

@ -65,12 +65,7 @@ public class Gui extends Application {
scene.addEventFilter(MouseEvent.MOUSE_MOVED, event -> {
if (controller.mouseRotate()) {
Vector3 rotate = new Vector3(
3 * Math.PI * (event.getSceneY() / scene.getHeight()),
3 * Math.PI * (event.getSceneX() / scene.getWidth()),
0
);
controller.setObjRotate(rotate, rotate);
controller.setMouseXY(event.getSceneX() / scene.getWidth(), event.getSceneY() / scene.getHeight());
}
if (controller.mouseTranslate()) {
controller.setTranslation(new Vector2(

Wyświetl plik

@ -19,10 +19,7 @@ import sh.ball.audio.midi.MidiNote;
import sh.ball.shapes.Vector2;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.function.Consumer;
@ -34,13 +31,14 @@ public class ImageController implements Initializable, SubController {
private static final double MAX_FREQUENCY = 12000;
private static final int DEFAULT_SAMPLE_RATE = 192000;
private static final double SCROLL_DELTA = 0.05;
private final RotateEffect rotateEffect;
private final TranslateEffect translateEffect;
private final DoubleProperty frequency;
private double scrollDelta = 0.05;
@FXML
private TextField translationXTextField;
@FXML
@ -87,6 +85,8 @@ public class ImageController implements Initializable, SubController {
private CheckBox visibilityMic;
@FXML
private Button resetRotationButton;
@FXML
private Button resetTranslationButton;
public ImageController() {
this.frequency = new SimpleDoubleProperty(0);
@ -105,6 +105,10 @@ public class ImageController implements Initializable, SubController {
translationYTextField.setText(MainController.FORMAT.format(translation.getY()));
}
public void setTranslationIncrement(double increment) {
this.scrollDelta = increment;
}
// changes the sinusoidal translation of the image rendered
private void updateTranslation() {
translateEffect.setTranslation(new Vector2(
@ -115,7 +119,7 @@ public class ImageController implements Initializable, SubController {
private void changeTranslation(boolean increase, TextField field) {
double old = tryParse(field.getText());
double delta = increase ? SCROLL_DELTA : -SCROLL_DELTA;
double delta = increase ? scrollDelta : -scrollDelta;
field.setText(MainController.FORMAT.format(old + delta));
}
@ -144,6 +148,10 @@ public class ImageController implements Initializable, SubController {
);
resetRotationButton.setOnAction(e -> rotateEffect.resetTheta());
resetTranslationButton.setOnAction(e -> {
translationXTextField.setText("0.00");
translationYTextField.setText("0.00");
});
translationXTextField.textProperty().addListener(e -> updateTranslation());
translationXTextField.setOnScroll((e) -> changeTranslation(e.getDeltaY() > 0, translationXTextField));

Wyświetl plik

@ -79,6 +79,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
private Paint armedMidiPaint;
private SVGPath armedMidi;
private Map<SVGPath, Slider> midiButtonMap;
private final Map<Slider, Short> channelClosestToZero = new HashMap<>();
private int midiDeadzone = 5;
// frames
private static final InputStream DEFAULT_OBJ = MainController.class.getResourceAsStream("/models/cube.obj");
@ -122,11 +124,15 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
@FXML
private Spinner<Integer> midiChannelSpinner;
@FXML
private Spinner<Double> translationIncrementSpinner;
@FXML
private ComboBox<PrintableSlider> sliderComboBox;
@FXML
private TextField sliderMinTextField;
@FXML
private TextField sliderMaxTextField;
@FXML
private Spinner<Integer> deadzoneSpinner;
public MainController() throws Exception {
// Clone DEFAULT_OBJ InputStream using a ByteArrayOutputStream
@ -164,22 +170,39 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
slider.setMajorTickUnit(Math.max(sh.ball.math.Math.EPSILON, MAJOR_TICK_UNIT * (slider.getMax() - slider.getMin())));
}
private void updateClosestChannelToZero(Slider slider) {
short closestToZero = 0;
double closestValue = Double.MAX_VALUE;
for (short i = 0; i <= MidiNote.MAX_VELOCITY; i++) {
double value = getValueInSliderRange(slider, i / (float) MidiNote.MAX_VELOCITY);
if (Math.abs(value) < closestValue) {
closestValue = Math.abs(value);
closestToZero = i;
}
}
System.out.println(closestToZero);
channelClosestToZero.put(slider, closestToZero);
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
List<Slider> sliders = sliders();
List<CheckBox> micCheckBoxes = micCheckBoxes();
targetSliderValue = new double[sliders.size()];
for (int i = 0; i < sliders.size(); i++) {
updateClosestChannelToZero(sliders.get(i));
targetSliderValue[i] = sliders.get(i).getValue();
int finalI = i;
if (micCheckBoxes.get(i) != null) {
CheckBox checkBox = micCheckBoxes.get(i);
int finalI = i;
sliders.get(i).valueProperty().addListener((e, old, value) -> {
if (!checkBox.isSelected()) {
targetSliderValue[finalI] = value.doubleValue();
}
});
}
sliders.get(i).minProperty().addListener(e -> updateClosestChannelToZero(sliders.get(finalI)));
sliders.get(i).maxProperty().addListener(e -> updateClosestChannelToZero(sliders.get(finalI)));
}
objController.setAudioProducer(producer);
@ -187,22 +210,24 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
this.midiButtonMap = initializeMidiButtonMap();
midiButtonMap.keySet().forEach(midi -> midi.setOnMouseClicked(e -> {
if (armedMidi == midi) {
// we are already armed, so we should unarm
midi.setFill(armedMidiPaint);
armedMidiPaint = null;
armedMidi = null;
} else {
// not yet armed
if (armedMidi != null) {
armedMidi.setFill(armedMidiPaint);
midiButtonMap.keySet().forEach(midi -> {
midi.setOnMouseClicked(e -> {
if (armedMidi == midi) {
// we are already armed, so we should unarm
midi.setFill(armedMidiPaint);
armedMidiPaint = null;
armedMidi = null;
} else {
// not yet armed
if (armedMidi != null) {
armedMidi.setFill(armedMidiPaint);
}
armedMidiPaint = midi.getFill();
armedMidi = midi;
midi.setFill(Color.RED);
}
armedMidiPaint = midi.getFill();
armedMidi = midi;
midi.setFill(Color.RED);
}
}));
});
});
osciFileChooser.setInitialFileName("project.osci");
osciFileChooser.getExtensionFilters().add(
@ -263,6 +288,12 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
midiChannelSpinner.getEditor().setTextFormatter(new TextFormatter<>(new IntegerStringConverter(), 0, filter));
midiChannelSpinner.valueProperty().addListener((o, oldValue, newValue) -> audioPlayer.setMainMidiChannel(newValue));
translationIncrementSpinner.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(-2, 2, 0.05, 0.01));
translationIncrementSpinner.valueProperty().addListener((o, oldValue, newValue) -> imageController.setTranslationIncrement(newValue));
deadzoneSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 20, 5));
deadzoneSpinner.valueProperty().addListener((e, old, deadzone) -> this.midiDeadzone = deadzone);
List<PrintableSlider> printableSliders = new ArrayList<>();
sliders.forEach(slider -> printableSliders.add(new PrintableSlider(slider)));
sliderComboBox.setItems(FXCollections.observableList(printableSliders));
@ -373,7 +404,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
objController.updateObjectRotateSpeed();
objController.updateFocalLength();
if (oldSettings instanceof ObjFrameSettings settings) {
setObjRotate(settings.baseRotation, settings.currentRotation);
objController.setObjRotate(settings.baseRotation, settings.currentRotation);
}
executor.submit(producer);
effectsController.restartEffects();
@ -469,8 +500,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
}
// updates the 3D object base and current rotation angle
public void setObjRotate(Vector3 baseRotation, Vector3 currentRotation) {
objController.setObjRotate(baseRotation, currentRotation);
public void setMouseXY(double mouseX, double mouseY) {
objController.setRotateXY(new Vector2(mouseX, mouseY));
}
@Override
@ -527,8 +558,26 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
if (cc <= MidiNote.MAX_CC && CCMap.containsKey(cc)) {
Platform.runLater(() -> {
Slider slider = midiButtonMap.get(CCMap.get(cc));
double sliderValue = getValueInSliderRange(slider, value / MidiNote.MAX_VELOCITY);
slider.setValue(sliderValue);
short closestToZero = channelClosestToZero.get(slider);
double sliderValue = getValueInSliderRange(slider, value / (float) MidiNote.MAX_VELOCITY);
// deadzone
if (value >= closestToZero - midiDeadzone && value <= closestToZero + midiDeadzone && sliderValue < 1) {
slider.setValue(0);
} else {
int leftDeadzone = Math.min(closestToZero, midiDeadzone);
int rightDeadzone = Math.min(MidiNote.MAX_VELOCITY - closestToZero, midiDeadzone);
int actualChannels = MidiNote.MAX_VELOCITY - (leftDeadzone + 1 + rightDeadzone);
int correctedValue;
if (value > closestToZero) {
correctedValue = value - midiDeadzone;
} else {
correctedValue = value + midiDeadzone;
}
double scale = MidiNote.MAX_VELOCITY / (double) actualChannels;
double zeroPoint = closestToZero / (double) MidiNote.MAX_VELOCITY;
slider.setValue(getValueInSliderRange(slider, scale * ((correctedValue / (double) MidiNote.MAX_VELOCITY) - zeroPoint) + zeroPoint));
}
});
} else if (cc == MidiNote.ALL_NOTES_OFF) {
audioPlayer.stopMidiNotes();
@ -670,6 +719,14 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
root.appendChild(flipX);
root.appendChild(flipY);
Element translationIncrement = document.createElement("translationIncrement");
translationIncrement.appendChild(document.createTextNode(translationIncrementSpinner.getValue().toString()));
root.appendChild(translationIncrement);
Element deadzone = document.createElement("deadzone");
deadzone.appendChild(document.createTextNode(deadzoneSpinner.getValue().toString()));
root.appendChild(deadzone);
Element filesElement = document.createElement("files");
for (int i = 0; i < openFiles.size(); i++) {
Element fileElement = document.createElement("file");
@ -758,6 +815,16 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
flipYCheckMenuItem.setSelected(Boolean.parseBoolean(flipY.getTextContent()));
}
Element translationIncrement = (Element) root.getElementsByTagName("translationIncrement").item(0);
if (translationIncrement != null) {
translationIncrementSpinner.getValueFactory().setValue(Double.parseDouble(translationIncrement.getTextContent()));
}
Element deadzone = (Element) root.getElementsByTagName("deadzone").item(0);
if (deadzone != null) {
deadzoneSpinner.getValueFactory().setValue(Integer.parseInt(deadzone.getTextContent()));
}
Element filesElement = (Element) root.getElementsByTagName("files").item(0);
List<byte[]> files = new ArrayList<>();
List<String> fileNames = new ArrayList<>();
@ -816,7 +883,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
if (checkBoxes.get(i) != null) {
if (checkBoxes.get(i).isSelected()) {
Slider slider = sliders.get(i);
double sliderValue = targetSliderValue[i] + getValueInSliderRange(slider, finalVolume);
double sliderValue = targetSliderValue[i] + (slider.getMax() - slider.getMin()) * finalVolume;
if (sliderValue > slider.getMax()) {
sliderValue = slider.getMax();
} else if (sliderValue < slider.getMin()) {

Wyświetl plik

@ -1,5 +1,6 @@
package sh.ball.gui.controller;
import javafx.beans.InvalidationListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
@ -12,13 +13,13 @@ import sh.ball.audio.FrameProducer;
import sh.ball.engine.Vector3;
import sh.ball.parser.obj.ObjSettingsFactory;
import sh.ball.shapes.Shape;
import sh.ball.shapes.Vector2;
import java.net.URL;
import java.util.*;
public class ObjController implements Initializable, SubController {
private Vector3 rotation = new Vector3(2 * Math.PI, 2 * Math.PI, 0);
private FrameProducer<List<Shape>> producer;
@FXML
@ -26,6 +27,24 @@ public class ObjController implements Initializable, SubController {
@FXML
private SVGPath focalLengthMidi;
@FXML
private Slider objectXRotateSlider;
@FXML
private SVGPath objectXRotateMidi;
@FXML
private CheckBox objectXRotateMic;
@FXML
private Slider objectYRotateSlider;
@FXML
private SVGPath objectYRotateMidi;
@FXML
private CheckBox objectYRotateMic;
@FXML
private Slider objectZRotateSlider;
@FXML
private SVGPath objectZRotateMidi;
@FXML
private CheckBox objectZRotateMic;
@FXML
private Slider objectRotateSpeedSlider;
@FXML
private SVGPath objectRotateSpeedMidi;
@ -40,6 +59,9 @@ public class ObjController implements Initializable, SubController {
public Map<SVGPath, Slider> getMidiButtonMap() {
return Map.of(
focalLengthMidi, focalLengthSlider,
objectXRotateMidi, objectXRotateSlider,
objectYRotateMidi, objectYRotateSlider,
objectZRotateMidi, objectZRotateSlider,
objectRotateSpeedMidi, objectRotateSpeedSlider
);
}
@ -61,14 +83,23 @@ public class ObjController implements Initializable, SubController {
setObjectRotateSpeed(objectRotateSpeedSlider.getValue());
}
private double linearSpeedToActualSpeed(double rotateSpeed) {
return (Math.exp(3 * Math.min(10, Math.abs(rotateSpeed))) - 1) / 50;
}
// changes the rotateSpeed of the FrameProducer
public void setObjectRotateSpeed(double rotateSpeed) {
double actualSpeed = (Math.exp(3 * Math.min(10, Math.abs(rotateSpeed))) - 1) / 50;
private void setObjectRotateSpeed(double rotateSpeed) {
double actualSpeed = linearSpeedToActualSpeed(rotateSpeed);
producer.setFrameSettings(
ObjSettingsFactory.rotateSpeed(rotateSpeed > 0 ? actualSpeed : -actualSpeed)
);
}
public void setRotateXY(Vector2 rotate) {
objectXRotateSlider.setValue(rotate.getX());
objectYRotateSlider.setValue(rotate.getY());
}
// determines whether the mouse is being used to rotate a 3D object
public boolean mouseRotate() {
return rotateCheckBox.isSelected();
@ -81,8 +112,7 @@ public class ObjController implements Initializable, SubController {
}
// updates the 3D object base rotation angle
public void setObjRotate(Vector3 vector) {
rotation = vector;
private void setObjRotate(Vector3 vector) {
producer.setFrameSettings(ObjSettingsFactory.baseRotation(vector));
}
@ -96,56 +126,57 @@ public class ObjController implements Initializable, SubController {
focalLengthSlider.valueProperty().addListener((source, oldValue, newValue) ->
setFocalLength(newValue.doubleValue())
);
objectRotateSpeedSlider.valueProperty().addListener((source, oldValue, newValue) ->
setObjectRotateSpeed(newValue.doubleValue())
);
resetObjectRotationButton.setOnAction(e -> setObjRotate(new Vector3(2 * Math.PI, 2 * Math.PI, 0), new Vector3()));
InvalidationListener rotateSpeedListener = e -> setObjRotate(new Vector3(
objectXRotateSlider.getValue() * Math.PI,
objectYRotateSlider.getValue() * Math.PI,
objectZRotateSlider.getValue() * Math.PI
));
objectXRotateSlider.valueProperty().addListener(rotateSpeedListener);
objectYRotateSlider.valueProperty().addListener(rotateSpeedListener);
objectZRotateSlider.valueProperty().addListener(rotateSpeedListener);
resetObjectRotationButton.setOnAction(e -> {
objectXRotateSlider.setValue(0);
objectYRotateSlider.setValue(0);
objectZRotateSlider.setValue(0);
objectRotateSpeedSlider.setValue(0);
setObjRotate(new Vector3(), new Vector3());
});
objectRotateSpeedSlider.valueProperty().addListener((e, old, speed) -> {
setObjectRotateSpeed(speed.doubleValue());
});
}
@Override
public List<CheckBox> micCheckBoxes() {
List<CheckBox> checkboxes = new ArrayList<>();
checkboxes.add(null);
checkboxes.add(objectXRotateMic);
checkboxes.add(objectYRotateMic);
checkboxes.add(objectZRotateMic);
checkboxes.add(objectRotateSpeedMic);
return checkboxes;
}
@Override
public List<Slider> sliders() {
return List.of(focalLengthSlider, objectRotateSpeedSlider);
return List.of(focalLengthSlider, objectXRotateSlider, objectYRotateSlider,
objectZRotateSlider, objectRotateSpeedSlider);
}
@Override
public List<String> labels() {
return List.of("focalLength", "objectRotateSpeed");
return List.of("focalLength", "objectXRotate", "objectYRotate", "objectZRotate",
"objectRotateSpeed");
}
@Override
public Element save(Document document) {
Element element = document.createElement("objectRotation");
Element x = document.createElement("x");
x.appendChild(document.createTextNode(Double.toString(rotation.x)));
Element y = document.createElement("y");
y.appendChild(document.createTextNode(Double.toString(rotation.y)));
Element z = document.createElement("z");
z.appendChild(document.createTextNode(Double.toString(rotation.z)));
element.appendChild(x);
element.appendChild(y);
element.appendChild(z);
return element;
return document.createElement("null");
}
@Override
public void load(Element root) {
Element element = (Element) root.getElementsByTagName("objectRotation").item(0);
Element x = (Element) element.getElementsByTagName("x").item(0);
Element y = (Element) element.getElementsByTagName("y").item(0);
Element z = (Element) element.getElementsByTagName("z").item(0);
rotation = new Vector3(
Double.parseDouble(x.getTextContent()),
Double.parseDouble(y.getTextContent()),
Double.parseDouble(z.getTextContent())
);
setObjRotate(rotation);
}
}

Wyświetl plik

@ -13,7 +13,7 @@ public class ObjFrameSource implements FrameSource<List<Shape>> {
private final WorldObject object;
private final Camera camera;
private Vector3 baseRotation = new Vector3(2 * Math.PI, 2 * Math.PI, 0);
private Vector3 baseRotation = new Vector3(Math.PI, Math.PI, 0);
private Vector3 currentRotation = baseRotation;
private Double rotateSpeed = 0.0;
private boolean active = true;
@ -26,7 +26,7 @@ public class ObjFrameSource implements FrameSource<List<Shape>> {
@Override
public List<Shape> next() {
currentRotation = currentRotation.add(baseRotation.scale(rotateSpeed));
object.setRotation(currentRotation);
object.setRotation(baseRotation.add(currentRotation));
return camera.draw(object);
}

Wyświetl plik

@ -288,4 +288,32 @@
/*** The context menu that contains a menu's menu items ***/
.context-menu {
-fx-background-color: -fx-my-menu-color;
}
.spinner .increment-arrow-button {
-fx-border-width: 1px 1px 0 0;
-fx-border-color: white;
}
.spinner .decrement-arrow-button {
-fx-border-width: 0 1px 1px 0;
-fx-border-color: white;
}
.spinner .increment-arrow-button,
.spinner .decrement-arrow-button {
-fx-background-color: very_dark;
-fx-background-radius: 0;
}
.spinner .increment-arrow-button:hover,
.spinner .decrement-arrow-button:hover {
-fx-background-color: grey_color;
}
.spinner .increment-arrow-button:hover:pressed,
.spinner .decrement-arrow-button:hover:pressed,
.spinner .increment-arrow-button:pressed,
.spinner .decrement-arrow-button:pressed {
-fx-background-color: white;
}
.spinner .increment-arrow-button .increment-arrow,
.spinner .decrement-arrow-button .decrement-arrow {
-fx-background-color: white;
}

Wyświetl plik

@ -12,25 +12,25 @@
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="329.0" prefWidth="576.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.controller.ImageController">
<children>
<CheckBox fx:id="translateEllipseCheckBox" layoutX="324.0" layoutY="19.0" mnemonicParsing="false" text="Ellipse" />
<Slider fx:id="rotateSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="159.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" />
<Label layoutX="12.0" layoutY="158.0" text="2D Rotate speed">
<Slider fx:id="rotateSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="199.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" />
<Label layoutX="12.0" layoutY="198.0" text="2D Rotate speed">
<font>
<Font size="13.0" />
</font>
</Label>
<Slider fx:id="translationSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="197.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="7.0" layoutY="196.0" text="Translation speed">
<Slider fx:id="translationSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="123.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="7.0" layoutY="122.0" text="Translation speed">
<font>
<Font size="13.0" />
</font>
</Label>
<Slider fx:id="volumeSlider" blockIncrement="0.05" layoutX="116.0" layoutY="236.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="253.0" showTickLabels="true" showTickMarks="true" value="3.0" />
<Label layoutX="33.0" layoutY="235.0" text="Volume scale">
<Slider fx:id="volumeSlider" blockIncrement="0.05" layoutX="116.0" layoutY="237.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="253.0" showTickLabels="true" showTickMarks="true" value="3.0" />
<Label layoutX="33.0" layoutY="236.0" text="Volume scale">
<font>
<Font size="13.0" />
</font>
</Label>
<Label layoutX="11.0" layoutY="119.0" text="Target frequency">
<Label layoutX="11.0" layoutY="160.0" text="Target frequency">
<font>
<Font size="13.0" />
</font>
@ -40,25 +40,21 @@
<Label layoutX="120.0" layoutY="18.0" text="x :" />
<Label layoutX="222.0" layoutY="18.0" text="y :" />
<TextField fx:id="translationYTextField" layoutX="241.0" layoutY="15.0" prefHeight="26.0" prefWidth="69.0" text="0.0" />
<Slider fx:id="frequencySlider" blockIncrement="0.001" layoutX="116.0" layoutY="114.0" majorTickUnit="0.07389" max="1.0" minorTickCount="2" prefHeight="42.0" prefWidth="253.0" showTickMarks="true" value="0.59269" />
<SVGPath fx:id="frequencyMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="118.0" pickOnBounds="true" />
<SVGPath fx:id="rotateSpeedMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="156.0" pickOnBounds="true" />
<SVGPath fx:id="translationSpeedMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="194.0" pickOnBounds="true" />
<SVGPath fx:id="volumeMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="233.0" pickOnBounds="true" />
<Label layoutX="257.0" layoutY="140.0" text="C4" />
<Label layoutX="239.0" layoutY="140.0" text="C3" />
<Label layoutX="222.0" layoutY="140.0" text="C2" />
<Label layoutX="193.0" layoutY="140.0" text="20" />
<Label layoutX="274.0" layoutY="140.0" text="C5" />
<Label layoutX="292.0" layoutY="140.0" text="C6" />
<Label layoutX="310.0" layoutY="140.0" text="C7" />
<Label layoutX="344.0" layoutY="140.0" text="12000">
<font>
<Font size="11.0" />
</font>
</Label>
<Label layoutX="162.0" layoutY="140.0" text="5" />
<Label layoutX="122.0" layoutY="140.0" text="0" />
<Slider fx:id="frequencySlider" blockIncrement="0.001" layoutX="116.0" layoutY="155.0" majorTickUnit="0.07389" max="1.0" minorTickCount="2" prefHeight="42.0" prefWidth="253.0" showTickMarks="true" value="0.59269" />
<SVGPath fx:id="frequencyMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="159.0" pickOnBounds="true" />
<SVGPath fx:id="rotateSpeedMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="196.0" pickOnBounds="true" />
<SVGPath fx:id="translationSpeedMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="120.0" pickOnBounds="true" />
<SVGPath fx:id="volumeMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="371.0" layoutY="234.0" pickOnBounds="true" />
<Label layoutX="257.0" layoutY="181.0" text="C4" />
<Label layoutX="239.0" layoutY="181.0" text="C3" />
<Label layoutX="222.0" layoutY="181.0" text="C2" />
<Label layoutX="193.0" layoutY="181.0" text="20" />
<Label layoutX="274.0" layoutY="181.0" text="C5" />
<Label layoutX="292.0" layoutY="181.0" text="C6" />
<Label layoutX="310.0" layoutY="181.0" text="C7" />
<Label layoutX="345.0" layoutY="181.0" text="12000" />
<Label layoutX="162.0" layoutY="181.0" text="5" />
<Label layoutX="122.0" layoutY="181.0" text="0" />
<Label layoutX="24.0" layoutY="275.0" text="Image visibility">
<font>
<Font size="13.0" />
@ -75,11 +71,12 @@
</Label>
<SVGPath fx:id="translationScaleMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="370.0" layoutY="80.0" pickOnBounds="true" />
<CheckBox fx:id="translationScaleMic" layoutX="408.0" layoutY="83.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="frequencyMic" layoutX="408.0" layoutY="121.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="rotateSpeedMic" layoutX="408.0" layoutY="159.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="translationSpeedMic" layoutX="408.0" layoutY="197.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="volumeMic" layoutX="408.0" layoutY="236.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="frequencyMic" layoutX="408.0" layoutY="162.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="rotateSpeedMic" layoutX="408.0" layoutY="199.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="translationSpeedMic" layoutX="408.0" layoutY="123.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="volumeMic" layoutX="408.0" layoutY="237.0" mnemonicParsing="false" text="Mic" />
<CheckBox fx:id="visibilityMic" layoutX="408.0" layoutY="276.0" mnemonicParsing="false" text="Mic" />
<Button fx:id="resetRotationButton" layoutX="13.0" layoutY="49.0" mnemonicParsing="false" text="Reset Rotation" />
<Button fx:id="resetRotationButton" layoutX="464.0" layoutY="195.0" mnemonicParsing="false" text="Reset Rotation" />
<Button fx:id="resetTranslationButton" layoutX="396.0" layoutY="14.0" mnemonicParsing="false" text="Reset Translation" />
</children>
</AnchorPane>

Wyświetl plik

@ -13,7 +13,7 @@
<?import javafx.scene.input.KeyCodeCombination?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="788.0" prefWidth="1008.0" stylesheets="@../css/main.css" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.controller.MainController">
<AnchorPane prefHeight="798.0" prefWidth="1008.0" stylesheets="@../css/main.css" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.controller.MainController">
<MenuBar prefHeight="27.0" prefWidth="1008.0">
<menus>
<Menu mnemonicParsing="false" text="File">
@ -44,6 +44,16 @@
</MenuItem>
<MenuItem fx:id="stopMidiNotesMenuItem" mnemonicParsing="false" text="Stop MIDI Notes" />
<MenuItem fx:id="resetMidiMenuItem" mnemonicParsing="false" text="Reset MIDI" />
<CustomMenuItem hideOnClick="false" mnemonicParsing="false" text="Deadzone">
<content>
<AnchorPane>
<children>
<Label prefHeight="25.0" text="Deadzone" textFill="WHITE" />
<Spinner fx:id="deadzoneSpinner" editable="true" layoutY="25.0" />
</children>
</AnchorPane>
</content>
</CustomMenuItem>
<CustomMenuItem hideOnClick="false" mnemonicParsing="false" text="MIDI Channel">
<content>
<AnchorPane>
@ -62,31 +72,65 @@
<CheckMenuItem fx:id="flipYCheckMenuItem" mnemonicParsing="false" text="Flip Y Direction" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Controls">
<items>
<CustomMenuItem hideOnClick="false" mnemonicParsing="false" text="Translation Increment">
<content>
<AnchorPane>
<children>
<Label prefHeight="25.0" text="Translation Increment" textFill="WHITE" />
<Spinner fx:id="translationIncrementSpinner" editable="true" layoutY="25.0" />
</children>
</AnchorPane>
</content>
</CustomMenuItem>
</items>
</Menu>
<Menu mnemonicParsing="false" text="Sliders">
<items>
<CustomMenuItem hideOnClick="false" mnemonicParsing="false">
<content>
<AnchorPane>
<children>
<ComboBox fx:id="sliderComboBox" prefHeight="30.0" prefWidth="376.0" />
</children>
</AnchorPane>
</content>
</CustomMenuItem>
<CustomMenuItem hideOnClick="false" mnemonicParsing="false">
<content>
<AnchorPane>
<children>
<Label prefHeight="25.0" text="Min" textFill="WHITE" />
<TextField fx:id="sliderMinTextField" layoutY="25.0" prefHeight="26.0" prefWidth="70.0" text="0.0" />
</children>
</AnchorPane>
</content>
</CustomMenuItem>
<CustomMenuItem hideOnClick="false" mnemonicParsing="false">
<content>
<AnchorPane>
<children>
<Label prefHeight="25.0" text="Max" textFill="WHITE" />
<TextField fx:id="sliderMaxTextField" layoutY="25.0" prefHeight="26.0" prefWidth="69.0" text="0.0" />
</children>
</AnchorPane>
</content>
</CustomMenuItem>
</items>
</Menu>
</menus>
</MenuBar>
<TitledPane animated="false" collapsible="false" layoutX="7.0" layoutY="33.0" prefHeight="401.0" prefWidth="390.0" text="Main settings">
<TitledPane animated="false" collapsible="false" layoutX="7.0" layoutY="33.0" prefHeight="401.0" prefWidth="411.0" text="Main settings">
<fx:include fx:id="general" source="general.fxml" />
</TitledPane>
<TitledPane animated="false" collapsible="false" layoutX="425.0" layoutY="424.0" text="Image settings">
<TitledPane animated="false" collapsible="false" layoutX="425.0" layoutY="444.0" prefHeight="348.0" prefWidth="576.0" text="Image settings">
<fx:include fx:id="image" source="image.fxml" />
</TitledPane>
<TitledPane animated="false" collapsible="false" layoutX="425.0" layoutY="33.0" text="Audio Effects">
<TitledPane animated="false" collapsible="false" layoutX="425.0" layoutY="33.0" prefHeight="402.0" prefWidth="576.0" text="Audio Effects">
<fx:include fx:id="effects" source="effects.fxml" />
</TitledPane>
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" layoutX="7.0" layoutY="444.0" prefHeight="207.0" prefWidth="411.0" text="3D .obj file settings">
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" layoutX="7.0" layoutY="444.0" prefHeight="348.0" prefWidth="411.0" text="3D .obj file settings">
<fx:include fx:id="obj" source="obj.fxml" />
</TitledPane>
<TitledPane animated="false" collapsible="false" layoutX="7.0" layoutY="658.0" prefHeight="122.0" prefWidth="411.0" text="Slider settings">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="322.0">
<children>
<TextField fx:id="sliderMinTextField" layoutX="48.0" layoutY="53.0" prefHeight="26.0" prefWidth="70.0" text="0.0" />
<Label layoutX="14.0" layoutY="56.0" text="min :" />
<Label layoutX="133.0" layoutY="56.0" text="max :" />
<TextField fx:id="sliderMaxTextField" layoutX="168.0" layoutY="53.0" prefHeight="26.0" prefWidth="69.0" text="0.0" />
<ComboBox fx:id="sliderComboBox" layoutX="14.0" layoutY="12.0" prefHeight="30.0" prefWidth="376.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</AnchorPane>

Wyświetl plik

@ -7,14 +7,26 @@
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.SVGPath?>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="408.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.controller.ObjController">
<Slider fx:id="focalLengthSlider" blockIncrement="0.01" layoutX="106.0" layoutY="22.0" majorTickUnit="0.2" max="2.0" min="1.0E-5" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="32.0" layoutY="21.0" text="Focal length" />
<Slider fx:id="objectRotateSpeedSlider" blockIncrement="0.005" layoutX="106.0" layoutY="81.0" majorTickUnit="0.1" max="1.0" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" />
<Label layoutX="7.0" layoutY="80.0" text="3D Rotate speed" />
<CheckBox fx:id="rotateCheckBox" layoutX="133.0" layoutY="143.0" mnemonicParsing="false" text="Rotate with Mouse (Esc to disable)" />
<SVGPath fx:id="focalLengthMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="19.0" pickOnBounds="true" />
<SVGPath fx:id="objectRotateSpeedMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="78.0" pickOnBounds="true" />
<CheckBox fx:id="objectRotateSpeedMic" layoutX="353.0" layoutY="81.0" mnemonicParsing="false" text="Mic" />
<Button fx:id="resetObjectRotationButton" layoutX="16.0" layoutY="139.0" mnemonicParsing="false" text="Reset Rotation" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="313.0" prefWidth="408.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sh.ball.gui.controller.ObjController">
<Slider fx:id="focalLengthSlider" blockIncrement="0.01" layoutX="106.0" layoutY="16.0" majorTickUnit="0.2" max="2.0" min="1.0E-5" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="32.0" layoutY="15.0" text="Focal length" />
<Slider fx:id="objectXRotateSlider" blockIncrement="0.005" layoutX="106.0" layoutY="65.0" majorTickUnit="0.2" max="1.0" min="-1.0" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="52.0" layoutY="65.0" text="Rotate x" />
<CheckBox fx:id="rotateCheckBox" layoutX="133.0" layoutY="264.0" mnemonicParsing="false" text="Rotate with Mouse (Esc to disable)" />
<SVGPath fx:id="focalLengthMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="13.0" pickOnBounds="true" />
<SVGPath fx:id="objectXRotateMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="62.0" pickOnBounds="true" />
<CheckBox fx:id="objectXRotateMic" layoutX="353.0" layoutY="65.0" mnemonicParsing="false" text="Mic" />
<Button fx:id="resetObjectRotationButton" layoutX="16.0" layoutY="260.0" mnemonicParsing="false" text="Reset Rotation" />
<Slider fx:id="objectYRotateSlider" blockIncrement="0.005" layoutX="106.0" layoutY="114.0" majorTickUnit="0.2" max="1.0" min="-1.0" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" value="1.0" />
<Label layoutX="52.0" layoutY="114.0" text="Rotate y" />
<SVGPath fx:id="objectYRotateMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="111.0" pickOnBounds="true" />
<CheckBox fx:id="objectYRotateMic" layoutX="353.0" layoutY="114.0" mnemonicParsing="false" text="Mic" />
<Slider fx:id="objectZRotateSlider" blockIncrement="0.005" layoutX="106.0" layoutY="162.0" majorTickUnit="0.2" max="1.0" min="-1.0" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" />
<Label layoutX="52.0" layoutY="162.0" text="Rotate z" />
<SVGPath fx:id="objectZRotateMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="159.0" pickOnBounds="true" />
<CheckBox fx:id="objectZRotateMic" layoutX="353.0" layoutY="162.0" mnemonicParsing="false" text="Mic" />
<Slider fx:id="objectRotateSpeedSlider" blockIncrement="0.005" layoutX="106.0" layoutY="209.0" majorTickUnit="0.2" max="1.0" min="-1.0" prefHeight="42.0" prefWidth="205.0" showTickLabels="true" showTickMarks="true" />
<Label layoutX="9.0" layoutY="209.0" text="3D Rotate speed" />
<SVGPath fx:id="objectRotateSpeedMidi" content="M20.15 8.26H22V15.74H20.15M13 8.26H18.43C19 8.26 19.3 8.74 19.3 9.3V14.81C19.3 15.5 19 15.74 18.38 15.74H13V11H14.87V13.91H17.5V9.95H13M10.32 8.26H12.14V15.74H10.32M2 8.26H8.55C9.1 8.26 9.41 8.74 9.41 9.3V15.74H7.59V10.15H6.5V15.74H4.87V10.15H3.83V15.74H2Z" fill="WHITE" layoutX="316.0" layoutY="206.0" pickOnBounds="true" />
<CheckBox fx:id="objectRotateSpeedMic" layoutX="353.0" layoutY="209.0" mnemonicParsing="false" text="Mic" />
</AnchorPane>