JM3 and Canvas and Input, now with testcase

Hello,

I am currently trying to implement an application with visualisation done in JME. I need however to be able to use the mouse to select items in the 3d view.

Using the jme inputmanager gives me always a Nullpointer when adding a InputListener.

[java]

java.lang.NullPointerException

at zFarmerApplication.Applications.ZAppDataStoragePrograms.Filters.VisualisationFilter3dPlugin.initialize(VisualisationFilter3dPlugin.java:61)

at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:219)

at com.jme3.app.state.AppStateManager.update(AppStateManager.java:249)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:241)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)

at com.jme3.system.lwjgl.LwjglCanvas.runLoop(LwjglCanvas.java:227)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)

at java.lang.Thread.run(Thread.java:662)

[/java]



The next idea was to attach an MouseListener and a MouseMotionListener to the Panel on which JME drawn.



[java]

System.out.println(“Registering Listener 1”);

((MainGui)this.app.getApplication(MainGui.class)).getPanel3dView().addMouseListener(new MouseListener() {



public void mouseClicked(MouseEvent e) {



}



public void mousePressed(MouseEvent e) {

mouseClick(true);

}



public void mouseReleased(MouseEvent e) {

mouseClick(false);

}



public void mouseEntered(MouseEvent e) {

setCurrentMouseOverState(true);

}



public void mouseExited(MouseEvent e) {

setCurrentMouseOverState(false);

}

});

System.out.println(“Registering Listener 2”);

((MainGui)this.app.getApplication(MainGui.class)).getPanel3dView().addMouseMotionListener(new MouseMotionListener() {



public void mouseDragged(MouseEvent e) {

//throw new UnsupportedOperationException(“Not supported yet.”);

}



public void mouseMoved(MouseEvent e) {

setCurrentMouseCoordinates(new Vector2f(e.getPoint().x,e.getPoint().y));

//throw new UnsupportedOperationException(“Not supported yet.”);

}

});

System.out.println(“Registering Listener Done”);

[/java]



However, it seems JME ‘eats’ the events, since it works perfectly on every other panel then the 3dView.



What the correct approach dooing this?

Post the code surrounding “VisualisationFilter3dPlugin.java:61” so people can see what is null there.

Line 61 was only the try of adding a jme actionListener:

[java]

this.app3d.getInputManager().addListener(new ActionListener() {



public void onAction(String name, boolean isPressed, float tpf) {

// throw new UnsupportedOperationException("Not supported yet.");

}

}, new String[]{"Click"});

[/java]

app3d is of course the SimpleApplication

You will have to call that after the app has been started and after application.initialize() has been called. So in simpleInitApp()

