Allow x, y, and z values to be transformed using the 3D depth effect

pull/105/head
James Ball 2022-07-16 18:45:51 +01:00 zatwierdzone przez James H Ball
rodzic 6553e6391c
commit 9194209a66
10 zmienionych plików z 289 dodań i 207 usunięć

Wyświetl plik

@ -1,17 +1,27 @@
package sh.ball.audio.effect;
import org.luaj.vm2.LuaValue;
import sh.ball.engine.Vector3;
import sh.ball.parser.lua.LuaExecutor;
import sh.ball.shapes.Vector2;
import javax.xml.transform.Result;
// 3D rotation effect
public class PerspectiveEffect implements SettableEffect {
private final LuaExecutor executor;
private double zPos = 1.0;
private Vector3 baseRotation = new Vector3(Math.PI, Math.PI, 0);
private Vector3 currentRotation = new Vector3();
private double rotateSpeed = 0.0;
private double effectScale = 1.0;
public PerspectiveEffect(LuaExecutor executor) {
this.executor = executor;
}
@Override
public Vector2 apply(int count, Vector2 vector) {
currentRotation = currentRotation.add(baseRotation.scale(rotateSpeed));
@ -19,10 +29,23 @@ public class PerspectiveEffect implements SettableEffect {
Vector3 vertex = new Vector3(vector.x, vector.y, 0.0);
vertex = vertex.rotate(baseRotation.add(currentRotation));
executor.setVariable("x", vertex.x);
executor.setVariable("y", vertex.y);
executor.setVariable("z", -zPos);
double x = vertex.x;
double y = vertex.y;
double z = -zPos;
try {
LuaValue result = executor.execute();
x = result.get(1).checkdouble();
y = result.get(2).checkdouble();
z = result.get(3).checkdouble();
} catch (Exception ignored) {}
double focalLength = 1.0;
return new Vector2(
(1 - effectScale) * vector.x + effectScale * (vertex.x * focalLength / (vertex.z - zPos)),
(1 - effectScale) * vector.y + effectScale * (vertex.y * focalLength / (vertex.z - zPos))
(1 - effectScale) * vector.x + effectScale * (x * focalLength / z),
(1 - effectScale) * vector.y + effectScale * (y * focalLength / z)
);
}

Wyświetl plik

@ -1,6 +1,5 @@
package sh.ball.audio.engine;
import com.sun.javafx.PlatformUtil;
import sh.ball.shapes.Vector2;
import xt.audio.*;
@ -237,13 +236,7 @@ public class XtAudioEngine implements AudioEngine {
// connects to an XtAudio XtService in order of lowest latency to highest latency
private XtService getService(XtPlatform platform) {
XtService service = null;
if ((PlatformUtil.isLinux() || PlatformUtil.isUnix()) && !PlatformUtil.isMac()) {
service = platform.getService(Enums.XtSystem.JACK);
}
if (service == null) {
service = platform.getService(platform.setupToSystem(Enums.XtSetup.SYSTEM_AUDIO));
}
XtService service = platform.getService(platform.setupToSystem(Enums.XtSetup.SYSTEM_AUDIO));
if (service == null) {
service = platform.getService(platform.setupToSystem(Enums.XtSetup.PRO_AUDIO));
}

Wyświetl plik

@ -31,6 +31,7 @@ import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.logging.*;
public class Gui extends Application {
@ -40,12 +41,11 @@ public class Gui extends Application {
public static String LOG_DIR = "./logs/";
public static final Logger logger = Logger.getLogger(Gui.class.getName());
public static ProjectSelectController projectSelectController;
public static ShapeAudioPlayer audioPlayer;
public static AudioDevice defaultDevice;
public static CodeEditor editor;
public static Stage editorStage;
public static Scene editorScene;
private static CodeEditor editor;
private static Stage editorStage;
static {
try {
@ -79,13 +79,11 @@ public class Gui extends Application {
new Thread(midiCommunicator).start();
}
private Stage stage;
private Scene scene;
private Parent root;
@Override
public void start(Stage stage) throws Exception {
this.stage = stage;
System.setProperty("prism.lcdtext", "false");
System.setProperty("org.luaj.luajc", "true");
@ -93,7 +91,7 @@ public class Gui extends Application {
FXMLLoader projectSelectLoader = new FXMLLoader(getClass().getResource("/fxml/projectSelect.fxml"));
Parent projectSelectRoot = projectSelectLoader.load();
projectSelectController = projectSelectLoader.getController();
ProjectSelectController projectSelectController = projectSelectLoader.getController();
projectSelectController.setOpenBrowser(url -> getHostServices().showDocument(url));
stage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/icons/icon.png"))));
@ -166,12 +164,11 @@ public class Gui extends Application {
editor = new CodeEditor();
editor.initialize();
editorStage = new Stage();
editorScene = new Scene(editor, 900, 600, false, SceneAntialiasing.BALANCED);
Scene editorScene = new Scene(editor, 900, 600, false, SceneAntialiasing.BALANCED);
editorStage.setScene(editorScene);
editorStage.getIcons().add(new Image(Objects.requireNonNull(Gui.class.getResourceAsStream("/icons/icon.png"))));
editor.prefHeightProperty().bind(editorStage.heightProperty());
editor.prefWidthProperty().bind(editorStage.widthProperty());
editor.setCallback(controller::updateFileData);
}
public void launchMainApplication(MainController controller, String projectPath, Boolean muted) throws Exception {
@ -194,20 +191,12 @@ public class Gui extends Application {
}
}
public static void launchCodeEditor(String code, String fileName) {
public static void launchCodeEditor(String code, String fileName, String mimeType, BiConsumer<byte[], String> callback) {
editor.setCode(code, fileName);
editor.setCallback(callback);
editorStage.show();
editorStage.setTitle(fileName);
if (LuaParser.isLuaFile(fileName)) {
editor.setMode("text/x-lua");
} else if (ObjParser.isObjFile(fileName)) {
editor.setMode("");
} else if (SvgParser.isSvgFile(fileName)) {
editor.setMode("text/html");
} else if (TextParser.isTxtFile(fileName)) {
editor.setMode("");
}
editor.setMode(mimeType);
}
public static void closeCodeEditor() {

Wyświetl plik

@ -13,11 +13,15 @@ import org.w3c.dom.Element;
import sh.ball.audio.FrequencyAnalyser;
import sh.ball.audio.effect.*;
import sh.ball.audio.engine.AudioDevice;
import sh.ball.gui.Gui;
import sh.ball.gui.components.EffectComponentGroup;
import sh.ball.parser.lua.LuaExecutor;
import sh.ball.parser.lua.LuaParser;
import sh.ball.shapes.Shape;
import sh.ball.shapes.Vector2;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -29,6 +33,8 @@ public class EffectsController implements Initializable, SubController {
private static final int DEFAULT_SAMPLE_RATE = 192000;
private final LuaExecutor executor = new LuaExecutor(LuaExecutor.STANDARD_GLOBALS);
private final WobbleEffect wobbleEffect;
private final PerspectiveEffect perspectiveEffect;
private final TranslateEffect translateEffect;
@ -88,10 +94,12 @@ public class EffectsController implements Initializable, SubController {
private Button resetRotationButton;
@FXML
private Button resetPerspectiveRotationButton;
@FXML
private Button depthFunctionButton;
public EffectsController() {
this.wobbleEffect = new WobbleEffect(DEFAULT_SAMPLE_RATE);
this.perspectiveEffect = new PerspectiveEffect();
this.perspectiveEffect = new PerspectiveEffect(executor);
this.translateEffect = new TranslateEffect(DEFAULT_SAMPLE_RATE, 1, new Vector2());
this.rotateEffect = new RotateEffect(DEFAULT_SAMPLE_RATE);
}
@ -237,6 +245,14 @@ public class EffectsController implements Initializable, SubController {
rotateSpeed3D.controller.slider.setValue(0);
perspectiveEffect.resetRotation();
});
String script = "return { x, y, z }";
executor.setScript(script);
depthFunctionButton.setOnAction(e -> Gui.launchCodeEditor(script, "3D Perspective Effect Depth Function", "text/x-lua", this::updateDepthFunction));
}
private void updateDepthFunction(byte[] fileData, String fileName) {
executor.setScript(new String(fileData, StandardCharsets.UTF_8));
}
private List<EffectComponentGroup> effects() {

Wyświetl plik

@ -4,10 +4,15 @@ import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.event.Event;
import javafx.scene.control.*;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.SVGPath;
@ -61,6 +66,7 @@ import sh.ball.parser.lua.LuaParser;
import sh.ball.parser.obj.ObjFrameSettings;
import sh.ball.parser.obj.ObjParser;
import sh.ball.parser.ParserFactory;
import sh.ball.parser.svg.SvgParser;
import sh.ball.parser.txt.FontStyle;
import sh.ball.shapes.Shape;
import sh.ball.shapes.ShapeFrameSource;
@ -142,6 +148,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
@FXML
private MenuItem openProjectMenuItem;
@FXML
private Menu audioMenu;
@FXML
private Menu recentProjectMenu;
@FXML
private MenuItem saveProjectMenuItem;
@ -184,6 +192,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
@FXML
private ComboBox<AudioDevice> deviceComboBox;
@FXML
private CustomMenuItem audioDeviceMenuItem;
@FXML
private Slider brightnessSlider;
@FXML
private CustomMenuItem recordLengthMenuItem;
@ -1397,7 +1407,14 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
void openCodeEditor() {
String code = new String(openFiles.get(currentFrameSource), StandardCharsets.UTF_8);
closeCodeEditor();
launchCodeEditor(code, frameSourcePaths.get(currentFrameSource));
String name = frameSourcePaths.get(currentFrameSource);
String mimeType = "";
if (LuaParser.isLuaFile(name)) {
mimeType = "text/x-lua";
} else if (SvgParser.isSvgFile(name)) {
mimeType = "text/html";
}
launchCodeEditor(code, frameSourcePaths.get(currentFrameSource), mimeType, this::updateFileData);
}
private void updateTitle(String message, String projectName) {

Wyświetl plik

@ -0,0 +1,200 @@
package sh.ball.parser.lua;
import org.luaj.vm2.*;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.lib.jse.JsePlatform;
import javax.script.ScriptException;
import java.io.StringReader;
import java.util.*;
import java.util.logging.Level;
import static sh.ball.gui.Gui.logger;
public class LuaExecutor {
public static final Globals STANDARD_GLOBALS = JsePlatform.standardGlobals();
static {
org.luaj.vm2.luajc.LuaJC.install(STANDARD_GLOBALS);
}
private final Globals globals;
private final Map<LuaString, LuaValue> bindings = new HashMap<>();
private final Set<LuaString> programDefinedVariables = new HashSet<>();
private LuaFunction lastWorkingFunction;
private String lastWorkingTextScript;
private LuaFunction function;
private String textScript;
private long step = 1;
public LuaExecutor(Globals globals) {
this.globals = globals;
}
public void setScript(String script) {
LuaFunction f = LuaExecutor.STANDARD_GLOBALS.load(new StringReader(script), "script").checkfunction();
setFunction(script, f);
}
private void setFunction(String textScript, LuaFunction function) {
if (lastWorkingFunction == null) {
lastWorkingFunction = function;
lastWorkingTextScript = textScript;
}
this.function = function;
this.textScript = textScript;
}
public LuaValue execute() {
try {
boolean updatedFile = false;
globals.setmetatable(new BindingsMetatable(bindings));
bindings.put(LuaValue.valueOf("step"), LuaValue.valueOf((double) step));
LuaValue result;
try {
result = (LuaValue) LuaExecutor.eval(function, globals);
if (!lastWorkingTextScript.equals(textScript)) {
lastWorkingFunction = function;
lastWorkingTextScript = textScript;
updatedFile = true;
}
} catch (Exception e) {
logger.log(Level.INFO, e.getMessage(), e);
result = (LuaValue) LuaExecutor.eval(lastWorkingFunction, globals);
}
step++;
if (updatedFile) {
// reset variables
step = 1;
List<LuaString> variablesToRemove = new ArrayList<>();
bindings.keySet().forEach(name -> {
if (!programDefinedVariables.contains(name)) {
variablesToRemove.add(name);
}
});
variablesToRemove.forEach(bindings::remove);
}
return result;
} catch (Exception e) {
logger.log(Level.INFO, e.getMessage(), e);
}
return LuaValue.NIL;
}
public void setVariable(String variableName, Object value) {
LuaString name = LuaValue.valueOf(variableName);
programDefinedVariables.add(name);
bindings.put(name, toLua(value));
}
public void resetStep() {
step = 1;
}
/*
MIT License
Copyright (c) 2007 LuaJ. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit p ersons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------
The below functions have all been modified by James Ball to optimise Lua parsing
on machines with poorer performance.
*/
static class BindingsMetatable extends LuaTable {
BindingsMetatable(Map<LuaString, LuaValue> bindings) {
this.rawset(LuaValue.INDEX, new TwoArgFunction() {
public LuaValue call(LuaValue table, LuaValue key) {
LuaValue value = bindings.get(key.checkstring());
if (value == null) {
return LuaValue.NIL;
} else {
return value;
}
}
});
this.rawset(LuaValue.NEWINDEX, new ThreeArgFunction() {
public LuaValue call(LuaValue table, LuaValue key, LuaValue value) {
if (value == null || value.type() == LuaValue.TNIL) {
bindings.remove(key.checkstring());
} else {
bindings.put(key.checkstring(), value);
}
return LuaValue.NONE;
}
});
}
}
static private LuaValue toLua(Object javaValue) {
return javaValue == null? LuaValue.NIL:
javaValue instanceof LuaValue? (LuaValue) javaValue:
CoerceJavaToLua.coerce(javaValue);
}
static private Object toJava(LuaValue luajValue) {
return switch (luajValue.type()) {
case LuaValue.TNIL -> null;
case LuaValue.TSTRING -> luajValue.tojstring();
case LuaValue.TUSERDATA -> luajValue.checkuserdata(Object.class);
case LuaValue.TNUMBER -> luajValue.isinttype() ?
(Object) luajValue.toint() :
(Object) luajValue.todouble();
default -> luajValue;
};
}
static private Object toJava(Varargs v) {
final int n = v.narg();
switch (n) {
case 0: return null;
case 1: return toJava(v.arg1());
default:
Object[] o = new Object[n];
for (int i=0; i<n; ++i)
o[i] = toJava(v.arg(i+1));
return o;
}
}
static private Object eval(LuaFunction f, Globals g) throws ScriptException {
try {
f = f.getClass().newInstance();
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
throw new ScriptException(e);
}
f.initupvalue1(g);
return toJava(f.invoke(LuaValue.NONE));
}
}

Wyświetl plik

@ -1,25 +1,15 @@
package sh.ball.parser.lua;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
import sh.ball.audio.FrameSource;
import sh.ball.parser.FileParser;
import sh.ball.shapes.Vector2;
import javax.script.*;
import java.io.*;
import java.util.stream.Collectors;
public class LuaParser extends FileParser<FrameSource<Vector2>> {
private static final Globals globals = JsePlatform.standardGlobals();
static {
org.luaj.vm2.luajc.LuaJC.install(globals);
}
private final LuaSampleSource sampleSource = new LuaSampleSource(globals);
private final LuaSampleSource sampleSource = new LuaSampleSource(LuaExecutor.STANDARD_GLOBALS);
private String script;
@ -35,10 +25,7 @@ public class LuaParser extends FileParser<FrameSource<Vector2>> {
@Override
public FrameSource<Vector2> parse() throws Exception {
LuaFunction f = globals.load(new StringReader(script), "script").checkfunction();
sampleSource.setFunction(script, f);
sampleSource.setScript(script);
return sampleSource;
}

Wyświetl plik

@ -18,69 +18,21 @@ import static sh.ball.gui.Gui.logger;
public class LuaSampleSource implements FrameSource<Vector2> {
private final Globals globals;
private final Map<LuaString, LuaValue> bindings = new HashMap<>();
private final Set<LuaString> programDefinedVariables = new HashSet<>();
private LuaFunction lastWorkingFunction;
private String lastWorkingTextScript;
private LuaFunction function;
private String textScript;
private final LuaExecutor executor;
private boolean active = true;
private long step = 1;
public LuaSampleSource(Globals globals) {
this.globals = globals;
this.executor = new LuaExecutor(globals);
}
public void setFunction(String textScript, LuaFunction function) {
if (lastWorkingFunction == null) {
lastWorkingFunction = function;
lastWorkingTextScript = textScript;
}
this.function = function;
this.textScript = textScript;
public void setScript(String textScript) {
executor.setScript(textScript);
}
@Override
public Vector2 next() {
try {
boolean updatedFile = false;
globals.setmetatable(new BindingsMetatable(bindings));
bindings.put(LuaValue.valueOf("step"), LuaValue.valueOf((double) step));
LuaValue result;
try {
result = (LuaValue) LuaSampleSource.eval(function, globals);
if (!lastWorkingTextScript.equals(textScript)) {
lastWorkingFunction = function;
lastWorkingTextScript = textScript;
updatedFile = true;
}
} catch (Exception e) {
logger.log(Level.INFO, e.getMessage(), e);
result = (LuaValue) LuaSampleSource.eval(lastWorkingFunction, globals);
}
step++;
if (updatedFile) {
// reset variables
step = 1;
List<LuaString> variablesToRemove = new ArrayList<>();
bindings.keySet().forEach(name -> {
if (!programDefinedVariables.contains(name)) {
variablesToRemove.add(name);
}
});
variablesToRemove.forEach(bindings::remove);
}
return new Vector2(result.get(1).checkdouble(), result.get(2).checkdouble());
} catch (Exception e) {
logger.log(Level.INFO, e.getMessage(), e);
}
return new Vector2();
LuaValue result = executor.execute();
return new Vector2(result.get(1).checkdouble(), result.get(2).checkdouble());
}
@Override
@ -107,110 +59,10 @@ public class LuaSampleSource implements FrameSource<Vector2> {
}
public void setVariable(String variableName, Object value) {
programDefinedVariables.add(LuaValue.valueOf(variableName));
bindings.put(LuaValue.valueOf(variableName), toLua(value));
executor.setVariable(variableName, value);
}
public void resetStep() {
step = 1;
}
/*
MIT License
Copyright (c) 2007 LuaJ. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit p ersons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------
The below functions have all been modified by James Ball to optimise Lua parsing
on machines with poorer performance.
*/
static class BindingsMetatable extends LuaTable {
BindingsMetatable(Map<LuaString, LuaValue> bindings) {
this.rawset(LuaValue.INDEX, new TwoArgFunction() {
public LuaValue call(LuaValue table, LuaValue key) {
LuaValue value = bindings.get(key.checkstring());
if (value == null) {
return LuaValue.NIL;
} else {
return value;
}
}
});
this.rawset(LuaValue.NEWINDEX, new ThreeArgFunction() {
public LuaValue call(LuaValue table, LuaValue key, LuaValue value) {
if (value == null || value.type() == LuaValue.TNIL) {
bindings.remove(key.checkstring());
} else {
bindings.put(key.checkstring(), value);
}
return LuaValue.NONE;
}
});
}
}
static private LuaValue toLua(Object javaValue) {
return javaValue == null? LuaValue.NIL:
javaValue instanceof LuaValue? (LuaValue) javaValue:
CoerceJavaToLua.coerce(javaValue);
}
static private Object toJava(LuaValue luajValue) {
return switch (luajValue.type()) {
case LuaValue.TNIL -> null;
case LuaValue.TSTRING -> luajValue.tojstring();
case LuaValue.TUSERDATA -> luajValue.checkuserdata(Object.class);
case LuaValue.TNUMBER -> luajValue.isinttype() ?
(Object) luajValue.toint() :
(Object) luajValue.todouble();
default -> luajValue;
};
}
static private Object toJava(Varargs v) {
final int n = v.narg();
switch (n) {
case 0: return null;
case 1: return toJava(v.arg1());
default:
Object[] o = new Object[n];
for (int i=0; i<n; ++i)
o[i] = toJava(v.arg(i+1));
return o;
}
}
static private Object eval(LuaFunction f, Globals g) throws ScriptException {
try {
f = f.getClass().newInstance();
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
throw new ScriptException(e);
}
f.initupvalue1(g);
return toJava(f.invoke(LuaValue.NONE));
executor.resetStep();
}
}

Wyświetl plik

@ -85,7 +85,12 @@
</children>
</AnchorPane>
<EffectComponentGroup fx:id="depthScale" increment="0.005" label="depthScale" majorTickUnit="0.1" max="1.0" min="0.0" name="3D Perspective" type="DEPTH_3D" value="1.0" />
<EffectComponentGroup fx:id="zPos" alwaysEnabled="true" increment="0.005" label="zPos" max="1.0" name="3D Distance" type="Z_POS_3D" value="0.1" />
<AnchorPane prefHeight="34.0" prefWidth="602.0">
<children>
<Button fx:id="depthFunctionButton" layoutX="232.0" layoutY="1.0" mnemonicParsing="false" text="Modify Depth Function" />
</children>
</AnchorPane>
<EffectComponentGroup fx:id="zPos" alwaysEnabled="true" increment="0.005" label="zPos" max="1.0" name="3D Distance (z)" type="Z_POS_3D" value="0.1" />
<EffectComponentGroup fx:id="rotateSpeed3D" alwaysEnabled="true" increment="0.005" label="rotateSpeed3d" majorTickUnit="0.2" max="1.0" min="-1.0" name="3D Rotate speed" type="ROTATE_SPEED_3D" value="0.0" />
<EffectComponentGroup fx:id="rotateX" alwaysEnabled="true" increment="0.01" label="imageRotateX" majorTickUnit="0.2" max="1.0" min="-1.0" name="Rotate x" type="ROTATE_X" value="1.0" />
<EffectComponentGroup fx:id="rotateY" alwaysEnabled="true" increment="0.01" label="imageRotateY" majorTickUnit="0.2" max="1.0" min="-1.0" name="Rotate y" type="ROTATE_Y" value="1.0" />

Wyświetl plik

@ -39,11 +39,11 @@
</MenuItem>
</items>
</Menu>
<Menu mnemonicParsing="false" text="Audio">
<Menu fx:id="audioMenu" mnemonicParsing="false" text="Audio">
<items>
<CustomMenuItem hideOnClick="false" mnemonicParsing="false" text="Audio Device">
<CustomMenuItem fx:id="audioDeviceMenuItem" hideOnClick="false" mnemonicParsing="false" text="Audio Device">
<content>
<AnchorPane>
<AnchorPane focusTraversable="true">
<children>
<ComboBox fx:id="deviceComboBox" prefHeight="26.0" prefWidth="376.0" />
</children>