Well I already took a look at the docs but they don’t tell me how to build a plugin on top of the SceneComposer and its existing tools. Okay there apparently is an OffViewPanel (which is now named OffScenePanel?) but when I tried it, I simply saw a normal Swing panel. There is a SceneToolController, but is it just a controller or will it just provide the methods used by the SceneComposer? How could I get the UI of the SceneComposer to build on top of it?
This is the code I tried for just rendering a scene and all I see is an empty swing panel which is not black like it was if it showed the scene (and my jLabel):
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package net.softwarepage.nbplugins.cinematiceditor;
import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.core.scene.PreviewRequest;
import com.jme3.gde.core.scene.SceneApplication;
import com.jme3.gde.core.scene.SceneListener;
import com.jme3.gde.core.scene.SceneRequest;
import com.jme3.gde.core.scene.controller.SceneToolController;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.windows.TopComponent;
import org.openide.util.NbBundle.Messages;
/**
* Top component which displays something.
*/
@ConvertAsProperties(
dtd = "-//net.softwarepage.nbplugins.cinematiceditor//Main//EN",
autostore = false)
@TopComponent.Description(
preferredID = "MainTopComponent",
//iconBase="SET/PATH/TO/ICON/HERE",
persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "editor", openAtStartup = true)
@ActionID(category = "Window", id = "net.softwarepage.nbplugins.cinematiceditor.MainTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)
@TopComponent.OpenActionRegistration(
displayName = "#CTL_MainAction",
preferredID = "MainTopComponent")
@Messages({
"CTL_MainAction=Main",
"CTL_MainTopComponent=Main Window",
"HINT_MainTopComponent=This is a Main window"
})
public final class MainTopComponent extends TopComponent implements SceneListener {
com.jme3.scene.Node rootNode = new com.jme3.scene.Node("MyRootNode");
private ProjectAssetManager assetManager;
private SceneApplication app;
public MainTopComponent() {
initComponents();
setName(Bundle.CTL_MainTopComponent());
setToolTipText(Bundle.HINT_MainTopComponent());
registerSceneListener();
requestScene();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
offScenePanel1 = new com.jme3.gde.core.scene.OffScenePanel();
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, "jLabel1");
javax.swing.GroupLayout offScenePanel1Layout = new javax.swing.GroupLayout(offScenePanel1);
offScenePanel1.setLayout(offScenePanel1Layout);
offScenePanel1Layout.setHorizontalGroup(
offScenePanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
offScenePanel1Layout.setVerticalGroup(
offScenePanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 100, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(offScenePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(0, 346, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(20, 20, 20)
.addComponent(offScenePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jLabel1)
.addContainerGap(148, Short.MAX_VALUE))
);
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private com.jme3.gde.core.scene.OffScenePanel offScenePanel1;
// End of variables declaration
@Override
public void componentOpened() {
}
private void registerSceneListener() {
app = SceneApplication.getApplication();
app.addSceneListener(this);
}
private void requestScene() {
//create a jmeNode from the rootNode using the NodeUtility
JmeNode jmeNode = NodeUtility.createNode(rootNode);
assetManager = jmeNode.getLookup().lookup(ProjectAssetManager.class);
System.out.println(assetManager);
//create the scene request
SceneRequest request = new SceneRequest(this, jmeNode, assetManager);
//request the scene
app.openScene(request);
}
@Override
public void sceneOpened(SceneRequest request) {
//check if its our request
if (request.getRequester() == this) {
offScenePanel1.attach(rootNode);
}
}
@Override
public void sceneClosed(SceneRequest request) {
if (request.getRequester() == this) {
//we have to close the scene, any operations on the scene have to be done via Callables
}
}
@Override
public void componentClosed() {
// TODO add custom code on component closing
}
void writeProperties(java.util.Properties p) {
// better to version settings since initial version as advocated at
// http://wiki.apidesign.org/wiki/PropertyFiles
p.setProperty("version", "1.0");
// TODO store your settings
}
void readProperties(java.util.Properties p) {
String version = p.getProperty("version");
// TODO read your settings according to their version
}
@Override
public void previewCreated(PreviewRequest pr) {
}
}
There’s not much motiviation for creating a plugin because there’s always the option to do it as an other application, so you should make it as easy as possible. I’ve now been searching for some time, even looked in the source code and couldn’t find a way to display a scene with the exisitng camera controls without rewriting everything.
Of course I didn’t search and search and search because before doing that one would probably just create an own application, but I did spend some time on it.