Extends Application (instead of SimpleApplication)

Hello,



I don’t know if this is the right place, but something (minor) bugs me with this implementation. I want to extend Application, because SimpleApplication just has too much garbage I don’t use in my code. Application is cleaner. I do this :



[java]public final class JmeApplication extends Application

{

@Override

public void initialize()

{

super.initialize();

}



@Override

public void gainFocus()



@Override

public void loseFocus()



@Override

public void update()

{

super.update(); // makes sure to execute AppTasks

if ( speed == 0 || paused ) return;



float tpf = timer.getTimePerFrame() * speed;



// update states

stateManager.update( tpf );



// simple update and root node

viewSceneNode.updateLogicalState( tpf );

viewSceneNode.updateGeometricState();



// render states

stateManager.render( renderManager );

renderManager.render( tpf, context.isRenderable() );

stateManager.postRender();

}

}[/java]



See the problem here ? My update method must implement a copy of what you do in SimpleApplication. But the JavaDoc states “do not call directly” for stateManager.render…



My questions are :

  • should I use SimpleApplication because it’s a bad idea to use Application ?

    or
  • should you move the update code from SimpleApplication to Application because it’s universal anyway ?

    or
  • should you change the JavaDoc to remove this “do not call directly” and replace it with an explanation on when you should use it ?



    Thank you.

Use SimpleApplication.



What baggage does it have that you don’t want? 90% of that you actually need.

the rootNode, I want to have my own rootNode object.

same for guiNode.

I don’t want counters and GUI display, or StatView I have my own methods for this.

I want no flyCam, I have my own Camera object.

I don’t want SimpleApplication to manage the AppSettings itself, I do it better.

And I don’t want default Inputs, I use my own StateManager to manage the InputManager.



basically ? Everything… except for this Update() code.



And yes, all this is already programmed and works perfectly fine. This thread is just a theorical question.

1 Like
@ozonegrif said:
the rootNode, I want to have my own rootNode object.
same for guiNode.


A node is a node. I'm trying to understand why your rootNode and guiNode are any different than the ones provided. Or are you also manually handling your own updates for them, too.... the required stuff that you must call right every frame or mess up the scene graph state. These two nodes would be the ones I would expect people to want to inherit the most.

Just make sure you call the two update methods on these nodes in the right place inline with your state manager. Or your scene graph state will be out of whack from the state's perspective.

@ozonegrif said:
I don't want counters and GUI display, or StatView I have my own methods for this.
I want no flyCam, I have my own Camera object.
I don't want SimpleApplication to manage the AppSettings itself, I do it better.
And I don't want default Inputs, I use my own StateManager to manage the InputManager.

basically ? Everything... except for this Update() code.

And yes, all this is already programmed and works perfectly fine. This thread is just a theorical question.


Fair enough. Then just ignore the javadoc telling you not to manually call the state manager. You are in "advanced territory" where "normal documentation" no longer applies.

For everyone else, calling those methods is a bad idea. The javadoc should stay.

Personally, I didn't want to deal with the framework changes and keeping track. So even though I also manage some of my own root nodes, etc. I leave the JME ones in place and have an AppState to manage different viewports and states. I leave the JME stats in place and also use my own (the standard ones are still nice to have when you have to point to something and go "look what's broken!")

And I disable flyCam and create my own.

But I have no reason to manage my own InputManager. I'm not sure what the advantage is, though.
2 Likes

Please, lets deprecate SimpleApplication for 3.1 and have it all in Application @Momoko_Fan :stuck_out_tongue:

2 Likes
Or are you also manually handling your own updates for them, too…. the required stuff that you must call right every frame or mess up the scene graph state.

Yes, precisely. My own "RootNode" class extends Node and manages itself. Basically it's a control for my 3D scene graph.
Obviously I could just use rootNode.addChild( myRootNode ) but then I will have two rootNodes. And I'm easy to get confused when it comes to software architecture ;)
Just make sure you call the two update methods on these nodes in the right place inline with your state manager. Or your scene graph state will be out of whack from the state’s perspective.

Obviously it won't work without updateLogicalState and updateGeometricState. But since you have to declare your rootNode using viewPort.attachScene() and since those two update methods must be called... why isn't it handled by Application ? It could check all the attached scenes and update them, no ?
Fair enough. Then just ignore the javadoc telling you not to manually call the state manager. You are in “advanced territory” where “normal documentation” no longer applies.

I can do this ;) now it's a personal taste, but I always considered the JavaDoc as advanced documentation. It has to be precise and universal. Just my opinion.
But I have no reason to manage my own InputManager. I’m not sure what the advantage is, though.

