jME3 Application/AppState sample

normen said:

Ascendion said:

[InterfaceName]Base... is the Java standard to use Abstract[InterfaceName] ??

Well kind of, yes. Normally you have the MyClassType interface with all info and the AbstractMyClassType abstract class.


That was the least important part of the post in question, but I will acknowledge the will of the majority, bow down and pay homage to the java conventions :)

So what about the rest of it ?? Think about it some more, Code it, or Trash it ??
Ascendion said:

So what about the rest of it ?? Think about it some more, Code it, or Trash it ??

I think your ideas go in the right direction, I'd just like to make it more open than "RenderPriority" "StatePriority" etc. You were talking about the depth of such systems in production games yourself. As said, I imagine a general task priority system with states that the tasks have and can depend on. In the beginning of the render loop all tasks are collected and then executed by dependencies. If you dont know what I mean, such systems are also used to prioritize threads in modern concurrency systems (grand central in MacOSX for example).

Cheers,
Normen

I think adding priorities and all of that might kind of complicate things a bit. Consider the fact that most applications only use two viewports (scene, gui), so having all those priority buckets would be unnecessary in many cases.

Momoko_Fan said:

I think adding priorities and all of that might kind of complicate things a bit. Consider the fact that most applications only use two viewports (scene, gui), so having all those priority buckets would be unnecessary in many cases.

So we leave it to the user how he prioritizes his appstates, like in jme2?

Actually I was primarily talking about viewports. I like to stick with the "one true way" but in some cases you may be forced to make things flexible. I think this might be one such case.

Forcing people to manually render viewports inside the AppState would be kind of low-level, while forcing them to use the viewport managing system in RenderManager would expose too much control. Both ways have their own set of issues so having some flexibility might help here.

Sounds like you're going back and forth, and I know why. I think thats actually the reason why the AppState system is still in the current state of being a simple callback :slight_smile:

A system would be great to extend AppState but brings either a new system into jme3 that would have to be used throughout jme3 or it would restrict the AppState system to something like a viewport management system…

(other big post deferred until we get past this issue)



MF – you talk about exposing control but right now the programmer is in total control at the expense of a steeper learning curve to overcome because there is no clearly outlined method of managing order of updates and rendering. What I am trying to do is add functionality that will benefit the users that don't need total control and don't want the extra learning curve.



We can add a ViewportManager as singleton AppState to do the automatic prioritized rendering in the last state priority slot… set up SimpleApplication to use it so there is an example, and if the end user doesnt want it, they can take the next step and go Application/AppState, with calls to render viewports in the update method if they don't want to use the viewport manager. (though for the features we have discussed so far, they will have to make something similar, or expose some global references to access their viewports from multiple states)



(this is getting confusing – I was about to post an article describing methods to handle dependencies and prerequisites for the state system – and some of what I'm saying here would have a real need of that code)



How about we try this – MF – show me how adding functionality "exposes more control" in a system where nothing is hidden and you can do just about anything you want any time you want even if its stupid and will break your app ?? (Lets render the gui viewport first when we have the root viewport set to clear before rendering !!)



Normen - lets stop worrying about the state system for a minute and focus on viewports and rendering since that happens AFTER the state system does its job.



note: we still have one AppState class (AppElement if I can talk you into it since its gonna end up being used for a lot more than just states) and what kind of element it is depends on which manager you hook it to (State, Render, Physics, Input, Network, etc)… so we lose the render method and just update the element in whatever context that element is designed to operate.


AppElement sounds interesting…  :slight_smile:

How about we try this -- MF -- show me how adding functionality "exposes more control" in a system where nothing is hidden and you can do just about anything you want any time you want even if its stupid and will break your app ?? (Lets render the gui viewport first when we have the root viewport set to clear before rendering !!)

Well, how it works right now, is that the AppState gets a RenderManager, and must create/attach a viewport into a bigger pool of viewports inside RenderManager. It can also get a named viewport by name from the RenderManager and attach its own rootNode to it.
Both of those ways operate through side effects, which is considered a rather bad way to do things. In virtually all cases where I saw the "GameStates" idea being used, was where they had a render() method in which they would render an own rootNode into some rendering interface without knowing about the greater deal of whats out there.
In my 2nd side effects example, you notice that if the expected named viewport isn't there, then the program will crash. That's why I really wanted to avoid that situation when I noticed people trying to incorporate AppStates with viewports.

We can add a ViewportManager as singleton AppState to do the automatic prioritized rendering in the last state priority slot... set up SimpleApplication to use it so there is an example, and if the end user doesnt want it, they can take the next step and go Application/AppState, with calls to render viewports in the update method if they don't want to use the viewport manager. (though for the features we have discussed so far, they will have to make something similar, or expose some global references to access their viewports from multiple states)

That sounds reasonable, however you still have to fetch the ViewportManager from the AppStateManager to do anything. So essentially its just the functionality of the RenderManager except put into an AppState.

Normen - lets stop worrying about the state system for a minute and focus on viewports and rendering since that happens AFTER the state system does its job.

Actually the reason we started worrying about viewports was because of the appstates.. obviously their usage is closely related. We should strongly consider how we want appstates to be used so we can sort of form the render system around it.

Re Side Effects: We never said that using states/elements wouldn't requires some careful design. The programmers has a choice of getting a reference to an element every time he wants to interact, or of getting the reference once during initialization an keeping it handy for later use. In the case of viewports, this does not mean that the viewport is still attached to the viewport manager at some point later in the process. The benefit of elements is that everything is managed in similar fashion, easing the learning curve.



When it comes to any element of the system that should be globally available (the ApplicationManager, ViewportManager, InputManager, NetworkManager, and possibly others), I do not like the idea of having a common point of access where I have to go to get instances. I would prefer to have singletons, backed by factories if there are multiple implementations of the element available to chose from. Let me propose a use case to demonstrate what I mean.



A simple application might start off its initialization by creating a ViewportElement… the ViewportElement accesses the renderer singleton, which initializes the graphics system before returning to the viewport element. Then the ViewportElement is attached to the ApplicationManager, which creates the root of the dependency/update system, attaches a listener to the Renderer to get frame ticks to drive the update process, which will, at some point later in the process, cause the ViewportElement to call the Renderer to display itself.



The entire application just initialized itself without the programmer ever directly accessing any of the infrastucture elements that were not required to define the application behavior, and only the elements needed by the application get loaded and initialized. The input, sound, network and physics systems are never even referenced, since none of the elements mentioned needed to know anything about these systems given the structure of this particular application.



What that will get us in the long run is a lot of reusable elements that anyone can use to piece together with their own logic to create a game. If we want to be able to replace the implementation of any element, its easy enough to to create an interface and factory that can load the desired implementation (do I smell a generic factory here ??). This makes experimenting with implementations reasonably painless, and allows programmers with unique requirements to customize the system as much as needed to get exactly what they want. Programmers that don't need to customize will automatically get the elements that implement what we believe to be the best standard implementation of the element.



I admit this has gone a LOT further than I expected. I wasn't planning on reworking the entire application initialization system, or defining the requirements for a modular element system for most any part of an application. Unfortunately (from MFs point of view anyway), I think, and I believe Normen will agree since he has been pushing in this direction, that if we do this at all, it should be whole hog or none.

normen said:

AppElement sounds interesting..  :)

