Thursday, December 27, 2007

Resource Browsers

I've implemented a system where a SceneObject can add a 'resource' property to the list of editable properties. What this will do is provide a text field as well as a '...' button next to it inside of the PropertyGrid. When the user clicks on the ..., a browser window is opened (all handled through the editor) for the appropriate type of resource. This browser window can then be used to preview and select a new resource that should be linked in. Of course, these browser windows can only handle specific types such as a material or a sound, so they will be able to be plugged in to the editor. When a resource is going to be changed, an appropriate browser is looked up and presented to the user.

So far, I have implemented a browser for Materials which will most likely also work with other types of resources that are built in to Ogre but I have to provide a ResourceFactory for those. It simply defines a type and the ability to query for the name and a preview SceneObject of it.

Wednesday, December 19, 2007

Example Code

[This is just a temporary theme. I think it's fairly dark so I will either change that or find something to lighten it up.]

I just wanted to post some code to show how working with my properties can work. I've switched them over to use the Any class that is built in to Ogre but originally I was using my own version of it. There is more to a property itself than just the Any instance but a property does have one of them attached called the 'propertyValue'.

Here is the code I use to actually export the properties of *any* SceneObject at all. This works on Entities, ParticleSystems, Lights, and will work on any future thing out there. *All* of the code in the editor is like this. There is no notion of a particular type *anywhere* except inside the actual SceneObject derived classes themselves. So something that works on one SceneObject will work on a completely different type of SceneObject as long as it provides the same properties and commands (commands are 'issued' to the SceneObject through a generic interface). I'll post an example of the translate tool a bit later. But needless to say, I write code once and if it works, it'll work for anything. I know that whenever I implement sounds, the translate tool will work on those without having to touch the code. It's nice being able to expect that.


void XmlSceneExporter::_exportProperties ( SceneObject* rootObject, wxXmlNode* propertiesNode )
{
SceneObjectPropertyList properties;
rootObject->getProperties( &properties );

if( properties.size() == 0 )
return;

wxXmlNode* propertiesNode = new wxXmlNode( node, wxXML_ELEMENT_NODE, "properties" );

size_t numChildren = properties.size();
for( size_t i = 0; i < numChildren; i++ )
{
Any propertyValue = properties[i].getPropertyValue();
if ( propertyValue.isEmpty() )
continue;

String strData;
if( StringConverter::convertToString( propertyvalue, &strData ) == false )
continue;

wxXmlNode* propNode = new wxXmlNode( propertiesNode, wxXML_ELEMENT_NODE, "property" );
propNode->AddProperty( "name", properties[i].getName() );
propNode->AddProperty( "value", strValue );
}
}



And here's the example 'convertToString' that is used. It's all very simplistic. And this will allow future objects to be registered and saved without touching anything else. Just implement a new TypeDescriptor, register it (at run-time) with the TypeDescriptorManager, and you're all set.



bool StringConverter::convertToString( const Any& property, String* strData )
{
String strValue;
const TypeDescriptor* descriptor;
TypeDescriptorManager* mgr = TypeDescriptorManager::getSingletonPtr();

descriptor = mgr->findTypeDescriptor( propertyValue.getType() );
if( descriptor != NULL && descriptor->canConvertToString() )
return descriptor->convertToString( propertyValue, &strValue );

return false;
}




I am rather enjoying generic programming like this :) I haven't found myself going back to rework old code to fit a new object that I didn't expect to use. Anyways. I have another exam in 8 hours so I guess I'll start studying for it now.

Tuesday, December 18, 2007

Saving the world, one scene at a time

The conversion of the XmlSceneExporter is now complete. I can now save/load anything that's creatable inside the editor so far. It actually only took me about 2 hours to port it over, write any missing functionality, and test it. I had to change some internal workings in my SceneObject class as well as introduce a new class called a TypeDescriptor since I no longer had the power of .NET's Reflection. The TypeDescriptors are pluggable and they basically provide features for a particular type. For instance, they will provide a convert[To/From]String method so that data can be written to disk and reloaded again. I will be providing basic ones for all of the various things I'll need to save inside of Ogre but they can be plugged in through a plugin which means that people can add new types that are serializable with any existing exporter that uses TypeDescriptors (which will most likely be all of them).

I also revamped the blog style a bit. I will be searching for a better template eventually but for now, I just wanted something different. Anyways. I have a final exam to write in half an hour so I should possibly do something towards that :)

Sunday, December 16, 2007

"I like to move it, move it"

The translate tool is done. I had changed how the selection manager was processing events which required some changes to the tools. I also was getting some strange issues with control focus and wxWidgets which ended up getting solved. I had to force the render panel to get focus when it was clicked.