Basically, I use the InputManager for raw input processing. And I have a few objects to "improve" its abilities with reflection.
Just for exemple, my camera object looks like this :
[java]public class InpCamera extends AbstractInput
{
protected static final Logger logger = new Logger();

public static final AbstractCommand INPUT_MOVEFORWARD = new AnalogCommand( "moveForward" );
public static final AbstractCommand INPUT_MOVEBACKWARD = new AnalogCommand( "moveBackward" );
public static final AbstractCommand INPUT_STRAFERIGHT = new AnalogCommand( "strafeRight" );
public static final AbstractCommand INPUT_STRAFELEFT = new AnalogCommand( "strafeLeft" );

public static final AbstractCommand INPUT_INCREASEFOCAL = new DigitalRepeatCommand( "increaseFocal" );
public static final AbstractCommand INPUT_DECREASEFOCAL = new DigitalRepeatCommand( "decreaseFocal" );

public static final AbstractCommand INPUT_SLOWMOTION = new DigitalOnceCommand( "slowMotion" );
public static final AbstractCommand INPUT_ROTCAMERA = new DigitalOnceCommand( "rotCamera" );

public static final AbstractCommand MOUSE_LEFT = new AnalogCommand( "mouseLeft" );
public static final AbstractCommand MOUSE_RIGHT = new AnalogCommand( "mouseRight" );
public static final AbstractCommand MOUSE_UP = new AnalogCommand( "mouseUp" );
public static final AbstractCommand MOUSE_DOWN = new AnalogCommand( "mouseDown" );
public static final AbstractCommand MOUSE_WHEELUP = new AnalogCommand( "wheelUp" );
public static final AbstractCommand MOUSE_WHEELDOWN = new AnalogCommand( "wheelDown" );

public void init()
{
addMapping( INPUT_MOVEFORWARD, new KeyTrigger( KeyInput.KEY_Z ) );
addMapping( INPUT_MOVEBACKWARD, new KeyTrigger( KeyInput.KEY_S ) );
addMapping( INPUT_STRAFERIGHT, new KeyTrigger( KeyInput.KEY_D ) );
addMapping( INPUT_STRAFELEFT, new KeyTrigger( KeyInput.KEY_Q ) );
addMapping( INPUT_SLOWMOTION, new KeyTrigger( KeyInput.KEY_LSHIFT ) );
...
}

public void moveForward( float value )
{
moveCamera( value, false );
}

public void moveBackward( float value )
{
moveCamera( -value, false );
}

public void strafeLeft( float value )
{
moveCamera( value, true );
}

public void strafeRight( float value )
{
moveCamera( -value, true );
}

public void slowMotion( boolean isPressed, float tpf )
{
slowmotion = isPressed;
}

...
[/java]
Each input has its own method, which is faster and cleaner than a switch case.
Also, the DigitalRepeatCommand() object calls the method for every update() of the scene. instead of just once. It's only a beginning, I plan to add more input managment objects in the future. With conditional filters, and the like.

lets deprecate SimpleApplication for 3.1 and have it all in Application

Nuuuu ! :( This is evil.
Each input has its own method, which is faster and cleaner than a switch case.
Also, the DigitalRepeatCommand() object calls the method for every update() of the scene. instead of just once. It’s only a beginning, I plan to add more input managment objects in the future. With conditional filters, and the like.


maybe its faster then what i done(i created inputInterfaces+manager with priorities), but what with that priorities? i mean you could have situation where key or mouse affect two diffrent things(for example terrain and character), and you will need to do only one. then its not clean ;)
but what with that priorities? i mean you could have situation where key or mouse affect two diffrent things

Absolutly, that's why I will have conditional filtering objects later. Depending on the situation, they will link to the right Command. :)
Absolutly, that’s why I will have conditional filtering objects later. Depending on the situation, they will link to the right Command.


hmm ok, i dont know how exacly you planned to make possible situations like(this are only examples):
- some actions like click on button execute and block other executions(terrain, object / etc)
- possibility of execution 2 or more(but not all of them) executions at once(for example move camera + click character)

that is why i made priorities + some of executions can block lower priorities executions

Generally I don’t quite see why you would change the base to implement such functionality that you can implement else wise too without changing the base. This will definitely give you headaches over headaches with the coming jme3 versions.

@ozonegrif said:
Yes, precisely. My own "RootNode" class extends Node and manages itself. Basically it's a control for my 3D scene graph.
Obviously I could just use rootNode.addChild( myRootNode ) but then I will have two rootNodes. And I'm easy to get confused when it comes to software architecture ;)


Curious, why subclass Node instead of just adding a Control in this case?

@ozonegrif said:
Obviously it won't work without updateLogicalState and updateGeometricState. But since you have to declare your rootNode using viewPort.attachScene() and since those two update methods must be called... why isn't it handled by Application ? It could check all the attached scenes and update them, no ?


Sounds a bit expensive when there is already a set of loops to handle this. For example, I made a ViewPortAppState that manages a viewport, a camera, and its root node... then I never have to think about it again. It can be easily enabled/disabled, etc.

There may be other reasons concerning nesting, etc. that I haven't considered. I actually like the cases where JME gives me the option to do something different.

@ozonegrif said:
I can do this ;) now it's a personal taste, but I always considered the JavaDoc as advanced documentation. It has to be precise and universal. Just my opinion.