I'll take that as an invitation to expand on the idea :) You guys are seriously tempting me to grab something to do class diagrams -- talking out structure is getting tedious.... is there any good free team software out there for java ?? :)

I just threw this together to give a general idea how we might structure AppElements and their managers. Note that since ElementManagers are based on AppElement, it is completely possible to construct the entire top level "update cycle" for an application as a chain of managers attached to an ApplicationManager instance. Running the app then becomes nothing more than calling BeginUpdate on the ApplicationManager over and over when then engine ticks :)

This setup covers everything that needs to update per engine tick. Derived classes will have the following characteristics.

1. Constructor -- parameterized  instance configuration if needed, params are stored but not used until initialization
2. Initialization -- the element constructs any required persistent state (geometry, PhysicsNodes, whatever)
3. Attach -- element registers listeners, adds geometry to viewports, etc
4. Detach -- element reverses all the environmental changes made during Attach.
5. Update -- element performs processing as needed based on triggers and the interval since last update

I have been evisiononing this in terms of encapsulating state for GeometryElements which have complex interactive behaviors, but an element could also represent part of a GUI, a network connection, a reusable physics model, or anything else that Normen can cook up for an example. It can even be used to wrap up the Viewport class in order to have the render manager work like other managers will if we implement this model.


public abstract class AppElement
{
    // properties (public getter, private setter)
    public String Identity;                 // unique element name
    public List<AppElement> Prerequisites;  // elements that must be updated before this element can update
    public boolean Updated;                 // true if this element has completed updating
    public boolean Updating;                // true if this element is currently updating (or combine these 2 into an enum)
    public boolean Initialized;             // true if this element is ready for update processing
    
    // methods
    public AppElement()
    {
        Identity = NameManager.CreateIdentiy(this);
        Prerequisites = new List<AppElement>;
        Updated = false;
        Updating = false;
        Initialized = false;
    }
    
    public void PrepareForUpdate() {
        Updated = false;
        Updating = false;
    }
    
    public void BeginUpdate(float tpf) {
        Updating = true;
        foeach (AppElement e in Prerequisites)
        {
            if (e.Updated) continue;
            if (e.Updating) throw new Exception("Element Prerequisite Loop Detected");
            e.BeginUpdate(tpf);
        }
        Update(tpf);
        Updated = true;
        Updating = false;
    }
    
    public void BeginInitialization()
    {
        Initialize();
        Initialized = true;
    }
    
    // abstract methods
    protected abstract void Initialize();                // called when this element is first attached to a manager
    public abstract void Attach(ElementManager manager); // called when attached to a manager
    public abstract void Detach(ElementManager manager); // called when removed from a manager
    protected abstract void Update(float tpf);           // perform our processing
}

public class ElementManager extends AppElement
{
    protected Map<String, AppElement> ElementsByIdentity;
    
    public ElementManager()
    {
        ElementByIdentity = new Map<String, AppElement>();
    }
    
