problem accessing GUI element attributes (solved)

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

problem accessing GUI element attributes (solved)

Post by vectorcorpse »

Hi, i am writing a multi language app with i18n support already working, and i am using the irrlicht GUI and the the GUI editor to create the menus.
I managed to get around the missing factory in the editor by creating the drop down menu in code and saving the GUI to xml, but now i am not being able to figure out how to access the attributes in the menu element in order to feed the i18n translator and put back it's respective translated text, i can grab the element itself by ID but i cannot reach the Text0 attribute, i'v been searching in the forum, on the irrlicht API and in the GUI editor source and all i got is that it is related to the serializeAttributes and deserializeAttributes functions but it is a not a popular topic in the forum and i am not being able to figure out how to work with it.
the portion of the xml xml looks like this:

Code: Select all

       <element type="menu">
 
        <attributes>
            <string name="Name" value="" />
            <int name="Id" value="2" />
            <string name="Caption" value="" />
            <rect name="Rect" value="0, 0, 800, 19" />
            <position name="MinSize" value="1, 1" />
            <position name="MaxSize" value="0, 0" />
            <enum name="LeftAlign" value="upperLeft" />
            <enum name="RightAlign" value="upperLeft" />
            <enum name="TopAlign" value="upperLeft" />
            <enum name="BottomAlign" value="upperLeft" />
            <bool name="Visible" value="true" />
            <bool name="Enabled" value="true" />
            <bool name="TabStop" value="false" />
            <bool name="TabGroup" value="false" />
            <int name="TabOrder" value="-1" />
            <bool name="NoClip" value="false" />
            <position name="Position" value="0, 0" />
            <int name="CloseHandling" value="1" />
            <int name="ItemCount" value="4" />
            <bool name="IsSeparator0" value="false" />
            <string name="Text0" value="File" />
            <int name="CommandID0" value="-1" />
            <bool name="Enabled0" value="true" />
            <bool name="Checked0" value="false" />
            <bool name="AutoChecking0" value="false" />
            <bool name="IsSeparator1" value="false" />
            <string name="Text1" value="View" />
            <int name="CommandID1" value="-1" />
            <bool name="Enabled1" value="true" />
            <bool name="Checked1" value="false" />
            <bool name="AutoChecking1" value="false" />
            <bool name="IsSeparator2" value="false" />
            <string name="Text2" value="Camera" />
            <int name="CommandID2" value="-1" />
            <bool name="Enabled2" value="true" />
            <bool name="Checked2" value="false" />
            <bool name="AutoChecking2" value="false" />
            <bool name="IsSeparator3" value="false" />
            <string name="Text3" value="Help" />
            <int name="CommandID3" value="-1" />
            <bool name="Enabled3" value="true" />
            <bool name="Checked3" value="false" />
            <bool name="AutoChecking3" value="false" />
        </attributes>
Could some of the gurus around here shed some light on the subject pls :)
Last edited by vectorcorpse on Wed Nov 23, 2016 12:43 am, edited 1 time in total.
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: problem accessing GUI element attributes

Post by CuteAlien »

Not 100% certain at which point you are stuck. I guess you have an IAttributes pointer already? Then you use getAttributeAsString on that. But in this case you have to build the attributeName first. So you first get ItemCount to know how many texts you need and then create attributeName "Text0" , "Text1", etc.

You can check the source of CGUIContextMenu::deserializeAttributes which also has to do that.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

Re: problem accessing GUI element attributes

Post by vectorcorpse »

well, nope, i don't have a IAttributes pointer :P i am translating things like window caption text or button caption text like this:

Code: Select all

guienv->getRootGUIElement()->getElementFromId(0)->setText(utf8_to_wide(dict.translate(wide_to_utf8(guienv->getRootGUIElement()->getElementFromId(0)->getText())).c_str()).c_str());
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

Re: problem accessing GUI element attributes

Post by vectorcorpse »

is there any detailed tutorial on how to handle IAttributes? besides de Irrlicht API
i don't quite grasp the way they work from looking at the source of the GUI editor, its way to many things at once.
what do you recommend me to study to get in touch with its inner working, considering i have no clue were to begin with :oops:

thx in advance.
Seven
Posts: 1030
Joined: Mon Nov 14, 2005 2:03 pm

Re: problem accessing GUI element attributes

Post by Seven »

maybe this helps......

objects serialize / deserialize themselves
virtual function allows heirarchy