We already have users that directly extend Application for not other reason than that they think "SimpleApplication" somehow too simple for them.

For 99% of applications, directly calling these methods on state manager is a really bad idea. This is not part of the "public API" and could therefore change at any time.

But as soon as we add to the Javadoc "never do this unless A, B, or C" we will have people doing it just because they saw the "unless" and didn't bother reading the rest.
Generally I don’t quite see why you would change the base to implement such functionality that you can implement else wise too without changing the base. This will definitely give you headaches over headaches with the coming jme3 versions.

About what ?
I don't change Application since SimpleApplication itself extends it.
I don't change InputManager, I use it normally.
Now RootNode :
Curious, why subclass Node instead of just adding a Control in this case?

True actually. I can do everything in a simple control implementation. I will do that instead of extending Node.
Sounds a bit expensive when there is already a set of loops to handle this. [...] I actually like the cases where JME gives me the option to do something different.

The architecture is very well though, jMonkey is really a great tool to play with 3D programming. I don't really see how a simple loop can be expensive if it does the job automatically. Nesting ? How can you nest a rootNode, isn't it dangerous ? :)
We already have users that directly extend Application for not other reason than that they think “SimpleApplication” somehow too simple for them.

Or maybe they are like me and don't like to have their program initialized with inputs, a flyCam, and stats on the screen. Because when this happen, you have to un-initialize everything. Blleeh. :D
Why not make those initialisations optional or something ?

SimpleApplication, to me, is a tool to have something up very quickly. For prototypes and experimentation it's great !

Thank you for your great answers. The jMonkey team is great ! o/
1 Like
hmm ok, i dont know how exacly you planned to make possible situations like(this are only examples):
- some actions like click on button execute and block other executions(terrain, object / etc)
- possibility of execution 2 or more(but not all of them) executions at once(for example move camera + click character)

It's not on the paper yet because there's no simple answer.
But it will be a conditional filtering. You just link two (or more?) commands together, and if the first matches, it will block or allow the next one.
So ... yes ... it's pretty close to a priority system.

When I finish it (and other tools I'm working on), and if I'm happy with it, I'll submit the code.

I agree with @ozonegrif. I also extend Application, because I don’t want FlyCam, statistic views, settings and other stuff automatically initialized for me, but I do like to have Nifty initialized and some other stuff, which I need in any kinda serious project I want to start. :smiley: Anyway, most of the code in my extended Application is actually copied from SimpleApplication, or at least the most important parts. :slight_smile:

Maybe the solution here would be to introduce another class between SimpleApplication and Application, which would only initialize the most essential stuff with root node and contain that simple update and render loops. SimpleApplication could then add FlyCam, auto showing settings dialog, statistic views and other…

We know what the difference between the two classes is and we know what we say when we say “use SimpleApplication”. And there should only be one class, one that does exactly what SimpleApplication does.

FlyCam seems like the only real sticky one for most folks since nearly everything else can be easily turned off. flyCam is a pain to undo, though.



Perhaps SimpleApplication needs to have a setupFlyCam method that can be overridden. (I would appreciate this one, too)



Otherwise, for the most common cases, AppSettings can be turned off, stats views can be turned off, etc. Certainly that is a safer and easier approach than manually cutting and pasting Application code.



Personally, I’d also appreciate getting to override the adding of the default key bindings since now I manually remove them in simpleInit.



Otherwise, I kind of like having that other stuff at the ready even if I turn it off.

1 Like
@normen said:
We know what the difference between the two classes is and we know what we say when we say "use SimpleApplication". And there should only be one class, one that does exactly what SimpleApplication does.


You know I'm a huge proponent of SimpleApplication but I kind of disagree with this. I don't think having one is a bad idea necessarily but SimpleApplication would have to be modified to be a bit more configurable.

In my opinion, if we continue to have two, Application isn't doing enough (why isn't it calling state manager update for example?) and SimpleApplication has too much hard-coded (most of that stuff could be converted to app states and then easily removed by others).

I may actually do that... convert some SimpleApplication stuff to app states leaving the API in place. It would be cleaner and easier for users to see what the proper pattern should be.
1 Like

Yeah, just in the end it should do exactly what SimpleApplication does ^^

By default. :slight_smile:

Two points for pspeed. I agree 100% with him. Nothing else to add to your argumentation.



Now, I promise to use SimpleApplication normen. :wink: