[SOLVED] How to use Custom Camera?

pspeed
Awesome dodge. Pick the parts of the post You can aggresively comment with Your classic “why this why that” instead of those require You to put an actual effort into an answer. Oh right… I forgot… You expect payment for Your help…

Why do You work on OpenSource Project then? I mean really? Isn’t “better future, great free tools and cookies for everyone” part of the deal?

Or if You simply dislike me (not the whole idea of helping which seems to be the case) why won’t You create good tutorials (I mean “zero to hero” tutorials that will explain every possible detail to people who see jMonkey for the first time in life). You’d have like 10000 times less repetetive questions here…

david
Here’s my code:

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.InputManager;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.math.Vector3f;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Node;
import com.jme3.scene.control.CameraControl;

public class AppStateTest1 extends AbstractAppState {

    private Node rootNode;
    private InputManager inputManager;

    public AppStateTest1(SimpleApplication app){
        this.rootNode     = app.getRootNode();
        this.inputManager = app.getInputManager();
    }

    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);

        initKeys();

        cameranode = new CameraNode("Main Camera", app.getCamera());
        cameranode.setControlDir(CameraControl.ControlDirection.SpatialToCamera);
        rootNode.attachChild(cameranode);
        cameranode.setLocalTranslation(0, -2, -20);
    }

    private CameraNode cameranode;

    private Boolean drag=false;

    private void initKeys() {
        inputManager.addMapping("Drag", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        inputManager.addMapping("Left", new MouseAxisTrigger(MouseInput.AXIS_X, true));
        inputManager.addMapping("Right", new MouseAxisTrigger(MouseInput.AXIS_X, false));
        inputManager.addMapping("Up", new MouseAxisTrigger(MouseInput.AXIS_Y, true));
        inputManager.addMapping("Down", new MouseAxisTrigger(MouseInput.AXIS_Y, false));

        inputManager.addListener(analogListener,"Left", "Right", "Up", "Down");
        inputManager.addListener(actionListener,"Drag");
    }
    private ActionListener actionListener = new ActionListener() {
        public void onAction(String name, boolean keyPressed, float tpf) {
            if (name.equals("Drag") && keyPressed) {
                drag = true;
            }
            if (name.equals("Drag") && !keyPressed) {
                drag = false;
            }
        }
    };
    private AnalogListener analogListener = new AnalogListener() {
        public void onAnalog(String name, float value, float tpf) {
            int speed = 25;
            if (drag) {
                if (name.equals("Right")) {
                    Vector3f v = cameranode.getLocalTranslation();
                    cameranode.setLocalTranslation(v.x + value * speed, v.y, v.z);
                }
                if (name.equals("Left")) {
                    Vector3f v = cameranode.getLocalTranslation();
                    cameranode.setLocalTranslation(v.x - value * speed, v.y, v.z);
                }
                if (name.equals("Up")) {
                    Vector3f v = cameranode.getLocalTranslation();
                    cameranode.setLocalTranslation(v.x, v.y + value * speed, v.z);
                }
                if (name.equals("Down")) {
                    Vector3f v = cameranode.getLocalTranslation();
                    cameranode.setLocalTranslation(v.x, v.y - value * speed, v.z);
                }
            }
        }
    };
}

But it doesn’t explain why I need another option because it works (like a charm actually).
As I said to our dearest developer above, I’m just exploring possibilities so I can make a decision what to use based on actual comparison. When I created this topic I hoped for several ready to use examples of solutions to choose from, guess that was too big of an expectation :frowning:

1 Like
  1. few comments about AppStateTest1:
  • Don’t inject SimpleApplication into the constructor. The common usage is like :
   @Override
   public void initialize(AppStateManager stateManager, Application app) {
       super.initialize(stateManager, app);
       SimpleApplication app0 = (SimpleApplication) app;
       this.rootNode     = app0.getRootNode();
       this.inputManager = app0.getInputManager();
  • AppState is dettachable (eg on loading screen you don’t want to control the camera,…), so next step support the other part of the api (setEnable, dispose,…)
  1. An other approach, create your own class with the setup function that will reproduce the AppState lifecycle, but that can be more api friendly with your DI lib or any code you use to manage “service” lifecyle. but integration with jME constraint require better knowledge of the jME API than what you have.

Tips: to you can use app.enqueue(…) to do job the jME thread without the need to override SimpleApplication methods (init, update). I use it to attach/detach AppState, run task in jME from service that are not managed by jME,…

AppState is the way to follow. pspeed did a great API with this piece of cake. he has some improvements in standby for next version of jME. AppState + enqueue are my “secret” sauce to modularize my jME apps.