[PATCH]Displaying coordinates on SceneComposer and TerrainEditor in SDK

Hello,



When editing scenes, specially complex scenes, you often miss information like spatials position to make sure you are doing the right thing. Although you can easily set the positions with the setLocalTranslation, visual editing is always easier than textually. Please post some feedback whether you like this or not, or if something should be changed to get this effect.



Note that this is the first part for a serious of improvements on the visual editing of the SDK. I plan adding features like regions in scenes, and support for loading/adding objects that are not j3o objects in the scenes, and allow them to have their attributes saved for runtime.



[patch]Index: jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java

===================================================================

— jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java (revision 9945)

+++ jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java (working copy)

@@ -27,6 +27,8 @@

import com.jme3.app.Application;

import com.jme3.app.state.AbstractAppState;

import com.jme3.app.state.AppStateManager;

+import com.jme3.font.BitmapFont;

+import com.jme3.font.BitmapText;

import com.jme3.gde.core.Installer;

import com.jme3.gde.core.scene.SceneApplication;

import com.jme3.gde.core.scene.controller.toolbars.CameraToolbar;

@@ -85,6 +87,9 @@

protected boolean checkReleaseLeft = false;

protected boolean checkReleaseRight = false;

protected boolean shiftModifier = false;

  • protected BitmapText mousePositionText;
  • protected Vector3f coordinates = new Vector3f();
  • protected String coordinatesText = "Coordinates: ";



    public AbstractCameraController(Camera cam, InputManager inputManager) {

    this.cam = cam;

    @@ -112,11 +117,35 @@

    }

    inputManager.addRawInputListener(me);

    inputManager.addListener(me, "MouseAxisX", "MouseAxisY", "MouseAxisX-", "MouseAxisY-", "MouseWheel", "MouseWheel-", "MouseButtonLeft", "MouseButtonMiddle", "MouseButtonRight");
  •            if (mousePositionText != null &amp;&amp; mousePositionText.getParent() == null)<br />
    
  •                SceneApplication.getApplication().getGuiNode().attachChild(mousePositionText);<br />
    

return null;

}

  •    });<br />
    
  • }

    +
  • /**
  • * Call this to active the display of coordinates text on the screen. Call {@link #setCoordinates(com.jme3.math.Vector3f) } to update the coordinates.<br />
    
  • */<br />
    
  • protected void activateCoordinatesText() {
  •    BitmapFont font = SceneApplication.getApplication().getAssetManager().loadFont(&quot;Interface/Fonts/Default.fnt&quot;);<br />
    

+

  •    mousePositionText = new BitmapText(font, false);<br />
    
  •    mousePositionText.setSize(font.getCharSet().getRenderedSize());<br />
    
  •    mousePositionText.setLocalTranslation(0, mousePositionText.getLineHeight(), 0);<br />
    
  •    mousePositionText.setText(coordinatesText);<br />
    
  •    SceneApplication.getApplication().enqueue(new Callable&lt;Object&gt;() {<br />
    
  •        public Object call() throws Exception {<br />
    
  •            SceneApplication.getApplication().getGuiNode().attachChild(mousePositionText);<br />
    
  •            return null;<br />
    
  •        }<br />
    

});

}


  • public void setCoordinates(Vector3f coordinates) {
  •    this.coordinates = coordinates;<br />
    
  • }

    +

    private void addAdditionnalToolbar() {

    SceneViewerTopComponent svtc = SceneViewerTopComponent.findInstance();

    if (svtc != null) {

    @@ -145,6 +174,8 @@

    public Object call() throws Exception {

    inputManager.removeRawInputListener(me);

    inputManager.removeListener(me);
  •            if (mousePositionText != null)<br />
    
  •                mousePositionText.removeFromParent();<br />
    

return null;

}

});

@@ -473,6 +504,8 @@



@Override