One of the major down falls to switching over was that I wasn't NULL'ing out my pointers in Managed C++ since this was done for me. Now that I'm using C++, this has come back to haunt my debugging dreams. I've made a large pass over the code base and have initialized all my variables in the constructor but there are still some NULLs getting passed around that somehow worked in Managed C++. Who knows. It's all getting solved and it's making the code more stable with every step.

I am going to see about implementing the next plugin which is the Sample Exporter. At least this will let me load up the larger scenes that I had saved before. I'm tired of looking at a single test OgreHead. I am really not sure how I'm going to write out all of the variables right now. With .NET, I could write a converter that would parse from/to a string which meant that I could use this for my PropertyGrid display as well as for writing out to a file. Since C++ doesn't natively support this, I believe I am going to write a 'converter' class which will take a specific type and be able to parse to/from a string. For most types, I can convert *to* a string using Ogre's built in StringConverter class. I'll have to convert back from a string but worse things have happened. I believe once I have this, I'll be able to say Convert::toString( const Any& someObject ) and based on the value returned from Any::getType, I'll be able to match it to a specific converter and it'll be written out. The joy of this is that the exporter won't need to know how to save any particular value. The down side is that in the future, if the converter changes, there isn't really any way to know about it from an exporter point of view. That is, data could be written out with v1.0 of TypeX Converter but then that could be replaced with v2.0 of TypeX Converter which no longer recognizes that particular format. I'm sure I'll think of something other than just crashing :)

It's nice being able to finally put a scene together. Here is my current progress:

Base Editor: 95%

Plugins
--------
Basic Align Tools: 0%
Basic Object Editors: 0%
Properties Window: 0%
Sample Exporter: 0%
Basic Gizmos: 50% - Translate is done, the others are extremely similar to it
Basic Object Factories: 100%
Scene Graph Window: 100%
Resource Browser: 100%

Saturday, December 15, 2007

Port Job

The porting is coming along nicely. I've made a few internal changes but nothing huge. The biggest problem I've had is that I had tons of memory leaks. I have removed all of them so far. The editor starts up and exits cleanly from start to finish. I still have to figure out how to handle exceptions better since once one happens, the app usually crashes and burns. This is going to be an issue between exceptions and wxWidgets but I'll get there.

I've completed the following plugins:

Scene Graph Tree
Resource Browser
Basic Object Factories

and am working on the Gizmos plugin which contains the translate/rotate/scale tools that will be provided. I will have to overhaul the UI once the porting is done to make it nicer to look at. Right now, I'm concerned with getting it functional to where it was with .NET/CLI C++


Friday, December 14, 2007

Break Up

I'm sorry to be reporting this but the team of Doug and myself has broken up. We're still talking and will hopefully continue to collaborate on things but as a dedicated team, it fell apart. I am the one to take all the blame here. I simply didn't keep up on things and let emails slip and responses be delayed longer than I should have. Things just ended up drifting apart to the point where I think it was obvious to both of us that it wasn't really working anymore. We're still chatting over email though so hopefully we'll still be able to exchange ideas. There isn't really much more to say on the issue. I feel bad about it so hopefully I can use it as a learning experience about the dedication I need in order to bring other people onto a project.

In other news, the editor is still being worked on. I'm going to keep going with the project itself so nothing has changed in that respect. A lot of the focus has shifted away from the game as I haven't worked on that in ages. I am trying to develop an awesome editor which I can give back to the community and hopefully see a lot of useful stuff come out of it. I'll be using that to design as much of the game as I can. I want almost everything to be defined in the editor so that I can avoid changing code when I don't need to. It'll also allow for rapid development of new units and levels once that stage has arrived.

I am however in a major overhaul of the editor. I am switching away from .NET with Managed C++ and moving into using wxWidgets and C++. I hit a few barriers in .NET that aren't documented at all and nobody really knows how to do them. I also found myself writing a lot of wrapper code around Ogre objects to pass things around inside of the managed environment. With the move to C++, I can use a lot of the features of Ogre as well as the awesome 'Any' class which can wrap anything up to be passed around. I also go back to straight C++ which is what I'm most comfortable with as well as what Ogre is written in. This will have the advantage that when people write plugins or modify the editor, it will be in the language that is used with Ogre.

I am making good progress so far. I've been leaving a bit of code commented out here and there, marked with a 'todo' for later, since features aren't finished but the base editor package is about 95% done. In terms of progress, here is my list:

Base Editor: 95%

Plugins
--------
Basic Align Tools: 0%
Basic Gizmos: 0%
Basic Object Editors: 0%
Basic Object Factories: 100%
Properties Window: 0%
Resource Browser: 100%
Sample Exporter: 0%
Scene Graph Window: 0%