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.