public void update(float f) {

  •    if (mousePositionText != null &amp;&amp; coordinates != null)<br />
    
  •        mousePositionText.setText(coordinatesText + coordinates);<br />
    

if (moved) {

// moved, check for drags

if (checkReleaseL || checkReleaseR || checkReleaseM) {

Index: jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java

===================================================================

— jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java (revision 9945)

+++ jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java (working copy)

@@ -24,11 +24,15 @@

*/

package com.jme3.gde.scenecomposer;



+import com.jme3.collision.CollisionResult;

+import com.jme3.collision.CollisionResults;

import com.jme3.gde.core.scene.SceneApplication;

import com.jme3.gde.core.scene.controller.AbstractCameraController;

import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;

import com.jme3.input.KeyInput;

import com.jme3.input.event.KeyInputEvent;

+import com.jme3.input.event.MouseMotionEvent;

+import com.jme3.math.Ray;

import com.jme3.math.Vector2f;

import com.jme3.math.Vector3f;

import com.jme3.renderer.Camera;

@@ -49,6 +53,7 @@

super(cam, SceneApplication.getApplication().getInputManager());

this.jmeRootNode = rootNode;

this.rootNode = rootNode.getLookup().lookup(Node.class);

  •    activateCoordinatesText();<br />
    

}



private boolean isEditButtonEnabled() {

@@ -84,6 +89,36 @@

}



@Override

  • public void onMouseMotionEvent(MouseMotionEvent mme) {
  •    super.onMouseMotionEvent(mme); //To change body of generated methods, choose Tools | Templates.<br />
    

+

  •    Vector3f point = get3DPoint();<br />
    
  •    if (point != null)<br />
    
  •        setCoordinates(point);<br />
    
  • }

    +

    +

    +
  • protected Vector3f get3DPoint() {<br />
    
  •    CollisionResults results = new CollisionResults();<br />
    
  •    Ray ray = new Ray();<br />
    
  •    Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone();<br />
    
  •    Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone();<br />
    
  •    dir.subtractLocal(pos).normalizeLocal();<br />
    
  •    ray.setOrigin(pos);<br />
    
  •    ray.setDirection(dir);<br />
    
  •    rootNode.collideWith(ray, results);<br />
    
  •    if (results == null) {<br />
    
  •        return null;<br />
    
  •    }<br />
    
  •    final CollisionResult result = results.getClosestCollision();<br />
    
  •    if (result == null) {<br />
    
  •        return null;<br />
    
  •    }<br />
    
  •    return result.getContactPoint();<br />
    
  • }

    +
  • @Override

    public void checkClick(int button, boolean pressed) {

    if (button == 0) {

    if (isEditButtonEnabled() && !forceCameraControls) {

    Index: jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java

    ===================================================================

    — jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java (revision 9945)

    +++ jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java (working copy)

    @@ -65,6 +65,8 @@

    public TerrainCameraController(Camera cam) {

    super(cam, SceneApplication.getApplication().getInputManager());

    app = SceneApplication.getApplication();
  •    activateCoordinatesText();<br />
    
  •    coordinatesText = &quot;Marker position: &quot;;<br />
    

}



public void setToolController(TerrainToolController toolController) {

@@ -89,6 +91,7 @@

Vector3f pos = getTerrainCollisionPoint();

if (pos != null) {

toolController.doMoveEditTool(pos);

  •        setCoordinates(toolController.getMarkerLocation());<br />
    

}

}



@@ -196,7 +199,7 @@

final CollisionResult result = results.getClosestCollision();

if (result == null) {

return null;

  •    }<br />
    
  •    }<br />
    

return result.getContactPoint();

}



[/patch]

So what does it do? could you post a screen shot?


@shirkit said:
Note that this is the first part for a serious of improvements on the visual editing of the SDK. I plan adding features like regions in scenes, and support for loading/adding objects that are not j3o objects in the scenes, and allow them to have their attributes saved for runtime.

Could you elaborate on the region thing?

Also you want to load primitive shapes or something like that?

Yeah, what do you mean? You can already add models to a j3o and saving anything thats not a model should be done in different files. The point is that j3o yields a spatial.



You should communicate your intended changes to avoid disappointment if the changes are no used. This here for example should rather be a separate display as well as plugin instead of hard-coding it into the SceneComposer (which is due to change anyway).

@nehon said:
So what does it do? could you post a screen shot?


Could you elaborate on the region thing?

Also you want to load primitive shapes or something like that?


I'm skipping the screenshot as anyways this should be optional. This was one of the changes I've made to improve my scenario creation a while ago.

@normen said:
Yeah, what do you mean? You can already add models to a j3o and saving anything thats not a model should be done in different files. The point is that j3o yields a spatial.

You should communicate your intended changes to avoid disappointment if the changes are no used. This here for example should rather be a separate display as well as plugin instead of hard-coding it into the SceneComposer (which is due to change anyway).


So let me elaborate what I'm trying to create over here, this should facilitate things. I'm designing a map editor, a more complex and complete one. I'm doing this as one of the features of my game is the ability to create and edit levels for the game, pretty much like Warcraft 3.

http://users.soe.ucsc.edu/~sewsmith/images/Warcraft3SpartanCampaignMap2.JPG

I've done quite a few experiments for this, and even have some parts of this done, but not for the SDK. I've built the code into a different application, and the level editing was being done in that area. But I think this could be re-used by some other people, as some ideas over here are pretty nice in my opinion. So I'm trying to think how could I bring this to the SDK.

One of the features I have is the ability to place units in the map in a grid, without overlapping them. Units/buildings occupy grid units in the map, and when a new one is added, it checks for overlapping (done with a matrix). I think this feature would be nice to be exported to the SDK. But I've built this with the help of my own entities that I designed in XML files, which have the necessary information (how many grid squares it occupies) to add this unit to the map. That's why I said of being able to load other things that are not j3o. The file that was being loaded would have the j3o that you wish to load in the scene, and the additional information. This could be done with some kind of plugin, so everyone could design their own wrappers and load the information however it is designed in it's own game.

The region I talked about is a feature just like that in the screenshot @nehon. I have this quite done in my other editor, but this is in my game specific logic, and I wanted to try to design this and bring it to a more general way.
1 Like

Yeah, I can imagine how one would copy some other editor from the user side, thats exactly whats not happening in the SDK to maintain compatibility with the features of the engine without extending them too much or making them dependent on the editor or its metadata. I doubt we can reuse much of this for the SDK but you’ll still have to elaborate so it becomes clear what you are doing.



That doesn’t mean that you can’t create a SDK plugin from this if you want though, just that it probably won’t merge with core unless its redesigned from the perspective of the SDK and engine and not from the side of the desired editor UI. I don’t want to sound dismissive and maybe with some more information you can make me see how this ties into the engine. For now I consider it very game and application specific not because its not reusable but because it doesn’t use core facilities.

@normen said:
Yeah, I can imagine how one would copy some other editor from the user side, thats exactly whats not happening in the SDK to maintain compatibility with the features of the engine without extending them too much or making them dependent on the editor or its metadata. I doubt we can reuse much of this for the SDK but you'll still have to elaborate so it becomes clear what you are doing.

That doesn't mean that you can't create a SDK plugin from this if you want though, just that it probably won't merge with core unless its redesigned from the perspective of the SDK and engine and not from the side of the desired editor UI. I don't want to sound dismissive and maybe with some more information you can make me see how this ties into the engine. For now I consider it very game and application specific not because its not reusable but because it doesn't use core facilities.


I doubt this will ever fit into the core functionalists as it is very specific for some kind of game that wants to go though this approach. I still can't see either how to make this a bit more general, or even if that's possible, I'm trying to solve those things for now.
@shirkit said:
I doubt this will ever fit into the core functionalists as it is very specific for some kind of game that wants to go though this approach. I still can't see either how to make this a bit more general, or even if that's possible, I'm trying to solve those things for now.

Okay, from the fact that you gave a patch for the core SDK and said "improvements to visual editing" I thought you were thinking that way. If you need any assistance in creating your plugin, hit me :)

Ok, thank you @normen ^^ I still need to figure it out how to do most of the things I want. I have some of them ready on my editor, some not. Can I create, let’s say, two plugins, and one of them uses a library defined in the other?

@shirkit said:
Ok, thank you normen ^^ I still need to figure it out how to do most of the things I want. I have some of them ready on my editor, some not. Can I create, let's say, two plugins, and one of them uses a library defined in the other?


Yes it is possible. I have for example a module with a GUI-addon to the SDK that uses a library that another "wrapper" module exposes. Make sure that the wrapper module exposes the packages, don't have the SDK in fornt of me, but somewhere in the properties of the wrapper module you select what packages to make "public" to other modules.