Code: Select all

 
    //! Writes attributes of the object.
    void CSObject::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options)
    {
        // log this event
        CS_LOG(CSL_DEBUG, "CSObject::serialize()");
 
        out->addInt("Id", m_Id);
        out->addString("Name", m_Name.c_str());
        out->addVector3d("Position", m_Position);
        out->addVector3d("Rotation", m_Rotation);
        out->addVector3d("Scale", m_Scale);
        out->addVector3d("PositionOffset", m_PositionOffset);
        out->addVector3d("RotationOffset", m_RotationOffset);
        out->addVector3d("ScaleOffset", m_ScaleOffset);
        out->addVector3d("BBOffset", m_BBOffset);
        out->addFloat("Mass", m_Mass);
    }
 
    //! Reads attributes of the object.
    void CSObject::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
    {
        // log this event
        CS_LOG(CSL_DEBUG, "CSObject::deserialize()");
 
        m_Id = in->getAttributeAsInt("Id");
        m_Name = in->getAttributeAsString("Name");
        m_Position = in->getAttributeAsVector3d("Position");
        m_Rotation = in->getAttributeAsVector3d("Rotation");
        m_Scale = in->getAttributeAsVector3d("Scale");
        m_PositionOffset = in->getAttributeAsVector3d("PositionOffset");
        m_RotationOffset = in->getAttributeAsVector3d("RotationOffset");
        m_ScaleOffset = in->getAttributeAsVector3d("ScaleOffset");
        m_BBOffset = in->getAttributeAsVector3d("BBOffset");
        m_Mass = in->getAttributeAsFloat("Mass");
    }
 

level class loads objects from xml file

Code: Select all

 
    bool CSLevel::saveToDisk(stringc filename)
    {
        CS_LOG(CSL_DEBUG, "%s %s", "saving level to file ", filename);
 
        IXMLWriter* writer = getDevice()->getFileSystem()->createXMLWriter(filename);
        if (!writer)
        {
            CS_LOG(CSL_WARNING, "Warning! unable to create save file");
            return false;
        }
 
        writer->writeXMLHeader();
 
        vector3df pos(0, 0, 0);
        vector3df tar(0, 0, 0);
        if (getSmgr()->getActiveCamera())
        {
            pos = getSmgr()->getActiveCamera()->getPosition();
            tar = getSmgr()->getActiveCamera()->getTarget();
        }
 
        // write the camera position and target
        writer->writeLineBreak();
        writer->writeElement(L"CAMERA", false,
            L"POSITION", stringw(vector3dfToStringc(pos)).c_str(),
            L"TARGET", stringw(vector3dfToStringc(tar)).c_str()
            );
        writer->writeLineBreak();
 
        writer->writeLineBreak();
        writer->writeElement(L"LIGHT", false,
            L"USE", stringw(boolToStringc(getUseLight())).c_str(),
            L"AMBIENTLIGHT", stringw(SColorfToStringc(m_AmbientLight)).c_str());
        writer->writeLineBreak();
 
 
        writer->writeLineBreak();
        writer->writeElement(L"FOG", false,
            L"USE", stringw(boolToStringc(getUseFog())).c_str(),
            L"COLOR", stringw(SColorToStringc(m_FogParams.m_Color)).c_str(),
            L"START", stringw(floatToStringc(m_FogParams.m_Start)).c_str(),
            L"END", stringw(floatToStringc(m_FogParams.m_End)).c_str());
        writer->writeLineBreak();
 
        writer->writeLineBreak();
        writer->writeElement(L"DEBUGINFO", false,
            L"USE", stringw(boolToStringc(getUsePhysXDebugRender())).c_str());
        writer->writeLineBreak();
 
        writer->writeLineBreak();
        writer->writeElement(L"MAINCHARACTERID", false,
            L"USE", stringw(intToStringc(getMainCharacterId())).c_str());
        writer->writeLineBreak();
 
        writer->writeLineBreak();
 
 
        CSObject* obj = getObjectFactory()->getObjectManager()->getNextObject(true);
        while (obj)
        {
            if (!obj->getIsDebugObject())
            {
                stringw name("CSOBJECT");
                writer->writeElement(name.c_str(), false, L"TYPE", stringw(obj->getInfo()->getName()).c_str());
                writer->writeLineBreak();
 
                IAttributes* attr = getDevice()->getFileSystem()->createEmptyAttributes(getDriver());
                SAttributeReadWriteOptions options;
                obj->serializeAttributes(attr, &options);
 
                if (attr->getAttributeCount() != 0)
                {
                    attr->write(writer);
                    writer->writeLineBreak();
                }
 
                attr->drop();
 
                writer->writeClosingTag(name.c_str());
                writer->writeLineBreak();
                writer->writeLineBreak();
            }
            obj = getObjectFactory()->getObjectManager()->getNextObject(false);
        }
 
        writer->drop();
 
        return true;
    }
 
    bool CSLevel::loadFromDisk(stringc filename)
    {
        CS_LOG(CSL_DEBUG, "%s %s", "loading level from file ", filename);
 
        IXMLReader* reader = getDevice()->getFileSystem()->createXMLReader(filename);
        if (!reader)
        {
            CS_LOG(CSL_WARNING, "Warning! unable to open save file");
            return false;
        }
 
        // read file
        while (reader->read())
        {
            switch (reader->getNodeType())
            {
            case io::EXN_ELEMENT:
                stringw name = reader->getNodeName();
 
                // if this is an object definition
                if (stringw("CAMERA") == name)
                {
                    stringw pos = reader->getAttributeValueSafe(L"POSITION");
                    stringw tar = reader->getAttributeValueSafe(L"TARGET");
                    if (getSmgr()->getActiveCamera())
                    {
                        getSmgr()->getActiveCamera()->setPosition(stringcToVector3df(stringc(pos)));
                        getSmgr()->getActiveCamera()->setTarget(stringcToVector3df(stringc(tar)));
                    }
                    else CS_LOG(CSLOGTYPE::CSL_WARNING, "no camera in game save file");
                }
 
                // if this is an object definition
                // if this is an object definition
                if (stringw("LIGHT") == name)
                {
                    stringw use = reader->getAttributeValueSafe(L"USE");
                    stringw color = reader->getAttributeValueSafe(L"AMBIENTLIGHT");
                    setUseLight(stringcToBool(use));
                    setAmbientLight(stringcToSColorf(color));
                }
 
                // if this is an object definition
                if (stringw("FOG") == name)
                {
                    stringw use = reader->getAttributeValueSafe(L"USE");
                    stringw color = reader->getAttributeValueSafe(L"COLOR");
                    stringw start = reader->getAttributeValueSafe(L"START");
                    stringw end = reader->getAttributeValueSafe(L"END");
                    m_FogParams.m_Color = stringcToSColor(color);
                    m_FogParams.m_Start = stringcToFloat(start);
                    m_FogParams.m_End = stringcToFloat(end);
                    setFogParams(m_FogParams);
                    setUseFog(stringcToBool(use));
                }
 
                // if this is an object definition
                if (stringw("DEBUGINFO") == name)
                {
                    stringw use = reader->getAttributeValueSafe(L"USE");
                    setUsePhysXDebugRender(stringcToBool(use));
                }
 
                // if this is an object definition
                if (stringw("MAINCHARACTERID") == name)
                {
                    stringw use = reader->getAttributeValueSafe(L"USE");
                    setMainCharacterId(stringcToInt(use));
                }
 
                if (stringw("CSOBJECT") == name)
                {
                    stringw type = reader->getAttributeValueSafe(L"TYPE");
 
                    CSObject* obj = getObjectFactory()->createObjectByType(stringc(type), false, 0, stringc(type), true);
                    if (obj)
                    {
                        IAttributes* attr = getDevice()->getFileSystem()->createEmptyAttributes(getDriver());
                        attr->read(reader, false);
                        obj->deserializeAttributes(attr);
                        obj->reCreate();
                        attr->drop();
                    }
                    else CS_LOG(CSL_WARNING, "Did not create object\n");
                }
            }
        }
        reader->drop();
 
        return true;
    }
 
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

