Monday, July 16, 2007

Alignment

I've taken a stab at creating an "align" tool inside of the editor. Again, to make sure I am exposing everything I need to for outside developers, I wrote this as a plugin. I need better support for adding toolbars and stuff but it'll get there.

This will align any object that exposes the appropriate properties. I should probably throw up a warning or something when an object is selected that can't be aligned using the current settings. But for the most part, you can grab a scene node and either align it based on location or on bounding box. Bounding box is the most useful since the location can be arbitrary depending on what is attached to it. Bounding box allows you to align two objects to be along the same axis on the Z or to even be right next to each other except along the x-axis. It's all up to you.

I've stolen the icons from Maya so they'll have to be replaced sometime. But all the features work. It'll make things a lot easier to lay down in an organized fashion. I think I will need to implement grid-snapping soon as well with customized values so you can create bigger/smaller grids. This will be a must-have feature when we get to lay down the terrain tiles.


Thursday, July 12, 2007

Particle Systems

I've implemented the ability to spawn existing particle systems in the editor. Currently, there are no properties exposed to adjust them but that's fairly trivial to do. They are saved as well which fell out automatically.

I am going to have to write some internal editor to allow creation and customization of particle systems. You'll need to be able to add emitters and changers and stuff like that. This should all be done through the editor and then the properties of each emitter, such as the material it uses, will be exposed in the properties view for easy configuration.

I am currently working on creating a wrapper for the ManualObjects in Ogre. These are going to be the hardest thing to create one for I think. I need to be able to go backwards to support undo/redo which Ogre doesn't have any functionality for. I'd rather not change the source of Ogre since I want this editor to be entirely external so I'll need to manually keep track of how to rebuilt a certain part of the ManualObject and when you undo, I'll scrape what it is there and then rebuilt it. It's pretty brute force but it should work until I come up with another solution.

I'll be using this to create the grid that is normally visible in editors. It won't be terribly robust at first but I think it can get there. I'd love to be able to create simple geometry in the editor and then be able to convert it to mesh and export it. This is great for quickly prototyping things. It will not be a replacement for a professional modeling tool but it should let you create a house or something simple without loading up 3ds Max or something.

On a personal note, I haven't been sleeping at all lately. I was up until 8am today and got an hour and a halfs worth of sleep before I went to work and told them I couldn't come in. I came home expecting to sleep but after 2 attempts, I failed. I haven't done much today since I am utterly exhausted but I am able to post a blog of what I accomplished last night :)


Deleting Things

I've added the ability to delete objects in the editor. This was actually fairly trivial since everything is nicely wrapped up as an EditorObject. Each type simple defines its constructor to remove the various Ogre items from the scene and a small amount of work is done by the EditorObjectManager (these really should be renamed to SceneObject and SceneObjectManager) to fire off an event and remove it from its internal list. That's about all there is to it.

With this, I have the ability to create and destroy the following Ogre items:

Scene Nodes
Entities
Lights

I haven't gotten to particle systems yet and they should prove to be interesting. I'm not sure how I'm going to layout the properties for those just yet. I'm assuming I'll have some plugin to expose even more properties of it so that it can be edited in its own window.

It should be fairly easy to add undo/redo functionality to this as well since I already have export/import working. I already have the ability to query for all of the properties I need to save so that shouldn't be a problem. The thing I am thinking will be the hard part is recreating the hierarchy. For example, if I delete a scene node, I will need to save that node and everything attached to it. Now when I store that, I'll have to store the scene node as well as all of the children objects (and then traverse downwards). When I go to undo the delete action, I will have to start at the top and create the object and assign its properties and then traverse downwards again. Now that I'm thinking about it, it won't be that hard actually. I'll store the properties of the object as well as an array of all the children objects. Then just create the main objects, set its properties, and then recurse down to its children. Presto bango I have an undo for delete. (And this is why I blog). I may in the future have to add the ability to parse some parameters *after* children objects have been created but I don't think there are any properties in Ogre that you can set on an object that rely on having a children. So yay for that.

I'd post a screen shot but it wouldn't mean much. It'd be the same scenes as I've shown before but with objects remove. Who knows. I could even fake it just be recreating the scenes without putting in a certain light. You wouldn't know :)

I'm still going to leave undo/redo for a bit until I get more done. So far, the system is become fairly stable. I haven't made any significant changes to it in a while which is good. I've been able to accomplish a lot, and in an easy manner, with this EditorObject system. I want it fully solid before I put in undo/redo since it will rely on it heavily to work.

The next feature I am going to work on is the ability to reparent things in the scene so that they can be moved around. It's a pain if you realize you want an additional node in between 2 existing ones. There is no way to do that without having to restart the entire tree at the given node.


That's it for today. I am going to try and go back to bed now.

Wednesday, July 11, 2007

Basic Saving/Loading

I've implemented very basic save/load functionality into the editor. It's more of a test for me to see:

1) If it is possible to save/load a scene without an exporter knowing what it is actually exporting. I've done this so it obviously works. There may be some special cases where certain pieces of data will be required but I can't foresee that happening right now. Possibly if I get into editing terrain or something, it *may* need to know how the terrain is there to export it properly but I don't think so.

2) Bigger scenes come together. It's rather annoying not being able to have larger scenes without having to touch code. I'll probably start putting together test areas in this to test out various things. So far, everything seems to save/load fine even though I at save/load time, I have no idea what I am exporting or importing. It's all taken care of through my EditorObject system. So I'll be able to implement a binary, XML, and a custom file format in the editor without knowing a single damn thing about what I'm exporting :) Importing into the game may be different but that's another story. It will be possible to export into a certain format that is read back in so it's up to the game to read in all the properties.


Currently I am also investigating diagram editors for use inside of the editor. I'd very much like to graphically lay out the scene so it's easy to spot things. This will also come in handy when I get around to a "scritable" piece that I've wanted to support for a while. It's much like Kismet (Unreal) or FlowGraph (CryTek) in that it is a visual way to use script objects. So you can chain together small building blocks together to form logic and perform things in the game. For an example, you could use this visual system to create a system where you have to align boulders on to various scales in order to solve a puzzle. All of this is possible to be driven through these types of systems (I don't support it yet but I will) which allows designers to create actual gameplay mechanics without having to touch code or bother a coder. It also allows for much faster prototyping and tweaking since it's all data driven as opposed to code driven.


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.