In this code I have a Subscene
with 3d features enabled. I add camera and meshviews at runtime, but I want to put the camera in FXML because I don´t need to change it at runtime. How can I do that
?
<SubScene fx:id="viewer3d" depthBuffer="true" fill="#3389de" height="600.0" width="600.0">
<root>
<Region />
</root>
<antiAliasing>
<SceneAntialiasing fx:constant="BALANCED" />
If you're okay with the fixedEyeAtCameraZero
property being false then all you need is:
<camera>
<!-- make sure to import the class (or use fully qualified name) -->
<PerspectiveCamera/>
</camera>
Nested in the SubScene
element.
However, if you want the aforementioned property to be true then unfortunately you have to write some code. Said property can only be set during construction, but the constructor does not annotate its parameter with @NamedArg
. Meaning the following:
<camera>
<PerspectiveCamera fixedEyeAtCameraZero="true"/>
</camera>
Will fail because the FXMLLoader
will not know what to do with the attribute. In this case, there are two options:
Instead of defining the camera in the FXML file, create the camera and set it on the sub-scene in code (e.g., in the controllers initialize
method).
I find this option preferable, but that is just my opinion.
Continue defining the camera in the FXML file and implement a Builder
and BuilderFactory
.
Here is an example implementation. Note the example Builder
is extremely simple. It is only implemented to allow setting the fixedEyeAtCameraZero
property. Trying to set any other property, which would have otherwise worked without registering this builder, will now fail. You can add other getters and setters as needed. Or, perhaps easier, you could have the builder implement Map<String, Object>
and appropriately implement the put
method.
Builder
import javafx.scene.PerspectiveCamera;
import javafx.util.Builder;
public class PerspectiveCameraBuilder implements Builder<PerspectiveCamera> {
private boolean fixedEyeAtCameraZero;
public boolean isFixedEyeAtCameraZero() {
return fixedEyeAtCameraZero;
}
public void setFixedEyeAtCameraZero(boolean fixedEyeAtCameraZero) {
this.fixedEyeAtCameraZero = fixedEyeAtCameraZero;
}
@Override
public PerspectiveCamera build() {
return new PerspectiveCamera(fixedEyeAtCameraZero);
}
}
Builder Factory
import javafx.scene.PerspectiveCamera;
import javafx.util.Builder;
import javafx.util.BuilderFactory;
public class MyBuilderFactory implements BuilderFactory {
@Override
public Builder<?> getBuilder(Class<?> type) {
if (type == PerspectiveCamera.class) {
return new PerspectiveCameraBuilder();
}
return null;
}
}
Usage
var loader = new FXMLLoader(...);
loader.setBuilderFactory(new MyBuilderFactory());
// ... load FXML file