Re: problem accessing GUI element attributes

Post by vectorcorpse »

yes, the second part of the code is how i use to save and load config data to/from a xml file, but now i need to edit from memory and i am not being able to understand how the serialize/deserialize relates to the element attributes, maybe i am missing something really easy...
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

Re: problem accessing GUI element attributes

Post by vectorcorpse »

btw, if i create an item with additem it is easy to set attributes has they are set on creation, but changing some of them like the text in a menu (file, edit, options...) after creation is the part i don't understand
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

Re: problem accessing GUI element attributes

Post by vectorcorpse »

Lets say i do this:

Code: Select all

    gui::IGUIContextMenu* menu = env->addMenu();
    menu->addItem(L"File", -1, true, true);
    menu->addItem(L"View", -1, true, true);
    menu->addItem(L"Camera", -1, true, true);
    menu->addItem(L"Help", -1, true, true);
and later i want to change the text to an arbitrary language, i can't do it the same way has with a window caption.
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: problem accessing GUI element attributes

Post by CuteAlien »

You have 2 ways. First is - you don't need serialization at all but insteada use menu->setItemText directly.
The second is using IAttributes and serialization. So you deserialize into IAttributes (which you created with createEmptyAttributes like Seven posted above). Then find the texts like I mentioned in last post. Then serialize the result back to the gui-element.

Or maybe I'm still not getting the problem. I remember I had one problem with internationalization - which was - where to keep the string used to look-up the translation strings. One way for that is to only keep id's to strings in the original xml's. But - you can only translate once then - because that id-text is then replaced by real text so it can't be used a second time. Meaning - if you want multiple languages you have to load from xml again each time.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
vectorcorpse
Posts: 86
Joined: Thu Feb 14, 2008 7:30 pm
Location: Portugal

Re: problem accessing GUI element attributes

Post by vectorcorpse »

Thank you both for the tips they really helped, CuteAlien that last tip really was a duh on me LOL but managed to make the so much needed click on my head, it was something really easy that i was missing and there was no need for serialization at all
all i was missing was pulling the context menu aside and point to the correct menu item from the index :D

Code: Select all

gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)guienv->getRootGUIElement()->getElementFromId(2, true);
menu->setItemText(0,utf8_to_wide(dict.translate(wide_to_utf8(menu->getItemText(0))).c_str()).c_str());
Post Reply