Event Manager
Routes Events to subscribers(aka handlers) on channels, eventually there will be a network transparent handler
Class Manager (handles introspection)
The mechanism to handle introspection resembles MFC , but is tuned for performance and avoids excessive use of macros
classes are initialized at program startup ( or thereafter )
this introspection method is intrusive (requires you to subclass CObject), but thats not an issue as orkid is a media application framework
Classes (as in CClass)
Classes contain knowledge about the layout of Objects (as in CObject)
This knowledge is stored in Attributes which know the data type and the offset from the base address of the Object Instance.
Classes can also contain Interfaces, which is basically a simplified COM like method for implementing objectiveC/smalltalk style dynamic dispatch.
There are 2 types of interfaces, differing only by their access speed, they are Indexed Interfaces and Named Interfaces.
Indexed Interfaces are retrieved by index, there are a fixed constant number of these per class, but they are stored in an array for quick access.
Named Interfaces are retrieved by name, there is no limit to the number of them per class, but they are slower to retrieve.
An example of how I use these is for the modeler, for picking .
when the user kliks in a modeler viewport, the modeler draws the ObjectID's into an offscreen buffer with appropriate render states set
This ObjectID is retrieved from the buffer as a pixel at the mouse coord and checked for validity
if its a valid object, an interface Query is performed to determine if its pickable
if the Query returns an interface, that interface is called and the object is attached to the selection
this works for any Object of a class with a PICK interface set, no need for inheritance in this case other than inheriting from COrkObject
sounds like a lot of work for the gpu to do just to pick, but gpus are fast these days, and it was ezier to write it this way then
write selection code for every object,
not to mention this will work even for objects with funky vertex displacements.
Interfaces will also open the door for scriping language hooks
This knowledge can be used to (de)serialize objects and build editor UI's without requiring specific code for every class
Performance loss for this system is minimal considering this level of support
All this class knowledge is stored per class , not per instance
All of this data is initialized at program startup , so memory fragmentation is not an issue
The only overhead is 8bytes per object in the vtable and a 4byte tag which contains a class code (CID) and an unique instance (UID) code
The member variables of a class are still just member variables, there is no need for special accessors just because the class manager knows about them
Not all members must be declared, only items which you want the system to serialize or build editors for (aka inspect)
Where ever possible, information retrieval has been optimized
The most annoying thing about using this system (for me anyway) is the fact you cant just call new on an object,
you do it like this : CObject *pObj = CClassManager::CreateObject( "ClassName" );
or like this (to save a map lookup) CObject *pObj = CClassManager::CreateObject( ClassID );
note: upon further thought, this isnt an issue, this limitation can be overcome like this (as long as you dont create a CDerivedObject before the class is registered)
class CDerivedObject : public CObject
{
static CClass smpDerivedObjectClass;
static void ClassInit( CClass *pClass ) { smDerivedObjectClass = pClass; } // class manager calls this automatically when class is registered
CDerivedObject( CClass *pClass )
: CObject( pClass )
{ }
CDerivedObject()
: CObject( smpDerivedObjectClass )
{ }
};
Plugin Manager
Allows Classes to be added to class manager from plugin DLL's (only windoze version, ps2dev version loads an irx)
Plugins must access class manager thru an Application Context
No limit to what functionality a plugin can contain,
it can contain new Classes, and Commands which pretty much enables anything from a plugin - even an application can exist as a plugin
Asset Filters
An Asset filter knows how to convert 1 extension to another so a filter contains 2 halfs,
a loader which loads to an in memory intermediate format and a saver which saves in a platform specific format
example (from a commandline)
>orkid filter mid : mmt midi/test.mid midi/test.mmt
this will convert a midi file to a mmt file using the "mid : mmt" filter
>orkid filter list
this will list all filters available
>orkid filtertree mid : mmt midi/
this will recursively search the midi folder for mid files and convert them to mmt's
Ideally filters should use a hub layout, but this is not enforced.
I tend to convert a source into an intermediate superset (with any common processing occuring on the superset),.
Then to the target format, this allows you to share alot of code
like this (just an example):
obj->hub - wavefront 3d object (unskinned)
lwo->hub - lightwave 3d object (unskinned)
mb ->hub - maya 3d object (unskinned)
hub->pgm - pc unskinned model (directx or opengl)
hub->ggm - gamecube unskinned model
that gives you 3 sources and 2 targets, of which you can use any combo