Hello, thank you for the fast responses, the call above is made inside the ‘initialize’ function of an AbstractAppState. So i strongly assume that at this point the SimpleApplication is already up and running. Here is the whole code of this class (its just a prototype so theres still nothing nicely done.



[java]

/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    package zFarmerApplication.Applications.ZAppDataStoragePrograms.Filters;



    import Gui.MainGui;

    import Managers.ApplicationManager;

    import com.jme3.app.Application;

    import com.jme3.app.SimpleApplication;

    import com.jme3.app.state.AbstractAppState;

    import com.jme3.app.state.AppStateManager;

    import com.jme3.input.controls.ActionListener;

    import com.jme3.material.Material;

    import com.jme3.math.Vector2f;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Node;

    import com.jme3.scene.shape.Quad;

    import java.awt.event.MouseEvent;

    import java.awt.event.MouseListener;

    import java.awt.event.MouseMotionListener;



    import java.util.List;

    import java.util.concurrent.Callable;



    import zFarmerApplication.Applications.ZApp3d;

    import zFarmerApplication.Applications.ZAppDataStoragePrograms.DataObjects.Wiese;





    /**

    *
  • @author Michael

    /

    public class VisualisationFilter3dPlugin extends AbstractAppState{

    float minX=Integer.MAX_VALUE,maxX=Integer.MIN_VALUE,minY=Integer.MAX_VALUE,maxY=Integer.MIN_VALUE;

    private SimpleApplication app3d;

    private ApplicationManager app;

    Node guiNode;

    VisualisationFilter filter;

    public VisualisationFilter3dPlugin(ApplicationManager app,VisualisationFilter filter) {

    this.app = app;

    ((ZApp3d) app.getApplication(ZApp3d.class)).getApplication().getStateManager().attach(this);

    this.guiNode = new Node();

    this.filter=filter;



    }



    @Override

    public void initialize(AppStateManager stateManager, Application app) {

    super.initialize(stateManager, app);

    this.app3d = (SimpleApplication) app;



    this.app3d.getGuiNode().attachChild(guiNode);

    guiNode.setLocalTranslation(5, 5, 0);

    filter.showGFX();

    this.app3d.getInputManager().addListener(new ActionListener() {



    public void onAction(String name, boolean isPressed, float tpf) {

    // throw new UnsupportedOperationException(“Not supported yet.”);

    }

    }, new String[]{“Click”});





    System.out.println(“Registering Listener 1”);

    ((MainGui)this.app.getApplication(MainGui.class)).getPanel3dView().addMouseListener(new MouseListener() {



    public void mouseClicked(MouseEvent e) {



    }



    public void mousePressed(MouseEvent e) {

    mouseClick(true);

    }



    public void mouseReleased(MouseEvent e) {

    mouseClick(false);

    }



    public void mouseEntered(MouseEvent e) {

    setCurrentMouseOverState(true);

    }



    public void mouseExited(MouseEvent e) {

    setCurrentMouseOverState(false);

    }

    });

    System.out.println(“Registering Listener 2”);

    ((MainGui)this.app.getApplication(MainGui.class)).getPanel3dView().addMouseMotionListener(new MouseMotionListener() {



    public void mouseDragged(MouseEvent e) {

    //throw new UnsupportedOperationException(“Not supported yet.”);

    }



    public void mouseMoved(MouseEvent e) {

    setCurrentMouseCoordinates(new Vector2f(e.getPoint().x,e.getPoint().y));

    //throw new UnsupportedOperationException(“Not supported yet.”);

    }

    });

    System.out.println(“Registering Listener Done”);

    }

    @Override

    public void update(float tpf){

    float screenXmult=app3d.getCamera().getWidth()/maxX;

    float screenYmult=app3d.getCamera().getHeight()/maxY;

    float maxMult=Math.min(screenXmult, screenYmult);

    guiNode.setLocalScale(maxMult
    0.9f);

    }

    public void updateWiesen(final List<Wiese> wiesen){

    Callable function = new Callable() {



    public Object call() throws Exception {

    minX=Integer.MAX_VALUE;maxX=Integer.MIN_VALUE;minY=Integer.MAX_VALUE;maxY=Integer.MIN_VALUE;

    for(Wiese wiese:wiesen){

    Quad q = new Quad(wiese.getWidth(), wiese.getHeight());

    Geometry g = new Geometry(wiese.getName(), q);

    Material mat = app3d.getAssetManager().loadMaterial(“Materials/WiesenMaterial.j3m”);

    g.setMaterial(mat);

    g.setLocalTranslation(wiese.getXpos(), wiese.getYpos(), -10);

    minX=Math.min(minX, wiese.getXpos());

    minY=Math.min(minY, wiese.getYpos());

    maxX=Math.max(maxX, wiese.getXpos()+wiese.getWidth());

    maxY=Math.max(maxY, wiese.getYpos()+wiese.getHeight());

    guiNode.attachChild(g);

    }

    float screenXmult=app3d.getCamera().getWidth()/maxX;

    float screenYmult=app3d.getCamera().getHeight()/maxY;

    float maxMult=Math.min(screenXmult, screenYmult);

    guiNode.setLocalScale(maxMult*0.9f);



    return true;

    }



    };

    this.app3d.enqueue(function);

    }



    public void setCurrentMouseCoordinates(Vector2f vector){

    System.out.println("MouseCoord State: "+vector.toString());

    }

    public void setCurrentMouseOverState(boolean state){

    System.out.println("MouseOver State: "+state);

    }

    public void mouseClick(boolean pressed){

    System.out.println("MouseClick State: "+pressed);

    }

    }

    [/java]



    The other way, if i do not want to use the default JME inputManager, is there a way to disable the ‘eating’ of actions?

inputManager.clearMappings()

But the fact that an NPE is raised when you try an get the inputManager is a big red flag. Step through the debugger and see what is up when you try and get it from the app.

Ok, i have managed to track down the the NPE issue. Since i am using

[java]

AppSettings CustomSettings = new AppSettings(true);

CustomSettings.setUseInput(false);

[/java]

as settings, no inputManager gets started, however the actions are still not getting fired on the JPanel :frowning:

Hello again: here is a testcase showing my problem:

As you can see, the ActionEvent get’s never fired.

[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.system.AppSettings;

import com.jme3.system.JmeCanvasContext;

import java.awt.Frame;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import javax.swing.JFrame;



/**

  • test
  • @author normenhansen

    */

    public class Main {



    public void Main() {

    }



    public void init() {

    java.awt.EventQueue.invokeLater(new Runnable() {



    public void run() {



    JFrame ApplicationFrame = new JFrame("ZFarmer 0.0.1");

    ApplicationFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    ApplicationFrame.setExtendedState(Frame.MAXIMIZED_BOTH);

    Jme gfx = new Jme();



    AppSettings CustomSettings = new AppSettings(true);

    CustomSettings.setUseInput(false);

    CustomSettings.setWidth(640);

    CustomSettings.setHeight(480);

    gfx.setPauseOnLostFocus(false);



    gfx.setSettings(CustomSettings);

    gfx.createCanvas();

    JmeCanvasContext gfx_context = (JmeCanvasContext) gfx.getContext();



    gfx_context.setSystemListener(gfx);

    gfx_context.setSettings(CustomSettings);

    ApplicationFrame.add(gfx_context.getCanvas());



    ApplicationFrame.addMouseListener(new MouseListener(){



    public void mouseClicked(MouseEvent e) {

    System.out.println("Click little monkey, Click Click Click");

    // throw new UnsupportedOperationException("Not supported yet.");

    }



    public void mousePressed(MouseEvent e) {

    //throw new UnsupportedOperationException("Not supported yet.");

    }



    public void mouseReleased(MouseEvent e) {

    //throw new UnsupportedOperationException("Not supported yet.");

    }



    public void mouseEntered(MouseEvent e) {

    //throw new UnsupportedOperationException("Not supported yet.");

    }



    public void mouseExited(MouseEvent e) {

    //throw new UnsupportedOperationException("Not supported yet.");

    }

    });



    ApplicationFrame.setVisible(true);



    }

    });

    }



    public static void main(String[] args) {

    Main main = new Main();

    main.init();

    }



    public class Jme extends SimpleApplication {



    @Override

    public void simpleInitApp() {

    }

    }

    }



    [/java]

Ok, at least i managed to use the jme way of input handling.

The issue here why it did not work in the beginning is that:

[java]

this.inputManager.setCursorVisible(false);

[/java]

needs to be set to false to show the cursor. May be my personal missinterpreting of the term, but for me, setCursorVisible(true) should make the cursor visible :stuck_out_tongue: