Monday 4 May 2015

Tech time 2: new-old properties widget

So the last tech time mentioned changes in threading of editor. This change may look small in first glimpse but in reality it was really challenging task. I needed to make transition from monolithic application where almost everything happen in one thread to system which work like game.

Right now I can tell I succeeded but in the same time I cannot say I finished. There is still need for a lot of changes in editor and tools to fit new threading setup. Today I  will talk about one of the biggest one:

Properties panel 

Today I can say that most important part of work is finished and rest will be added with time. Bellow you can see effects of last month programming.


Looks almost the same like old one, right? If you think this way than I'm happy because the biggest change is not in its look but in the code that handle it.

But lets start with basics. My properties widget was and still is based on custom RTTI. If you curious how it look here you have some example from code:

In header (*.h):
    /*
    ===================================================================
    Main game object class.
    ===================================================================
    */
    class CGameObject : public CRttiObject
    { 
        RTTI(CGameObjectCRttiObject);
     public:
                                    CGameObjectvoid );
        virtual                     ~CGameObjectvoid );
        ...
    private:
        CGameObjectID               m_Index;
        wrStringID                  m_Name;
        wrBitflag<EGOFlags::Enum>   m_GameFlags;
        ...     };
In source code (*.cpp)
RTTI_DECLARATION_NOPARENT_BEGIN(CGameObject)
    RTTI_FILTER_BEGIN("general")
        RTTI_ATTRIB(m_Index)
            .setAlias("id")
            .setEditorParams("[Unique]")
            .setFlags(EAttribFlag::NotSerializable|EAttribFlag::NoEdition);
 
        RTTI_ATTRIB(m_Name)
            .setAlias("name")
            .bindSetCallback(&CGameObject::setNameCallback)
            .setEditorParams("[Unique]");
    RTTI_FILTER_END
 
    RTTI_FILTER_BEGIN("render")
        RTTI_ATTRIB(m_GameFlags)
            .setAlias("gameflags")
            .bindSetCallback(&CGameObject::onSetGameFlags)
            .setEnumDesc(EGOFlags::desc);
    RTTI_FILTER_END
    RTTI_ATTRIB_ARRAY(m_components)
        .setAlias("Components")
        .setEditorParams("[filter:IGameObjectComponent]")
        .bindSetEvent(&CGameObject::setComponentEvent)
        .setFlags(EAttribFlag::NotSerializable);
RTTI_DECLARATION_END
...
Old properties system

Old properties system was rather straight forward. UI widget contain pointers to all classes that properties were display. It iterate over their attributes and create properties tree. When any element was changed UI code just iterate over classes again and changed value in them. Simple right?

Pros:
  • There was easy control over class which properties you edit.
  • It was executed really efficiently.
  • It was implemented and it worked.

Cons:
  • Because of new threading setup you could set value in meantime of some important operation. This could create random crashes and weird behaviors. In my test it worked, but it was just luck and I knew about it.
  • There were missing functionality I need for new animation system.
  • A lot of edition functionality was inside UI code which is ugly.
There was no choice at some point I needed to switch properties system. Because I needed to add some new functionality I decided it's good time to do it.


New properties system

New system is different. Creation of tree, acquiring of values, setting values are events. This events are send from UI thread and process on App thread asynchronously. After that UI thread get notification about finishing event and process returned data.

Pros:
  • There is no problem with randomly changed memory in meantime of App Thread execution.
  • Events don't contain any raw pointers only serialized data (UI don't know anything about objects it modify. It get tree and data description.)
  • Properties widget is independent from game/engine code. It's based purely on Qt code.

Cons:
  • It's for sure slower because I need to serialize data to some memory container which later I need to parse (In most cases this won't be noticeable).
  • There is no longer possibility to access any classes information without events.
  • I need to handle cases where execution/processing of event take some longer time (events are asynchronous).
Summary

Right now when new plugin is in usable state I see that this was good change. Of course price was high: one month of work which could be spend in some other areas. But well with time it will probably repay itself and allow me to create even more awesome game. And on this hopeful wish I will finish this post. Till the next time.

Greg

No comments:

Post a Comment