Quote:Original post by return0
Why not a pub/sub event model for communication between the components of an entity?
I'm doing a signally type event system as well, mostly for designer-level scripting stuff. For things like pushing an updated transformation matrix from a physics body to a graphics node though, a generic event system is way too bulky.
For things that happen once a second I'm happy to use events, but for things that happen 10,000 times per frame, I'd rather that the components communicate directly.
Quote:Original post by jyk
In other words, what does the code that parses the entity definition, creates and adds the specified components, and passes previously created components as arguments to other components' constructors (if requested) look like? I assume it doesn't look like the above, since that hard-codes a particular set of relationships.Basically, the reason I ask is that it seems like you'd still have the dreaded downcasts, it'd just be moved to a different place in the code.
I'm still writing the part that interprets this data file ;)
At the moment though, I'm using a reflection system in my components that provides run-time info on the constructors, interfaces, member functions and member variables.
I can use this system at the moment to look up a list of constructors (by type-name) and then find one that matches the user's data.
e.g. if the user writes: BarComponent bar1( foo, 42 );, then I'll:
* look in my local component table for a member named "foo"
* get a list of type-hashes (inheritance list) from the instance associated with foo
* determine the constant '42' is an integer, and retrieve the integer-type-hash:
* look up the constructor list for BarComponent.
* search this list for one that matches (any foo type-hash, int type hash)
* if a match is found I get two function pointers from the list entry
** the first function pointer constructs a struct{FooComponent*,int} object, which implements a generic set/get interface
** on this object I call
*** Set(0, GetComponent("foo"))
*** Set(1, atoi("42"))
** Then I use the second function pointer to call a constructor-proxy, passing the struct I just filled in, which returns:
*** new BarComponent(args.Get<FooComponent*>(0), args.Get<int>(1));
* then the newly constructed component will by added to the entity under the name "bar1"
The FooComponent may be upcast to a Component and then downcast again to a FooComponent at some point, but there's type-hash checks done along the line to ensure these casts are safe.
The actual management of the above function-pointers, dynamic-structures and proxy functions is all handled by the reflection system and will be transparent to the user, except for the pain of having to use a macro to 'register' their constructors. e.g.
class MyComponent{ MyComponent(); CONSTRUCTOR( () ); MyComponent( int i ); CONSTRUCTOR( (int) );};
[Edited by - Hodgman on April 11, 2010 11:53:20 PM]