Wednesday, July 04, 2007

In the dark

I knew up front that being able to determine what type of object you were looking at was not going to be a good thing. The SceneView tree graph had different code depending on what type of thing you clicked on. This would not be good for extensibility since you'd have to go to 100 places and add support for a new type of object.

Thus was born the EditorObject. This can wrap anything that can be present in a scene. It can be as simple as a single SceneNode or as complex as an entire terrain heightmap or a "unit" made up of 14 different meshes with 12 scene nodes and 4 particle systems. It doesn't matter. Everything just deals with EditorObjects which support set/get methods for their properties. You simply say getProperty ( name, type ) and it will return a property of that type if it supports it, nullptr otherwise (Yes, I'm using .NET and C++/CLI).

They do support getting the name of the type to which they belong. For instance, the scene node editor object returns "SceneNode" when its type is queried. This value is only used when categorizing items such as in a sorted view of the various items or in an options page to enable displaying/hiding the various types. There is no way to actually query for the scene node to which it belongs. You *can* get the type and name and manually look it up in Ogre but that's circumventing the system deliberately and if you do that, god help you.

This is going to work seamlessly (hopefully) with my undo/redo system when I get around to it. I will be able to store the previous value of a property and the new value as well as the property name/type. Thus, when you undo it, I simply call "setProperty" and pass in the original stuff. Deletion and creation are going to be different as well as things like reparenting scene nodes but those will come in time. For now, this works perfectly.

I've reworked the SceneView as well as the Translation Gizmo to be unaware of what object they are looking at. The translation gizmo simply queries whether a 'translate' command is available and if so, it will show. Otherwise it stays hidden since it doesn't know how to move the currently selected object. The SceneView can now contain so many things. A single Unit such as a lizard grunt could show up in the SceneView as a single object which you can click and select. It is up to the UnitEditorObject whether it exposes the objects that make it up or not which is a handy feature.

I've also added a sprite system that any EditorObject can use to hook up a sprite to show for itself. The LightEditorObject is using this to show a simple sprite (go Google images go) where the light is. The Sprite object simply has an associated EditorObject with it and uses the getProperty with the name of "Location" to find the position of where it should be. They are all the exact same size as well and they don't change size the further they get from the camera. They stay the same screen size no matter how far they are. Once the scene is more populated, it will be easier to see why since parts will be hidden and that's how you can determine where they are. It makes it easier to see icons in the distance instead of spending 5 mintues flying around a level trying to find one.

I still haven't figured out how I am going to deal with the problem of setting a location on an object buried in some hierarchy of nodes. For example, a light is attached to a node. The node is moved away from the origin. If you call setPosition(0, 0, 0) on the light, should it go to the origin of the parent node or should it go to the origin of the world? And if it goes to the origin of the world, is it going to be easy to figure out what type of local translation will be needed? I haven't thought about it yet (literally just thought of that as I typed this) but we'll see. I'm sure both are possible and maybe an option of local/world space will work on this.


No comments: