Sunday, May 24, 2015

Project generator

I like to experiments and have fun doing that. Right now I work on another crazy idea. You know because developing of game and technology behind is not enough. Don't worry this is just another side project connected with this one. 

Project generator.

I know that I could use some existing solutions (i.e CMake) but this wouldn't be so fun as doing it myself in python :] Well I started doing ... some time ago and returning to it whenever I had some time. Right now I'm at the level where Linux make support is better than previous generator I use. Sadly Microsoft Visual Studio support not exist there right now :D

Well I fix this in future. But lets move to some details about new project generator which is wrote in python.


Sunday, May 17, 2015

Singleton pattern

Singleton pattern... People love it or hate it. There are also group of people who don't mind them.

I'm still try figure out which I'm :] I'm for sure not the one who love them. I'm also cannot say that I rally hate them because I still use them in code (It is like with my Facebook account. After I created one I try not complain about fb. ). So probably I'm best fit to don't mind group.

But my past experience showing me that I have bigger tendency to removing them from code than adding new one. And probably some colleagues from work will be happy about this because we spend a lot of time discussing about problem.

I remove them because I put even more effort in good design of systems. In a lot of cases thanks to changes I just don't need global objects. Which is good. It allow me to better utilize multithreading thanks to encapsulation.

Today sadly I had problem where I still don't know cleaner solution than global state:

//////////////////////////////////////////////////////////////////////////
template<> bool write<CResHandle>( ISerializerWritera_writerconst CResHandlea_value )
{
    return a_writer.serialize(a_value.isValid() ? a_value->getId() : wrResourceID());
}

//////////////////////////////////////////////////////////////////////////
template<> bool read<CResHandle>( ISerializerReadera_readerCResHandlea_value )
{
    wrResourceID id;

    if (!a_reader.deserialize(id)) return false;

    if (CResource::isValid(id))
    {
        a_value = getResMgr()->createResource(id);
    }
    else
    {
        a_value = nullptr;
    }

    return true;
}

Function getResMgr() return global resource manager. I don't want to pass it around inside arguments because this is ugly and I would need to do the same with each manager I want to use. This would increase my arguments list and each new manager would recommend changes in all write/read functions.
I thought maybe about storing inside ISerializerReader/ISerializerWriter function like setData()/data() in some Qt classes. This way it will be really easily to extend list of available data even by game (which may add some new write/read functions). 

I'm still not sure about this solution and how nice it is. I will spend some time thinking about it but for now I will leave getResMgr() use with nice macro call right before it : 

WR_TODO("gwojciechowski""Think about way to not use global getResMgr().");

If you have any idea, thoughts or you just want to comment this. I'm open on opinion how to make this nice and clean :]

Greg 

Sunday, May 10, 2015

Sculptures gallery moved

To make my life simpler I moved my sculptures gallery to my deviant art account. You can find link in Arts page or here :

http://angelusda.deviantart.com/

UI

It's funny that only with time and experience you start to understanding how hard UI code is. I remember a lot of situations when UI freeze in meantime of doing something. Whole window is locked and you just prying that its still alive.

First version of my tools were similar: everything happening in one thread which was block when I was doing some longer operation. Because there was not too much to process it was not so painful. With time this changed, amount of data grow. To fix the issue I started adding progress bars to some operations and was happy.

Sadly I was still wrong. This solution is still messy. I block whole UI and just update progress bar when some operations may be processed in background. Recent change of threading taught me beaut of asynchronous operations.

Right now all my communication Engine <-> UI is happening by events which cleaning my design of whole tools. All code where I mix UI with mechanics changing in creation of event and processing of it later. Bellow you can see code creating event:

if (autoevent = m_appCtx->createEventT<CEditorEventGetLevelProperties>())
{
    event->setLevelSessionID(m_levelID);
    event->setUserData((size_t)a_properties);
    m_appCtx->submitEvent(eventfuncEventCallback()
                                 .connect(this, &QWrPropertiesEngine::onRequestTreeEvent));
}

Later I just need to process returned callback:

void QWrPropertiesEngine::onRequestTreeEventCEditorEventa_event )
{
    if (EErrors::isFailed(a_event->getErrorCode()))
    {
        return;
    }

    QPropertiesWidgetproperties = (QPropertiesWidget*)a_event->getUserData();

    Q_ASSERT(properties);

    autoevent = WR_RTTI_CAST_PTR(IEditorEventPropertiesa_event);

    Q_ASSERT(event);

    properties->clear();
    ...
}

I like this approach so much that I will probably switch in game UI on the same basics. How it will go we will see but for now I fell that this is good decision.

Greg