    @Override
    public void BeginUpdate(float tpf)
    {
        Updating = true;
        if (Updated) ResetStatus();
        super.BeginUpdate(tpf);
    }
    
    @Override
    protected void Update(float tpf) {}
    
    public void ResetStatus()
    {
        foeach (AppElement e in Prerequisites)
        {
            e.PrepareForUpdate();
        }
        PrepareForUpdate();
    }
    
    // stubs to be filled in if this idea is accepted
    public void AddElement(AppElement e) { }        // init and attach elements, manage ElementsByName
    public void RemoveElement(AppElement e) { }     // detach elements, manage ElementsByName
    public AppElement FindElement(String name)      // lookup an element by name, null if not found
    {
        return null;
    }  
}



I took the liberty of creating this with the simple dependency/prerequisite system even though there is a problem with prerequisite loops not being detected until an update is attempted.

We mostly use googledoc for collaboration.

I like the state system you propose, but I'd like to see concurrency at least just planned into it. There have to be states of other elements that you can depend on and read or read/write update calls so you know what can be called in parallel… I will see if I can hobble together a schematic of what I mean exactly.

The worries about a complicated system… by giving the user named variables, premade classes etc. even a very open and complicated system can be made user-friendly. Totally agree about the "whole hog" thing :slight_smile:

Google Docs will work, I guess…



There is no reason a thread cannot have an ElementManager to control an independent hierarchy of elements but some thought will have to be give to managing prerequisites that are intended to be updated on another thread.



One solution to bake in thread safety would be to have each manager store a reference to the thread it was created on, and have each element track which manager it is currently attached to. Then, when a cross thread BeginUpdate call occurs, it can be deteced and the code can wait on a semaphore built into the element forcing the calling thread to pause until the thread containing the element "catches up"… BeginUpdate from the same thread will not use the semaphore, but will instead actually process the update.



I'm working on a quick and dirty implementation… I'll throw that into the mix  :smiley:



I'm getting a crash course in java generics as applied to singletons and factories right now – What I'm attempting is a generic class factory that, given a type, can figure out the implementation to load based on an explicit class name passed in code, loaded from settings, or hard coded into the factory implementation for the type, with the caveat that, once you have instanced a specific concrete implementation, all instances created by future calls to the factory will be from the same concrete implementation.

Ascendion said:

One solution to bake in thread safety

Not thread safety, threading logic! Anything we do would have to be something that Momoko can simply use and build into the renderer, following his internal logic or we start messing things up. Also, I think you try to reinvent the wheel in the end of your post, java has pretty good reflection and class checking abilities.

OK – explain what you mean by threading logic – something along the lines of sorting the elements by prerequisites then using a thread pool to launch parallel updates ??



I think I've gotten the loader architecture the way I want it… I'm looking into creating an ApplicationElement to start things off. I want this element to be the BARE minimums to start up the engine. So far it looks like it needs to wrap JmeContext and the taskQueue. I might add on the AssetManager and the Renderer, but with Android in the pipe, it might be worth making those as elements so target implementations can be switched out with a configuration change. Pretty much everything else should be an element.



Comments/Suggestions ??

Ascendion said:

I think I've gotten the loader architecture the way I want it.. I'm looking into creating an ApplicationElement to start things off. I want this element to be the BARE minimums to start up the engine. So far it looks like it needs to wrap JmeContext and the taskQueue. I might add on the AssetManager and the Renderer, but with Android in the pipe, it might be worth making those as elements so target implementations can be switched out with a configuration change. Pretty much everything else should be an element.

About threading: yes, something like that. It requires the elements having dependencies on other elemets "processes", in a read or write manner, this way you can also sort the tasks concurrently.

These wide-spread changes you suggest probably won't happen that quickly, you're a little too late for that I guess, jme3 is already in alpha.. If you can provide a good system for task priorization etc. thats good, but the way you're talking you sound like you want to create your own jme3 branch or something..? As said, Momoko has the final say about what happens how in the renderer and he will have to take the time putting such a system in without messing things up or losing overview.

Are you guys using the JME3 alpha or SVN, because the release I have (jme3-alpha) doesn't have the



com.jme3.input.controls package



Also strangely enough application states aren't working. I can attach a state to the state manager but only the @stateAttached method is being called. It seems that the state manager isn't part of the main application loop. This is the case if I use the SimpleApplication class or the Application Class.



I looked at the source code in the SVN and it doesn't look like the AppStateManager field is used at all for the Application Class and only use once in SimpleApplication (which is odd because it's inherited from the Application class). Am I supposed to override the Application Class functions and add the hooks for the AppStateManager?



Is there a reason it has a field with no implementation? or am I just looking at some really outdated half release?

lemonaid81 said:

Is there a reason it has a field with no implementation? or am I just looking at some really outdated half release?

Input system and AppState system have recieved massive changes since alpha-1, yes.

oh good I was afraid I was missing something important… thank you.

Right now I'm looking at wrapping or porting the existing managers into the Elements framework, so it can be considered an addition until such time (jME4 ??) when and if it becomes a standard part of the core. That gives the end user a choice of using the current system as is, or using the element system once we have enough of it to be useful.