kopia lustrzana https://github.com/jameshball/osci-render
Convert weight-based shape drawing to frequency-based drawing for consistent output frequency
rodzic
03e1e679e6
commit
d785538f94
|
@ -14,7 +14,7 @@ public interface AudioPlayer<S> extends Runnable {
|
|||
|
||||
boolean isPlaying();
|
||||
|
||||
void setQuality(double quality);
|
||||
void setFrequency(double quality);
|
||||
|
||||
void addFrame(S frame);
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@ import sh.ball.shapes.Vector2;
|
|||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
||||
|
||||
|
@ -27,6 +25,7 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
|||
private static final boolean BIG_ENDIAN = false;
|
||||
// Stereo audio
|
||||
private static final int NUM_OUTPUTS = 2;
|
||||
private static final double MIN_LENGTH_INCREMENT = 0.0001;
|
||||
|
||||
private final Callable<AudioEngine> audioEngineBuilder;
|
||||
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
|
||||
|
@ -39,10 +38,11 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
|||
private int framesRecorded = 0;
|
||||
private List<Shape> frame;
|
||||
private int currentShape = 0;
|
||||
private int audioFramesDrawn = 0;
|
||||
private double lengthIncrement = MIN_LENGTH_INCREMENT;
|
||||
private double lengthDrawn = 0;
|
||||
private int count = 0;
|
||||
private double frequency = 261.63;
|
||||
|
||||
private double weight = Shape.DEFAULT_WEIGHT;
|
||||
private AudioDevice device;
|
||||
|
||||
public ShapeAudioPlayer(Callable<AudioEngine> audioEngineBuilder) throws Exception {
|
||||
|
@ -51,29 +51,30 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
|||
}
|
||||
|
||||
private Vector2 generateChannels() throws InterruptedException {
|
||||
Shape shape = getCurrentShape().setWeight(weight);
|
||||
Shape shape = getCurrentShape();
|
||||
|
||||
double totalAudioFrames = shape.getWeight() * shape.getLength();
|
||||
double drawingProgress = totalAudioFrames == 0 ? 1 : audioFramesDrawn / totalAudioFrames;
|
||||
double length = shape.getLength();
|
||||
double drawingProgress = length == 0 ? 1 : lengthDrawn / length;
|
||||
Vector2 nextVector = applyEffects(count, shape.nextVector(drawingProgress));
|
||||
|
||||
Vector2 channels = cutoff(nextVector);
|
||||
writeChannels((float) channels.getX(), (float) channels.getY());
|
||||
|
||||
audioFramesDrawn++;
|
||||
lengthDrawn += lengthIncrement;
|
||||
|
||||
if (++count > MAX_COUNT) {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (audioFramesDrawn > totalAudioFrames) {
|
||||
audioFramesDrawn = 0;
|
||||
if (lengthDrawn > length) {
|
||||
lengthDrawn = lengthDrawn - length;
|
||||
currentShape++;
|
||||
}
|
||||
|
||||
if (currentShape >= frame.size()) {
|
||||
currentShape = 0;
|
||||
frame = frameQueue.take();
|
||||
updateTotalAudioFrames();
|
||||
}
|
||||
|
||||
return channels;
|
||||
|
@ -128,8 +129,8 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setQuality(double quality) {
|
||||
this.weight = quality;
|
||||
public void setFrequency(double frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
private Shape getCurrentShape() {
|
||||
|
@ -140,10 +141,17 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
|||
return frame.get(currentShape);
|
||||
}
|
||||
|
||||
private void updateTotalAudioFrames() {
|
||||
double totalLength = Shape.totalLength(frame);
|
||||
int sampleRate = device.sampleRate();
|
||||
lengthIncrement = Math.max(totalLength / (sampleRate / frequency), MIN_LENGTH_INCREMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
frame = frameQueue.take();
|
||||
updateTotalAudioFrames();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Initial frame not found. Cannot continue.");
|
||||
}
|
||||
|
|
|
@ -15,4 +15,6 @@ public interface AudioEngine {
|
|||
List<AudioDevice> devices();
|
||||
|
||||
AudioDevice getDefaultDevice();
|
||||
|
||||
AudioDevice currentDevice();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ public class ConglomerateAudioEngine implements AudioEngine {
|
|||
private static AudioDevice javaDevice;
|
||||
|
||||
private boolean playing = false;
|
||||
private AudioDevice device;
|
||||
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
|
@ -29,12 +30,14 @@ public class ConglomerateAudioEngine implements AudioEngine {
|
|||
@Override
|
||||
public void play(Callable<Vector2> channelGenerator, AudioDevice device) throws Exception {
|
||||
playing = true;
|
||||
this.device = device;
|
||||
if (xtDevices.contains(device)) {
|
||||
xtEngine.play(channelGenerator, device);
|
||||
} else {
|
||||
javaEngine.play(channelGenerator, javaDevice);
|
||||
}
|
||||
playing = false;
|
||||
this.device = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,4 +69,9 @@ public class ConglomerateAudioEngine implements AudioEngine {
|
|||
public AudioDevice getDefaultDevice() {
|
||||
return javaEngine.getDefaultDevice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioDevice currentDevice() {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ public class JavaAudioEngine implements AudioEngine {
|
|||
private volatile boolean stopped = false;
|
||||
|
||||
private SourceDataLine source;
|
||||
private AudioDevice device;
|
||||
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
|
@ -31,6 +32,7 @@ public class JavaAudioEngine implements AudioEngine {
|
|||
@Override
|
||||
public void play(Callable<Vector2> channelGenerator, AudioDevice device) throws Exception {
|
||||
this.stopped = false;
|
||||
this.device = device;
|
||||
|
||||
AudioFormat format = new AudioFormat((float) device.sampleRate(), BIT_DEPTH, NUM_CHANNELS, SIGNED_SAMPLE, BIG_ENDIAN);
|
||||
|
||||
|
@ -71,6 +73,7 @@ public class JavaAudioEngine implements AudioEngine {
|
|||
}
|
||||
}
|
||||
source.stop();
|
||||
this.device = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,4 +90,9 @@ public class JavaAudioEngine implements AudioEngine {
|
|||
public AudioDevice getDefaultDevice() {
|
||||
return new DefaultAudioDevice("default", "default", DEFAULT_SAMPLE_RATE, AudioSample.INT16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioDevice currentDevice() {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ public class XtAudioEngine implements AudioEngine {
|
|||
}
|
||||
}
|
||||
playing = false;
|
||||
this.device = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -196,6 +197,11 @@ public class XtAudioEngine implements AudioEngine {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioDevice currentDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
private XtService getService(XtPlatform platform) {
|
||||
XtService service = platform.getService(platform.setupToSystem(Enums.XtSetup.SYSTEM_AUDIO));
|
||||
|
|
|
@ -105,9 +105,9 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
|||
@FXML
|
||||
private TextField translationYTextField;
|
||||
@FXML
|
||||
private Slider weightSlider;
|
||||
private Slider frequencySlider;
|
||||
@FXML
|
||||
private SVGPath weightMidi;
|
||||
private SVGPath frequencyMidi;
|
||||
@FXML
|
||||
private Slider rotateSpeedSlider;
|
||||
@FXML
|
||||
|
@ -192,7 +192,7 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
|||
|
||||
private Map<SVGPath, Slider> initializeMidiButtonMap() {
|
||||
Map<SVGPath, Slider> midiMap = new HashMap<>();
|
||||
midiMap.put(weightMidi, weightSlider);
|
||||
midiMap.put(frequencyMidi, frequencySlider);
|
||||
midiMap.put(rotateSpeedMidi, rotateSpeedSlider);
|
||||
midiMap.put(translationSpeedMidi, translationSpeedSlider);
|
||||
midiMap.put(scaleMidi, scaleSlider);
|
||||
|
@ -208,7 +208,7 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
|
|||
|
||||
private Map<Slider, Consumer<Double>> initializeSliderMap() {
|
||||
return Map.of(
|
||||
weightSlider, audioPlayer::setQuality,
|
||||
frequencySlider, audioPlayer::setFrequency,
|
||||
rotateSpeedSlider, rotateEffect::setSpeed,
|
||||
translationSpeedSlider, translateEffect::setSpeed,
|
||||
scaleSlider, scaleEffect::setScale,
|
||||
|
|
|
@ -7,19 +7,14 @@ public class CubicBezierCurve extends Shape {
|
|||
private final Vector2 p2;
|
||||
private final Vector2 p3;
|
||||
|
||||
public CubicBezierCurve(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3, double weight) {
|
||||
public CubicBezierCurve(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) {
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
this.weight = weight;
|
||||
this.length = new Line(p0, p3).length;
|
||||
}
|
||||
|
||||
public CubicBezierCurve(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) {
|
||||
this(p0, p1, p2, p3, DEFAULT_WEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 nextVector(double t) {
|
||||
return p0.scale(Math.pow(1 - t, 3))
|
||||
|
@ -31,7 +26,7 @@ public class CubicBezierCurve extends Shape {
|
|||
@Override
|
||||
public CubicBezierCurve rotate(double theta) {
|
||||
return new CubicBezierCurve(p0.rotate(theta), p1.rotate(theta), p2.rotate(theta),
|
||||
p3.rotate(theta), weight);
|
||||
p3.rotate(theta));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,17 +37,12 @@ public class CubicBezierCurve extends Shape {
|
|||
@Override
|
||||
public CubicBezierCurve scale(Vector2 vector) {
|
||||
return new CubicBezierCurve(p0.scale(vector), p1.scale(vector), p2.scale(vector),
|
||||
p3.scale(vector), weight);
|
||||
p3.scale(vector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CubicBezierCurve translate(Vector2 vector) {
|
||||
return new CubicBezierCurve(p0.translate(vector), p1.translate(vector), p2.translate(vector),
|
||||
p3.translate(vector), weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CubicBezierCurve setWeight(double weight) {
|
||||
return new CubicBezierCurve(p0, p1, p2, p3, weight);
|
||||
p3.translate(vector));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,9 @@ public final class Ellipse extends Shape {
|
|||
private final double rotation;
|
||||
private final Vector2 position;
|
||||
|
||||
public Ellipse(double a, double b, double weight, double rotation, Vector2 position) {
|
||||
public Ellipse(double a, double b, double rotation, Vector2 position) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.weight = weight;
|
||||
this.rotation = rotation;
|
||||
this.position = position;
|
||||
// Approximation of length.
|
||||
|
@ -18,11 +17,11 @@ public final class Ellipse extends Shape {
|
|||
}
|
||||
|
||||
public Ellipse(double a, double b, Vector2 position) {
|
||||
this(a, b, Shape.DEFAULT_WEIGHT, 0, position);
|
||||
this(a, b, 0, position);
|
||||
}
|
||||
|
||||
public Ellipse(double a, double b) {
|
||||
this(a, b, Shape.DEFAULT_WEIGHT, 0, new Vector2());
|
||||
this(a, b, 0, new Vector2());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,7 +39,7 @@ public final class Ellipse extends Shape {
|
|||
theta -= 2 * Math.PI;
|
||||
}
|
||||
|
||||
return new Ellipse(a, b, weight, theta, position);
|
||||
return new Ellipse(a, b, theta, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,17 +49,12 @@ public final class Ellipse extends Shape {
|
|||
|
||||
@Override
|
||||
public Ellipse scale(Vector2 vector) {
|
||||
return new Ellipse(a * vector.getX(), b * vector.getY(), weight, rotation,
|
||||
return new Ellipse(a * vector.getX(), b * vector.getY(), rotation,
|
||||
position.scale(vector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ellipse translate(Vector2 vector) {
|
||||
return new Ellipse(a, b, weight, rotation, position.translate(vector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ellipse setWeight(double weight) {
|
||||
return new Ellipse(a, b, weight, rotation, position);
|
||||
return new Ellipse(a, b, rotation, position.translate(vector));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,21 +8,12 @@ public final class Line extends Shape {
|
|||
private final Vector2 a;
|
||||
private final Vector2 b;
|
||||
|
||||
public Line(Vector2 a, Vector2 b, double weight) {
|
||||
public Line(Vector2 a, Vector2 b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.weight = weight;
|
||||
this.length = calculateLength();
|
||||
}
|
||||
|
||||
public Line(Vector2 a, Vector2 b) {
|
||||
this(a, b, Shape.DEFAULT_WEIGHT);
|
||||
}
|
||||
|
||||
public Line(double x1, double y1, double x2, double y2, double weight) {
|
||||
this(new Vector2(x1, y1), new Vector2(x2, y2), weight);
|
||||
}
|
||||
|
||||
public Line(double x1, double y1, double x2, double y2) {
|
||||
this(new Vector2(x1, y1), new Vector2(x2, y2));
|
||||
}
|
||||
|
@ -33,26 +24,26 @@ public final class Line extends Shape {
|
|||
|
||||
@Override
|
||||
public Line rotate(double theta) {
|
||||
return new Line(a.rotate(theta), b.rotate(theta), weight);
|
||||
return new Line(a.rotate(theta), b.rotate(theta));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Line translate(Vector2 vector) {
|
||||
return new Line(a.translate(vector), b.translate(vector), weight);
|
||||
return new Line(a.translate(vector), b.translate(vector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Line scale(double factor) {
|
||||
return new Line(a.scale(factor), b.scale(factor), weight);
|
||||
return new Line(a.scale(factor), b.scale(factor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Line scale(Vector2 vector) {
|
||||
return new Line(a.scale(vector), b.scale(vector), weight);
|
||||
return new Line(a.scale(vector), b.scale(vector));
|
||||
}
|
||||
|
||||
public Line copy() {
|
||||
return new Line(a.copy(), b.copy(), weight);
|
||||
return new Line(a.copy(), b.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,11 +105,6 @@ public final class Line extends Shape {
|
|||
return lines;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Line setWeight(double weight) {
|
||||
return new Line(getX1(), getY1(), getX2(), getY2(), weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
|
|
|
@ -6,18 +6,13 @@ public class QuadraticBezierCurve extends Shape {
|
|||
private final Vector2 p1;
|
||||
private final Vector2 p2;
|
||||
|
||||
public QuadraticBezierCurve(Vector2 p0, Vector2 p1, Vector2 p2, double weight) {
|
||||
public QuadraticBezierCurve(Vector2 p0, Vector2 p1, Vector2 p2) {
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.weight = weight;
|
||||
this.length = new Line(p0, p2).length;
|
||||
}
|
||||
|
||||
public QuadraticBezierCurve(Vector2 p0, Vector2 p1, Vector2 p2) {
|
||||
this(p0, p1, p2, DEFAULT_WEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 nextVector(double t) {
|
||||
return p1.add(p0.sub(p1).scale(Math.pow(1 - t, 2)))
|
||||
|
@ -26,27 +21,22 @@ public class QuadraticBezierCurve extends Shape {
|
|||
|
||||
@Override
|
||||
public QuadraticBezierCurve rotate(double theta) {
|
||||
return new QuadraticBezierCurve(p0.rotate(theta), p1.rotate(theta), p2.rotate(theta), weight);
|
||||
return new QuadraticBezierCurve(p0.rotate(theta), p1.rotate(theta), p2.rotate(theta));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuadraticBezierCurve scale(double factor) {
|
||||
return new QuadraticBezierCurve(p0.scale(factor), p1.scale(factor), p2.scale(factor), weight);
|
||||
return new QuadraticBezierCurve(p0.scale(factor), p1.scale(factor), p2.scale(factor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuadraticBezierCurve scale(Vector2 vector) {
|
||||
return new QuadraticBezierCurve(p0.scale(vector), p1.scale(vector), p2.scale(vector), weight);
|
||||
return new QuadraticBezierCurve(p0.scale(vector), p1.scale(vector), p2.scale(vector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuadraticBezierCurve translate(Vector2 vector) {
|
||||
return new QuadraticBezierCurve(p0.translate(vector), p1.translate(vector),
|
||||
p2.translate(vector), weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuadraticBezierCurve setWeight(double weight) {
|
||||
return new QuadraticBezierCurve(p0, p1, p2, weight);
|
||||
p2.translate(vector));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,6 @@ import java.util.List;
|
|||
|
||||
public abstract class Shape {
|
||||
|
||||
public static final int DEFAULT_WEIGHT = 80;
|
||||
|
||||
protected double weight = DEFAULT_WEIGHT;
|
||||
protected double length;
|
||||
|
||||
public abstract Vector2 nextVector(double drawingProgress);
|
||||
|
@ -22,12 +19,6 @@ public abstract class Shape {
|
|||
|
||||
public abstract Shape translate(Vector2 vector);
|
||||
|
||||
public abstract Shape setWeight(double weight);
|
||||
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public double getLength() {
|
||||
return length;
|
||||
}
|
||||
|
@ -186,16 +177,15 @@ public abstract class Shape {
|
|||
return translatedShapes;
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start,
|
||||
double weight) {
|
||||
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start) {
|
||||
List<Shape> polygon = new ArrayList<>();
|
||||
|
||||
double theta = angleJump * 2 * Math.PI / sides;
|
||||
Vector2 rotated = start.rotate(theta);
|
||||
polygon.add(new Line(start, rotated, weight));
|
||||
polygon.add(new Line(start, rotated));
|
||||
|
||||
while (!rotated.equals(start)) {
|
||||
polygon.add(new Line(rotated.copy(), rotated.rotate(theta), weight));
|
||||
polygon.add(new Line(rotated.copy(), rotated.rotate(theta)));
|
||||
|
||||
rotated = rotated.rotate(theta);
|
||||
}
|
||||
|
@ -203,31 +193,14 @@ public abstract class Shape {
|
|||
return polygon;
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygram(int sides, int angleJump, Vector2 start) {
|
||||
return generatePolygram(sides, angleJump, start, Line.DEFAULT_WEIGHT);
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygram(int sides, int angleJump, double scale,
|
||||
double weight) {
|
||||
return generatePolygram(sides, angleJump, new Vector2(scale, scale), weight);
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygram(int sides, int angleJump, double scale) {
|
||||
return generatePolygram(sides, angleJump, new Vector2(scale, scale));
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygon(int sides, Vector2 start, double weight) {
|
||||
return generatePolygram(sides, 1, start, weight);
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygon(int sides, Vector2 start) {
|
||||
return generatePolygram(sides, 1, start);
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygon(int sides, double scale, double weight) {
|
||||
return generatePolygon(sides, new Vector2(scale, scale), weight);
|
||||
}
|
||||
|
||||
public static List<Shape> generatePolygon(int sides, double scale) {
|
||||
return generatePolygon(sides, new Vector2(scale, scale));
|
||||
}
|
||||
|
|
|
@ -7,18 +7,13 @@ public final class Vector2 extends Shape {
|
|||
private final double x;
|
||||
private final double y;
|
||||
|
||||
public Vector2(double x, double y, double weight) {
|
||||
public Vector2(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public Vector2(double x, double y) {
|
||||
this(x, y, Shape.DEFAULT_WEIGHT);
|
||||
}
|
||||
|
||||
public Vector2(double xy) {
|
||||
this(xy, xy, Shape.DEFAULT_WEIGHT);
|
||||
this(xy, xy);
|
||||
}
|
||||
|
||||
public Vector2() {
|
||||
|
@ -85,11 +80,6 @@ public final class Vector2 extends Shape {
|
|||
return new Vector2(getX() + vector.getX(), getY() + vector.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 setWeight(double weight) {
|
||||
return new Vector2(x, y, weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
|
|
@ -73,24 +73,24 @@
|
|||
<AnchorPane minHeight="0.0" minWidth="0.0">
|
||||
<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" />
|
||||
<Label layoutX="33.0" layoutY="88.0" text="Rotate speed">
|
||||
<Label layoutX="33.0" layoutY="89.0" text="Rotate speed">
|
||||
<font>
|
||||
<Font size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Slider fx:id="translationSpeedSlider" blockIncrement="0.05" layoutX="116.0" layoutY="128.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="254.0" showTickLabels="true" showTickMarks="true" />
|
||||
<Label layoutX="7.0" layoutY="126.0" text="Translation speed">
|
||||
<Label layoutX="7.0" layoutY="127.0" text="Translation speed">
|
||||
<font>
|
||||
<Font size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Slider fx:id="scaleSlider" blockIncrement="0.05" layoutX="116.0" layoutY="167.0" majorTickUnit="1.0" max="10.0" prefHeight="42.0" prefWidth="253.0" showTickLabels="true" showTickMarks="true" value="1.0" />
|
||||
<Label layoutX="79.0" layoutY="164.0" text="Scale">
|
||||
<Label layoutX="79.0" layoutY="166.0" text="Scale">
|
||||
<font>
|
||||
<Font size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label layoutX="43.0" layoutY="49.0" text="Line weight">
|
||||
<Label layoutX="11.0" layoutY="50.0" text="Target frequency">
|
||||
<font>
|
||||
<Font size="13.0" />
|
||||
</font>
|
||||
|
@ -100,8 +100,8 @@
|
|||
<Label layoutX="120.0" layoutY="18.0" text="x :" />
|
||||
<Label layoutX="219.0" layoutY="18.0" text="y :" />
|
||||
<TextField fx:id="translationYTextField" layoutX="238.0" layoutY="15.0" prefHeight="26.0" prefWidth="70.0" text="0" />
|
||||
<Slider fx:id="weightSlider" blockIncrement="1.0" layoutX="116.0" layoutY="52.0" majorTickUnit="100.0" max="1000.0" prefHeight="42.0" prefWidth="253.0" showTickLabels="true" showTickMarks="true" value="100.0" />
|
||||
<SVGPath fx:id="weightMidi" 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="49.0" pickOnBounds="true" />
|
||||
<Slider fx:id="frequencySlider" blockIncrement="1.0" layoutX="116.0" layoutY="52.0" majorTickUnit="200.0" max="1000.0" prefHeight="42.0" prefWidth="253.0" showTickLabels="true" showTickMarks="true" value="261.63" />
|
||||
<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="49.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="87.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="125.0" pickOnBounds="true" />
|
||||
<SVGPath fx:id="scaleMidi" 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="164.0" pickOnBounds="true" />
|
||||
|
|
Ładowanie…
Reference in New Issue