kopia lustrzana https://github.com/jameshball/osci-render
Add image visibility slider for when playing multiple notes and improve reliability
rodzic
8bbcc1fb07
commit
0d0fad297f
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<groupId>sh.ball</groupId>
|
<groupId>sh.ball</groupId>
|
||||||
<artifactId>osci-render</artifactId>
|
<artifactId>osci-render</artifactId>
|
||||||
<version>1.11.9</version>
|
<version>1.11.10</version>
|
||||||
|
|
||||||
<name>osci-render</name>
|
<name>osci-render</name>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ public interface AudioPlayer<S> extends Runnable {
|
||||||
|
|
||||||
void setOctave(int octave);
|
void setOctave(int octave);
|
||||||
|
|
||||||
|
void setMainFrequencyScale(double scale);
|
||||||
|
|
||||||
void setBaseFrequencies(List<Double> frequency);
|
void setBaseFrequencies(List<Double> frequency);
|
||||||
|
|
||||||
void setPitchBendFactor(double pitchBend);
|
void setPitchBendFactor(double pitchBend);
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
||||||
private int count = 0;
|
private int count = 0;
|
||||||
private List<Double> frequencies = List.of(MIDDLE_C);
|
private List<Double> frequencies = List.of(MIDDLE_C);
|
||||||
private double mainFrequency = MIDDLE_C;
|
private double mainFrequency = MIDDLE_C;
|
||||||
|
private double mainFrequencyScale = 0.5;
|
||||||
private double maxFrequency = MIDDLE_C;
|
private double maxFrequency = MIDDLE_C;
|
||||||
private double pitchBend = 1.0;
|
private double pitchBend = 1.0;
|
||||||
private double trace = 0.5;
|
private double trace = 0.5;
|
||||||
|
@ -132,10 +133,11 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2 applyEffects(int frame, Vector2 vector) {
|
private Vector2 applyEffects(int frame, Vector2 vector) {
|
||||||
int numNotes = sineEffects.size() + 1;
|
int numNotes = sineEffects.size();
|
||||||
vector.scale(1.0 / numNotes);
|
vector = vector.scale(2 * mainFrequencyScale);
|
||||||
|
double scaledVolume = (1 - mainFrequencyScale) / numNotes;
|
||||||
for (SineEffect effect : sineEffects) {
|
for (SineEffect effect : sineEffects) {
|
||||||
effect.setVolume(1.0 / numNotes);
|
effect.setVolume(scaledVolume);
|
||||||
vector = effect.apply(frame, vector);
|
vector = effect.apply(frame, vector);
|
||||||
}
|
}
|
||||||
for (Effect effect : effects.values()) {
|
for (Effect effect : effects.values()) {
|
||||||
|
@ -235,6 +237,11 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
||||||
this.mainFrequency = maxFrequency * Math.pow(2, octave - 1);
|
this.mainFrequency = maxFrequency * Math.pow(2, octave - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMainFrequencyScale(double scale) {
|
||||||
|
this.mainFrequencyScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFrame(List<Shape> frame) {
|
public void addFrame(List<Shape> frame) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -182,6 +182,10 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
||||||
@FXML
|
@FXML
|
||||||
private SVGPath octaveMidi;
|
private SVGPath octaveMidi;
|
||||||
@FXML
|
@FXML
|
||||||
|
private Slider visibilitySlider;
|
||||||
|
@FXML
|
||||||
|
private SVGPath visibilityMidi;
|
||||||
|
@FXML
|
||||||
private ComboBox<AudioDevice> deviceComboBox;
|
private ComboBox<AudioDevice> deviceComboBox;
|
||||||
|
|
||||||
public Controller(AudioPlayer<List<Shape>> audioPlayer) throws IOException {
|
public Controller(AudioPlayer<List<Shape>> audioPlayer) throws IOException {
|
||||||
|
@ -215,6 +219,7 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
||||||
midiMap.put(bitCrushMidi, bitCrushSlider);
|
midiMap.put(bitCrushMidi, bitCrushSlider);
|
||||||
midiMap.put(wobbleMidi, wobbleSlider);
|
midiMap.put(wobbleMidi, wobbleSlider);
|
||||||
midiMap.put(octaveMidi, octaveSlider);
|
midiMap.put(octaveMidi, octaveSlider);
|
||||||
|
midiMap.put(visibilityMidi, visibilitySlider);
|
||||||
midiMap.put(verticalDistortMidi, verticalDistortSlider);
|
midiMap.put(verticalDistortMidi, verticalDistortSlider);
|
||||||
midiMap.put(horizontalDistortMidi, horizontalDistortSlider);
|
midiMap.put(horizontalDistortMidi, horizontalDistortSlider);
|
||||||
return midiMap;
|
return midiMap;
|
||||||
|
@ -227,7 +232,8 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
||||||
translationSpeedSlider, translateEffect::setSpeed,
|
translationSpeedSlider, translateEffect::setSpeed,
|
||||||
scaleSlider, scaleEffect::setScale,
|
scaleSlider, scaleEffect::setScale,
|
||||||
focalLengthSlider, d -> updateFocalLength(),
|
focalLengthSlider, d -> updateFocalLength(),
|
||||||
objectRotateSpeedSlider, d -> updateObjectRotateSpeed()
|
objectRotateSpeedSlider, d -> updateObjectRotateSpeed(),
|
||||||
|
visibilitySlider, audioPlayer::setMainFrequencyScale
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,78 +656,80 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMidiMessage(ShortMessage message) {
|
public void sendMidiMessage(ShortMessage message) {
|
||||||
int command = message.getCommand();
|
Platform.runLater(() -> {
|
||||||
|
int command = message.getCommand();
|
||||||
|
|
||||||
if (command == ShortMessage.CONTROL_CHANGE) {
|
if (command == ShortMessage.CONTROL_CHANGE) {
|
||||||
int id = message.getData1();
|
int id = message.getData1();
|
||||||
int value = message.getData2();
|
int value = message.getData2();
|
||||||
|
|
||||||
if (armedMidi != null) {
|
if (armedMidi != null) {
|
||||||
if (CCMap.containsValue(armedMidi)) {
|
if (CCMap.containsValue(armedMidi)) {
|
||||||
CCMap.values().remove(armedMidi);
|
CCMap.values().remove(armedMidi);
|
||||||
|
}
|
||||||
|
if (CCMap.containsKey(id)) {
|
||||||
|
CCMap.get(id).setFill(Color.color(1, 1, 1));
|
||||||
|
}
|
||||||
|
CCMap.put(id, armedMidi);
|
||||||
|
armedMidi.setFill(Color.color(0, 1, 0));
|
||||||
|
armedMidiPaint = null;
|
||||||
|
armedMidi = null;
|
||||||
}
|
}
|
||||||
if (CCMap.containsKey(id)) {
|
if (CCMap.containsKey(id)) {
|
||||||
CCMap.get(id).setFill(Color.color(1, 1, 1));
|
Slider slider = midiButtonMap.get(CCMap.get(id));
|
||||||
|
double sliderValue = midiPressureToPressure(slider, value);
|
||||||
|
|
||||||
|
if (slider.isSnapToTicks()) {
|
||||||
|
double increment = slider.getMajorTickUnit() / (slider.getMinorTickCount() + 1);
|
||||||
|
sliderValue = increment * (Math.round(sliderValue / increment));
|
||||||
|
}
|
||||||
|
slider.setValue(sliderValue);
|
||||||
}
|
}
|
||||||
CCMap.put(id, armedMidi);
|
} else if (command == ShortMessage.NOTE_ON || command == ShortMessage.NOTE_OFF) {
|
||||||
armedMidi.setFill(Color.color(0, 1, 0));
|
MidiNote note = new MidiNote(message.getData1());
|
||||||
armedMidiPaint = null;
|
int velocity = message.getData2();
|
||||||
armedMidi = null;
|
|
||||||
}
|
|
||||||
if (CCMap.containsKey(id)) {
|
|
||||||
Slider slider = midiButtonMap.get(CCMap.get(id));
|
|
||||||
double sliderValue = midiPressureToPressure(slider, value);
|
|
||||||
|
|
||||||
if (slider.isSnapToTicks()) {
|
double oldVolume = scaleSlider.getValue();
|
||||||
double increment = slider.getMajorTickUnit() / (slider.getMinorTickCount() + 1);
|
double volume = midiPressureToPressure(scaleSlider, velocity);
|
||||||
sliderValue = increment * (Math.round(sliderValue / increment));
|
volume /= 10;
|
||||||
}
|
|
||||||
slider.setValue(sliderValue);
|
|
||||||
}
|
|
||||||
} else if (command == ShortMessage.NOTE_ON || command == ShortMessage.NOTE_OFF) {
|
|
||||||
MidiNote note = new MidiNote(message.getData1());
|
|
||||||
int velocity = message.getData2();
|
|
||||||
|
|
||||||
double oldVolume = scaleSlider.getValue();
|
if (command == ShortMessage.NOTE_OFF) {
|
||||||
double volume = midiPressureToPressure(scaleSlider, velocity);
|
downKeys.remove(note);
|
||||||
volume /= 10;
|
if (downKeys.isEmpty()) {
|
||||||
|
KeyValue kv = new KeyValue(scaleSlider.valueProperty(), 0, Interpolator.EASE_OUT);
|
||||||
if (command == ShortMessage.NOTE_OFF) {
|
KeyFrame kf = new KeyFrame(Duration.millis(500), kv);
|
||||||
downKeys.remove(note);
|
volumeTimeline = new Timeline(kf);
|
||||||
if (downKeys.isEmpty()) {
|
Platform.runLater(volumeTimeline::play);
|
||||||
KeyValue kv = new KeyValue(scaleSlider.valueProperty(), 0, Interpolator.EASE_OUT);
|
} else {
|
||||||
KeyFrame kf = new KeyFrame(Duration.millis(500), kv);
|
playNotes(oldVolume);
|
||||||
volumeTimeline = new Timeline(kf);
|
}
|
||||||
volumeTimeline.play();
|
|
||||||
} else {
|
} else {
|
||||||
playNotes(oldVolume);
|
downKeys.add(note);
|
||||||
|
if (volumeTimeline != null) {
|
||||||
|
volumeTimeline.stop();
|
||||||
|
volumeTimeline = null;
|
||||||
|
}
|
||||||
|
playNotes(volume);
|
||||||
|
KeyValue kv = new KeyValue(scaleSlider.valueProperty(), scaleSlider.valueProperty().get() * 0.75, Interpolator.EASE_OUT);
|
||||||
|
KeyFrame kf = new KeyFrame(Duration.millis(250), kv);
|
||||||
|
volumeTimeline = new Timeline(kf);
|
||||||
|
Platform.runLater(volumeTimeline::play);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (command == ShortMessage.PITCH_BEND) {
|
||||||
downKeys.add(note);
|
// using these instructions https://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/
|
||||||
if (volumeTimeline != null) {
|
|
||||||
volumeTimeline.stop();
|
int pitchBend = (message.getData2() << PITCH_BEND_DATA_LENGTH) | message.getData1();
|
||||||
volumeTimeline = null;
|
// get pitch bend in range -1 to 1
|
||||||
}
|
double pitchBendFactor = (double) pitchBend / PITCH_BEND_MAX;
|
||||||
playNotes(volume);
|
pitchBendFactor = 2 * pitchBendFactor - 1;
|
||||||
KeyValue kv = new KeyValue(scaleSlider.valueProperty(), scaleSlider.valueProperty().get() * 0.75, Interpolator.EASE_OUT);
|
pitchBendFactor *= PITCH_BEND_SEMITONES;
|
||||||
KeyFrame kf = new KeyFrame(Duration.millis(250), kv);
|
// 12 tone equal temperament
|
||||||
volumeTimeline = new Timeline(kf);
|
pitchBendFactor /= 12;
|
||||||
volumeTimeline.play();
|
pitchBendFactor = Math.pow(2, pitchBendFactor);
|
||||||
|
|
||||||
|
audioPlayer.setPitchBendFactor(pitchBendFactor);
|
||||||
}
|
}
|
||||||
} else if (command == ShortMessage.PITCH_BEND) {
|
});
|
||||||
// using these instructions https://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/
|
|
||||||
|
|
||||||
int pitchBend = (message.getData2() << PITCH_BEND_DATA_LENGTH) | message.getData1();
|
|
||||||
// get pitch bend in range -1 to 1
|
|
||||||
double pitchBendFactor = (double) pitchBend / PITCH_BEND_MAX;
|
|
||||||
pitchBendFactor = 2 * pitchBendFactor - 1;
|
|
||||||
pitchBendFactor *= PITCH_BEND_SEMITONES;
|
|
||||||
// 12 tone equal temperament
|
|
||||||
pitchBendFactor /= 12;
|
|
||||||
pitchBendFactor = Math.pow(2, pitchBendFactor);
|
|
||||||
|
|
||||||
audioPlayer.setPitchBendFactor(pitchBendFactor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the volume/scale
|
// gets the volume/scale
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<?import javafx.scene.shape.SVGPath?>
|
<?import javafx.scene.shape.SVGPath?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<AnchorPane prefHeight="539.0" prefWidth="837.0" stylesheets="@../css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
|
<AnchorPane prefHeight="589.0" prefWidth="837.0" stylesheets="@../css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<TitledPane animated="false" collapsible="false" layoutX="426.0" layoutY="8.0" prefHeight="303.0" prefWidth="402.0" text="Audio Effects">
|
<TitledPane animated="false" collapsible="false" layoutX="426.0" layoutY="8.0" prefHeight="303.0" prefWidth="402.0" text="Audio Effects">
|
||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="262.0" prefWidth="401.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="262.0" prefWidth="401.0">
|
||||||
|
@ -38,22 +38,22 @@
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</content>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
<TitledPane fx:id="objTitledPane" animated="false" collapsible="false" layoutX="426.0" layoutY="318.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="426.0" layoutY="318.0" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="257.0" prefWidth="402.0" text="3D .obj file settings">
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="359.0">
|
<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="42.0" prefWidth="258.0" showTickLabels="true" showTickMarks="true" value="1.0" />
|
<Slider fx:id="focalLengthSlider" blockIncrement="0.01" layoutX="116.0" layoutY="22.0" majorTickUnit="0.2" max="2.0" min="1.0E-5" prefHeight="42.0" prefWidth="258.0" showTickLabels="true" showTickMarks="true" value="1.0" />
|
||||||
<Label layoutX="34.0" layoutY="14.0" text="Focal length" />
|
<Label layoutX="34.0" layoutY="21.0" text="Focal length" />
|
||||||
<TextField fx:id="cameraXTextField" layoutX="134.0" layoutY="57.0" prefHeight="26.0" prefWidth="65.0" text="0" />
|
<TextField fx:id="cameraXTextField" layoutX="134.0" layoutY="74.0" prefHeight="26.0" prefWidth="65.0" text="0" />
|
||||||
<Label layoutX="35.0" layoutY="61.0" text="Camera pos" />
|
<Label layoutX="35.0" layoutY="78.0" text="Camera pos" />
|
||||||
<Label layoutX="118.0" layoutY="61.0" text="x :" />
|
<Label layoutX="118.0" layoutY="78.0" text="x :" />
|
||||||
<Label layoutX="207.0" layoutY="60.0" text="y :" />
|
<Label layoutX="207.0" layoutY="77.0" text="y :" />
|
||||||
<TextField fx:id="cameraYTextField" layoutX="224.0" layoutY="57.0" prefHeight="26.0" prefWidth="65.0" text="0" />
|
<TextField fx:id="cameraYTextField" layoutX="224.0" layoutY="74.0" prefHeight="26.0" prefWidth="65.0" text="0" />
|
||||||
<Label layoutX="299.0" layoutY="60.0" text="z :" />
|
<Label layoutX="299.0" layoutY="77.0" text="z :" />
|
||||||
<TextField fx:id="cameraZTextField" layoutX="315.0" layoutY="57.0" prefHeight="26.0" prefWidth="65.0" text="-2.5" />
|
<TextField fx:id="cameraZTextField" layoutX="315.0" layoutY="74.0" prefHeight="26.0" prefWidth="65.0" text="-2.5" />
|
||||||
<Slider fx:id="objectRotateSpeedSlider" blockIncrement="0.005" layoutX="116.0" layoutY="97.0" majorTickUnit="0.1" max="1.0" prefHeight="42.0" prefWidth="258.0" showTickLabels="true" showTickMarks="true" />
|
<Slider fx:id="objectRotateSpeedSlider" blockIncrement="0.005" layoutX="116.0" layoutY="121.0" majorTickUnit="0.1" max="1.0" prefHeight="42.0" prefWidth="258.0" showTickLabels="true" showTickMarks="true" />
|
||||||
<Label layoutX="9.0" layoutY="96.0" text="3D Rotate speed" />
|
<Label layoutX="9.0" layoutY="120.0" text="3D Rotate speed" />
|
||||||
<CheckBox fx:id="rotateCheckBox" layoutX="90.0" layoutY="147.0" mnemonicParsing="false" text="Rotate with Mouse (Esc to disable)" />
|
<CheckBox fx:id="rotateCheckBox" layoutX="90.0" layoutY="179.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="374.0" layoutY="12.0" pickOnBounds="true" />
|
<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="374.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="374.0" layoutY="94.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="374.0" layoutY="118.0" pickOnBounds="true" />
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
<AnchorPane id="control-pane" layoutX="12.0" layoutY="7.0" prefHeight="274.0" prefWidth="402.0">
|
<AnchorPane id="control-pane" layoutX="12.0" layoutY="7.0" prefHeight="274.0" prefWidth="402.0">
|
||||||
|
@ -71,9 +71,9 @@
|
||||||
<CheckBox fx:id="recordCheckBox" layoutX="143.0" layoutY="146.0" mnemonicParsing="false" text="Timed record" />
|
<CheckBox fx:id="recordCheckBox" layoutX="143.0" layoutY="146.0" mnemonicParsing="false" text="Timed record" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<TitledPane collapsible="false" layoutX="12.0" layoutY="289.0" prefHeight="239.0" prefWidth="402.0" text="Image settings">
|
<TitledPane collapsible="false" layoutX="12.0" layoutY="289.0" prefHeight="286.0" prefWidth="402.0" text="Image settings">
|
||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="250.0" prefWidth="402.0">
|
||||||
<children>
|
<children>
|
||||||
<Slider fx:id="rotateSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="90.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" />
|
<Slider fx:id="rotateSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="90.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" />
|
||||||
<Label layoutX="13.0" layoutY="89.0" text="2D Rotate speed">
|
<Label layoutX="13.0" layoutY="89.0" text="2D Rotate speed">
|
||||||
|
@ -122,6 +122,13 @@
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="162.0" layoutY="71.0" text="5" />
|
<Label layoutX="162.0" layoutY="71.0" text="5" />
|
||||||
<Label layoutX="122.0" layoutY="71.0" text="0" />
|
<Label layoutX="122.0" layoutY="71.0" text="0" />
|
||||||
|
<Label layoutX="24.0" layoutY="206.0" text="Image visibility">
|
||||||
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Slider fx:id="visibilitySlider" blockIncrement="0.005" layoutX="116.0" layoutY="207.0" majorTickUnit="0.1" max="1.0" prefHeight="42.0" prefWidth="253.0" showTickLabels="true" showTickMarks="true" value="0.5" />
|
||||||
|
<SVGPath fx:id="visibilityMidi" 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="204.0" pickOnBounds="true" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</content>
|
||||||
|
|
Ładowanie…
Reference in New Issue