GUI Coding Syntax

A place for Ogre users to discuss non-Ogre subjects with friends from the community.
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

Slightly on topic.

Instead of exposing the API. How about ignoring it:

Code: Select all

void function(string)
{
};

Code: Select all

enum
{
  SOMETHING_HAPPENED = 1
};

Chocolate.registerEvent<string>(SOMETHING_HAPPENED, &function);

Code: Select all

Window << TextInput("Hi there",
                 _with
                     << Align(_Center)
                     << Font(_Bold),
                 _do 
                     << TextEntered(SOMETHING_HAPPENED));
Since your GUI has a limited possible amount of values; it makes sense that the events/callbacks would do to. Most of the time; you don't want the caller of the event; just the attributes of it. If you do need the caller, then it's important enough to keep a reference of it handy.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

betajaen wrote:Slightly on topic.

Instead of exposing the API. How about ignoring it:

Code: Select all

void function(string)
{
};

Code: Select all

enum
{
  SOMETHING_HAPPENED = 1
};

Chocolate.registerEvent<string>(SOMETHING_HAPPENED, &function);

Code: Select all

Window << TextInput("Hi there",
                 _with
                     << Align(_Center)
                     << Font(_Bold),
                 _do 
                     << TextEntered(SOMETHING_HAPPENED));
Since your GUI has a limited possible amount of values; it makes sense that the events/callbacks would do to. Most of the time; you don't want the caller of the event; just the attributes of it. If you do need the caller, then it's important enough to keep a reference of it handy.
I'm not quite sure what you're getting at. For example, my callbacks get an event as such:

Code: Select all

struct event { widget &caller; boost::any misc; };
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

nullsquared wrote:

Code: Select all

function createGUI(sheet)
    sheet
        :update(
            gui.window("debugWin")
                :update(
                    gui.panel("0")
                        :update("texture", "renderer_gbuffer_0")
                        :update("size", vec2(128, 128))
                        :update("draggable", false)

                    ,gui.panel("1")
                        :update("texture", "renderer_gbuffer_1")
                        :update("size", vec2(128, 128))
                        :update("draggable", false)

                    ,gui.panel("2")
                        :update("texture", "renderer_gbuffer_2")
                        :update("size", vec2(128, 128))
                        :update("draggable", false)

                    ,gui.panel("3")
                        :update("texture", "renderer_gbuffer_3")
                        :update("size", vec2(128, 128))
                        :update("draggable", false)

                    ,gui.panel("4")
                        :update("texture", "renderer_shade_texture")
                        :update("size", vec2(128, 128))
                        :update("draggable", false)
                ) -- end debugWin children
                :update("size", vec2(5 * 128, 128))
                :update("autoArrange")
                :update("title", "debug")

            ,gui.window("timeSpeedScrollbarWin")
                :update("size", vec2(128, 16))
                :update("resizable", false)
                :update("closable", false)
                :update("title", "time speed")
                :update(
                    gui.scrollbar("timeSpeedScrollbar")
                        :update("points", vec4(0, 0, 112, 0))
                        :update("position", vec2(112, 0))
                ) -- end timeSpeedScrollbarWin children

            ,gui.window("toolboxWin")
                :update("size", vec2(256, 128))
                :update("resizable", false)
                :update("title", "toolbox")

            ,gui.window("objectPropertiesWin")
                :update("size", vec2(256, 512))
                :update("resizable", false)
                :update("title", "object properties")
    ) -- end sheet children
end
Wow that was incredibly ugly! New version:

Code: Select all

sheet:update({
        debugWin = {
            type = "window",
            title = "debug",
            size = vec2(5 * 128, 128),
            panel0 = {
                type = "panel",
                size = vec2(128, 128),
                draggable = false,
                texture = "renderer_gbuffer_0"
            },
            panel1 = {
                type = "panel",
                size = vec2(128, 128),
                draggable = false,
                texture = "renderer_gbuffer_1"
            },
            panel2 = {
                type = "panel",
                size = vec2(128, 128),
                draggable = false,
                texture = "renderer_gbuffer_2"
            },
            panel3 = {
                type = "panel",
                size = vec2(128, 128),
                draggable = false,
                texture = "renderer_gbuffer_3"
            },
            panel4 = {
                type = "panel",
                size = vec2(128, 128),
                draggable = false,
                texture = "renderer_shade_texture"
            }
        },
        timeSpeedScrollbarWin = {
            type = "window",
            size = vec2(128, 16),
            resizable = false,
            closable = false,
            title = "time speed",
            timeSpeedScrollbar = {
                type = "scrollbar",
                points = vec4(0, 0, 112, 0),
                position = vec2(112, 0)
            }
        },
        toolboxWin = {
            type = "window",
            size = vec2(256, 128),
            resizable = false,
            title = "toolbox"
        },
        objectPropertiesWin = {
            type = "window",
            size = vec2(256, 512),
            resizable = false,
            title = "object properties"
        }
    })

sheet:child("debugWin"):update({
        autoArrange = true
    })
So much better! :D

Now my problem is the fact that autoArrange seems to be parsed before the other things even if its after them (unless I explicitly make a separate call, as shown)? Are the tables in Lua sorted? :( Any ideas?
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

nullsquared wrote:I'm not quite sure what you're getting at. For example, my callbacks get an event as such:

Code: Select all

struct event { widget &caller; boost::any misc; };
What I mean is; they should be simple. Simpler than that in fact and no "anys" either. :D
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

betajaen wrote:
nullsquared wrote:I'm not quite sure what you're getting at. For example, my callbacks get an event as such:

Code: Select all

struct event { widget &caller; boost::any misc; };
What I mean is; they should be simple. Simpler than that in fact and no "anys" either. :D
I don't understand how the caller widget will know what attributes to pass to the callback. Taking your example, how does the caller widget know what that string is for? What if it was an int, or something?

And what's bad about anys? As long as you're safe, there's nothing wrong with anys.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 538

Post by Kojack »

Are the tables in Lua sorted?
Tables in Lua are basically like maps in stl, so they most likely store their data in a binary tree of some kind. Which means they will be sorted in some way to provide fast lookup.

To preserve the order, you could nest the tables a bit deeper. For example, in this code:

Code: Select all

p = function(t) for i,j in pairs(t) do print(i.."="..j) end end
a = {y=1, x=2, a=3, g=4, d=5}
p(a)
the result is:
y=1
x=2
d=5
g=4
a=3
(not the same order as entered, the tree structure reorganised them)

Instead, do it like:

Code: Select all

b = {{y=1}, {x=2}, {a=3}, {g=4}, {d=5}}
for i,j in ipairs(b) do p(j) end
the result is:
y=1
x=2
a=3
g=4
d=5
The same order. When you add an item to a table without giving it a key, an incrementing numeric value is used (treating the table like a normal numeric indexed array. The ipairs function iterates a table in numeric index order (0, 1, 2, etc). A lot more braces, but it should fix the order problem.
User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
x 5
Contact:

Post by _tommo_ »

An advice using table as indexed arrays:

Instead of doing

Code: Select all

panel = {
type = "type",
size = vec2(),
...

You could do

Code: Select all

panel = { "type", vec2(),
...
And index the first two unnamed values using numerical indexes in C++... this has two advantages:
-you haven't to write type and size each time;
-you force the user to put type and size at the top of the declaration, making it easier to read.

Just an advice anyway :D

You could also make those callbacks more elegant wrapping the Lua Stack to a C++ class; here's how i call my callbacks (wich are the most important part of the scripting in my game):

Code: Select all


//get the Lua Manager
	sm = GameServer::get<ScriptManager>();

//call object construction callback, named typeName+"_onCreation()"

	sm->luaLoadFunction( typeName + "_onCreation");
	sm->luaLoadParam<InkObject*>( "Object", this );	//SELF
	sm->luaLoadParam( position.x );					//X
	sm->luaLoadParam( position.y );					//Y
	sm->luaLoadParam<Trace*>("Trace", t);		//TRACE
	sm->luaCallFunction( 0 );                                //No results
So, you can call a callback of any shape, without using any crazy boost things, but only const char* + some functions :D
And these are all iinline functions!

PS: yes, i find Boost really bloated...
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

_tommo_ wrote:An advice using table as indexed arrays:
Thing about that is that it's not explicit, and it is specifically ordered. The user may want a default size, or a position before a size, or an auto-calculated size, and so on.
You could also make those callbacks more elegant wrapping the Lua Stack to a C++ class; here's how i call my callbacks (wich are the most important part of the scripting in my game):

Code: Select all


//get the Lua Manager
	sm = GameServer::get<ScriptManager>();

//call object construction callback, named typeName+"_onCreation()"

	sm->luaLoadFunction( typeName + "_onCreation");
	sm->luaLoadParam<InkObject*>( "Object", this );	//SELF
	sm->luaLoadParam( position.x );					//X
	sm->luaLoadParam( position.y );					//Y
	sm->luaLoadParam<Trace*>("Trace", t);		//TRACE
	sm->luaCallFunction( 0 );                                //No results
Using luabind:

Code: Select all

// L is your lua_State
luabind::call_function<void>(L, typeName + "_onCreation", this, position.x, position.y, t);
;)
So, you can call a callback of any shape, without using any crazy boost things, but only const char* + some functions :D
And these are all iinline functions!
Same with luabind. What I was talking about was this:

Code: Select all

// C++ widget callback
void scrolledCallback(const gui::event &e)
{
    std::cout << "scrolled scrollbar "" << e.caller.name() << ""\n";
}

// register as onScroll
someScrollbar.callback("onScroll", boost::bind(&scrolledCallback, _1));
That's pretty easy C++.

But what if you wanted Lua to be able to register Lua-based callbacks for the widgets? Obviously you can't use boost::bind(the_lua_function) ;). But it can be done - you need a proxy C++ widget callback that receives a Lua object (luabind::object) which corresponds to the Lua widget callback. Then, using boost::bind, you'd bind the widget's callback to this proxy C++ callback, use _1 for the event (widget passes it), and pass the Lua function for the second parameter. The widget doesn't know that it's now calling a Lua callback ;)
PS: yes, i find Boost really bloated...
Have you actually tried it and used it? I used to think it was really bloated and unnecessary, too - until I started using it. This thing is full of goodness and nothing else. And it's all headers - you don't need to compile anything (unless you use the platform-specific things, like Boost.Filesystem, which needs to be compiled first).
User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
x 5
Contact:

Post by _tommo_ »

Well, I like to reinvent the wheel :lol:

Anyway yes, i became unconfident with Boost after trying to use Boost::Python and luabind... wich was way more difficult than pure Lua C API to compile and use, and event to understand.
It uses really advanced template metaprogramming to cover a stack wich would have been simple in the 70s... the code may be clever, but the idea not much ;)

It blows the dependencies 8 mb up, and slowed down noticeabily the game only being activated... at least now i know much better how interpreted languages work, and how to have the least impact on the framerate...

For what I tried to obtain, boost was really bloated... but this depends on what you need. :wink:
My only regret are Lua Classes... I recreated a fake OOP, but I can't have "real" classes... not that it's a priority now...
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

Well, I certainly don't like reinventing the wheel. I wouldn't be able to code up anything decent in a short amount of time if I couldn't use boost (and if boost was applicable, of course). Not to even talk about the SC++L. Yes, Luabind is extremely complicated - I had a bit of trouble compiling it at first (read: LOADS of trouble :lol:). But once you get it working, it makes things so much easier. And the biggest problem is increased compilation times for the units that use luabind - I saw no runtime overhead whatsoever.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 538

Post by Kojack »

I stopped using Luabind when it was abandoned and no longer compatible with Lua. I haven't checked for ages to see if anybody has patched it for Lua 5.1.4. Now I just write all the interface code manually.

I really need to start playing with LuaJIT. It has large performance increases for mathematics, recursive function calls, table iteration and other areas, while remaining fully compatible with Lua 5.1.x. It only adds 32kb to your program.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

Kojack wrote:I stopped using Luabind when it was abandoned and no longer compatible with Lua.
Abondoned and not compatible with Lua? What?
GIT wrote: luabind/ November 10, 2008 Add missing include and namespace alias. [daniel-w]
src/ November 10, 2008 Use compute_score() when invoking constructors. [daniel-w]
http://github.com/luabind/luabind/tree/master

Code: Select all

I haven't checked for ages to see if anybody has patched it for Lua 5.1.4. Now I just write all the interface code manually.
The GIT repository code apparent works fine with 5.1.x. I still use the 0.7 version and Lua 5.0.3 because we have an automated Linux build system that is a pain in the ass when it comes to building and updating Luabind.

I used to write interface code manually, but it sucked, big time. For example, traversing a global Lua table:

Code: Select all

using luabind::object_cast;
using luabind::object;
using luabind::globals;
using luabind::type;
using luabind::iterator;

object table = globals(L)["theTable"];

if (type(table) != LUA_TTABLE)
    throw std::runtime_error("theTable is not a table");

for (iterator i(table), end; i != end; ++i)
{
    object key = i.key();
    object value = *i;

    // for example, setting a named string
    if (type(key) == LUA_TSTRING && type(value) == LUA_TSTRING)
        useNamedString(object_cast<std::string>(key), object_cast<std::string>(value));
}
I'd love to see the manual code for that, complete with the error checking and all.
I really need to start playing with LuaJIT. It has large performance increases for mathematics, recursive function calls, table iteration and other areas, while remaining fully compatible with Lua 5.1.x. It only adds 32kb to your program.
Intriguing.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 538

Post by Kojack »

Hmm, 0.7.1 of Luabind came out last month, and finally adds Lua 5.1 support.
Of course I've been using lua 5.1 since 2004. I got sick of waiting for a new luabind release around 2006 and just stopped using it.

What also made me decide to drop it was when I cut 66% of my compile time by removing the luabind include from one of my files (which only used it to export a single function I never used).

Still a pretty nice system if you want to expose c++ to Lua.
User avatar
syedhs
Silver Sponsor
Silver Sponsor
Posts: 2703
Joined: Mon Aug 29, 2005 3:24 pm
Location: Kuala Lumpur, Malaysia
x 51

Post by syedhs »

Luabind has been quiet last year, but came back active in the past months so it is not pretty much abandoned now.

Yeah luabind increase compilation time immensely, so the trick is to lump as much as luabind code in one C++ source code - if your design can afford to. And it also increase my executable file tremendously too as now, the luabind, lua and the bindings alone most probably are about 20% of my executable size :wink:

And I have seen several claims that luabind is slower, but for me I dont use lua for everything. Much of my lua uses is for customizing the scene ie the way the scene loads, the way it reacts to trigger, the way the vehicle/character is supposed to react given a circumstance.

And there is a function named tick in my lua script which is always called when the scene has been loaded. But I execute it only 10 times a second - I dont have to call the function 60hz or higher frequency and so far, it has satisfied my requirement.
A willow deeply scarred, somebody's broken heart
And a washed-out dream
They follow the pattern of the wind, ya' see
Cause they got no place to be
That's why I'm starting with me
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 538

Post by Kojack »

Good to see it's getting more active.
But I execute it only 10 times a second - I dont have to call the function 60hz or higher frequency and so far, it has satisfied my requirement.
The lua code in my 2d engine was calling an update function (which performs the whole game's logic) at over 1000fps, plus calling lua code to handle callbacks for all physics collisions.
And that's without LuaJIT.
I love Lua. :)



Although for bigger OO style stuff I'd prefer to use Ruby
gamedboy
Gremlin
Posts: 168
Joined: Wed Sep 19, 2007 1:19 pm
Location: singapore
x 3

Post by gamedboy »

/* in the log file */
*-*-* boost::bad_any_cast: failed conversion using boost::any_cast
in D:\programming\portalized\trunk\src\gui\widget.cpp
in virtual engine::gui::widget& engine::gui::widget::update(const engine
::string&, const boost::any&)
at line 331
if you are compiling with a compiler which support typeinfo, you can return the type name with any::type().name()
This thing is full of goodness and nothing else.
I agree. Although it performance may not be the best, but it offer a huge sense of security with very throughly tested codes.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

syedhs wrote:
Yeah luabind increase compilation time immensely, so the trick is to lump as much as luabind code in one C++ source code - if your design can afford to.
Exactly. Luabind is extremely compiler heavy with all of its template trickery and what-not. Lump as much luabind code into separate compilation units as you can, and keep your other code separate. Make wrappers around common functions you use, and use the wrappers (you don't have to wrap all of the functionality, just what you use). I keep specific bindings_gui.cpp, bindings_game.cpp, bindings_common.cpp, etc. that contain 99% of the luabind code, and the others I'm working on wrapping up so that they are out of the 'luabind takes over 9000 hours to compile' idea.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

This now works 100%:

Code: Select all

            panel0 = {
                type = "panel",
                size = vec2(128, 128),
                draggable = false,
                texture = "renderer_gbuffer_0",
                onClick = function(this)
                    log("clicked on widget \"" .. this:name() .. "\"")
                end
            },
All you boost nay-sayers, try doing this without boost :lol:

Code: Select all

        void _widgetLuaCallback(const gui::event &e, luabind::object func)
        {
            assert(luabind::type(func) == LUA_TFUNCTION);
            func(e.caller);
        }

// (iterating over the update table)
                    // callbacks can be bound as lua functions
                    case LUA_TFUNCTION:
                    {
                        const object &obj = *i;
                        _this.callback(key, boost::bind(&_widgetLuaCallback, _1, obj));
                    }
                    break;
User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
x 5
Contact:

Post by _tommo_ »

Yeah.:wink:

In Lua, you can request that a function becomes listener of an observable event::

Code: Select all

--register the listeners, to receive feedbacks from the game
	g:addListener("keyPressed", "KeyPressed");
	g:addListener("keyReleased", "keyReleased");
In C++, the callbacks are registerer to their queue type, and then fired when my Gameplay State class receives the actual callback:

Code: Select all

void GameplayState::registerListener(const char* type, const char* name)
{	
	size_t l = strlen(name);
	char* n = (char*)DMALLOC(sizeof(char)*l);
	strcpy(n, name);

	//registra il listener corretto
		 if( strcmp(type,"preRender" )==0 )	preRenderCalls.addElement( n );
	else if( strcmp(type,"postRender")==0 )	postRenderCalls.addElement( n);
	else if( strcmp(type,"keyPressed")==0 )	keyPressedCalls.addElement( n);
	else if( strcmp(type,"mouseMoved")==0 )	mouseMovedCalls.addElement( n);
	else if( strcmp(type,"keyReleased")==0) keyReleasedCalls.addElement(n);
	else
		std::cout << "Can't add a listener for the required type: " << type << "!" << std::endl;
}

//example: this one is called after each render call
void GameplayState::postRenderCall()
{
	//chiama tutti i callbacks
	for(unsigned int i = 0; i < postRenderCalls.size(); ++i)
	{
		scriptMgr->luaLoadFunction( postRenderCalls[i] );
		scriptMgr->luaCallFunction(0);
	}
}
And, using a contestualized callback registering function like yours, you could also skip the strcmp part...
And it doesn't require function pointers, any casts, table iterations, or 8 mb dependencies :twisted:
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

_tommo_ wrote:Yeah.:wink:

In Lua, you can request that a function becomes listener of an observable event::

Code: Select all

--register the listeners, to receive feedbacks from the game
	g:addListener("keyPressed", "KeyPressed");
	g:addListener("keyReleased", "keyReleased");
In C++, the callbacks are registerer to their queue type, and then fired when my Gameplay State class receives the actual callback:

Code: Select all

void GameplayState::registerListener(const char* type, const char* name)
{	
	size_t l = strlen(name);
	char* n = (char*)DMALLOC(sizeof(char)*l);
	strcpy(n, name);

	//registra il listener corretto
		 if( strcmp(type,"preRender" )==0 )	preRenderCalls.addElement( n );
	else if( strcmp(type,"postRender")==0 )	postRenderCalls.addElement( n);
	else if( strcmp(type,"keyPressed")==0 )	keyPressedCalls.addElement( n);
	else if( strcmp(type,"mouseMoved")==0 )	mouseMovedCalls.addElement( n);
	else if( strcmp(type,"keyReleased")==0) keyReleasedCalls.addElement(n);
	else
		std::cout << "Can't add a listener for the required type: " << type << "!" << std::endl;
}

//example: this one is called after each render call
void GameplayState::postRenderCall()
{
	//chiama tutti i callbacks
	for(unsigned int i = 0; i < postRenderCalls.size(); ++i)
	{
		scriptMgr->luaLoadFunction( postRenderCalls[i] );
		scriptMgr->luaCallFunction(0);
	}
}
First of all, you're using C++, so is there a reason you're not using std::string ;) (unless you're in some type embedded environment or something)
And it doesn't require function pointers, any casts, table iterations, or 8 mb dependencies :twisted:
There's nothing wrong with function pointers or any casts (or table iterations, considering tables are a major part of Lua). And Luabind is only 377kb, and it's statically linked (no DLL). Boost is headers-only, it doesn't even have a lib (well, it does, for things like Boost.Thread, but I'm not using those here).

My point is, while your code is functional for what you need it to do, what if you wanted to use some unnamed function like so:

Code: Select all

game:addListener("keyPressed", function(key) print("pressed key " .. key) end)
Obviously that's not possible, since you're not passing around Lua objects, just a function name.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

Kojack wrote:
Are the tables in Lua sorted?
To preserve the order, you could nest the tables a bit deeper. For example, in this code:

Code: Select all

p = function(t) for i,j in pairs(t) do print(i.."="..j) end end
a = {y=1, x=2, a=3, g=4, d=5}
p(a)
the result is:
y=1
x=2
d=5
g=4
a=3
(not the same order as entered, the tree structure reorganised them)

Instead, do it like:

Code: Select all

b = {{y=1}, {x=2}, {a=3}, {g=4}, {d=5}}
for i,j in ipairs(b) do p(j) end
Added :D

Code: Select all

                testText = {
                    type = "text",
                    -- preserve the order, use braces
                    { font = "courier" },
                    { text = "lol testing" }
                }
It really helps in cases like these where the text ends up being set before the font :lol:

And it was only literally 3 more lines of code.
(before)

Code: Select all

                if (type(keyObj) != LUA_TSTRING)
                {
                        log("key invalid (widget update of "" + _this.name() + "")");

                    continue;
                }
(after)

Code: Select all

                if (type(keyObj) != LUA_TSTRING)
                {
                    if (type(*i) == LUA_TTABLE)
                    {
                        // nested table, probably to avoid ordering issues in
                        // the lua tables... just iterate through it
                        _updateWidget(_this, *i);
                    }
                    else
                        log("key invalid (widget update of "" + _this.name() + "")");

                    continue;
                }
User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
x 5
Contact:

Post by _tommo_ »

Well, my code can do less than the boost library, but that's obvious ;)
I was only saying that, while Boost creates some overhead, and complicates the code with not-so-straightforward features, you can do everything with C strings and the Lua C API... but anyway what you choose depends on what you need!

For example, I need those const chars* only for comparation in the registerlistener method, so there's no point (for what I know) in using std::string wich is also a bit slower...
and there's no point also in using unnamed functions: script code should be the more possibile brain-dead easy, and those functions go for sure on the "advanced" side of Lua ;)

IMHO, forcing the user to declare full functions makes the code more readable, for sure more than using nested function declarations...
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

_tommo_ wrote: I was only saying that, while Boost creates some overhead, and complicates the code with not-so-straightforward features, you can do everything with C strings and the Lua C API... but anyway what you choose depends on what you need!
Boost may not really create as much of an overhead as you may think. It's going into the new C++ standard - I think that says something ;).
For example, I need those const chars* only for comparation in the registerlistener method,
My question is, ... why?

Code: Select all

void GameplayState::registerListener(const std::string &type, const std::string &name)
{    
   //registra il listener corretto 
       if( type == "preRender" )   preRenderCalls.addElement( name ); 
   else if( type == "postRender" )   postRenderCalls.addElement( name); 
   else if( type == "keyPressed" )   keyPressedCalls.addElement( name); 
   else if(type == "mouseMoved" )   mouseMovedCalls.addElement( name); 
   else if( type == "keyReleased") keyReleasedCalls.addElement(name); 
   else 
      std::cout << "Can't add a listener for the required type: " << type << "!" << std::endl; 
} 
;)
so there's no point (for what I know) in using std::string wich is also a bit slower...
Again, there's no proof that std::string is slower. You do know that sizeof(std::string) == sizeof(char*), right ;)? (on most typical implementations) Accessing the string is not any slower, comparing it is faster (precached length, no '\0' searching), etc.
and there's no point also in using unnamed functions: script code should be the more possibile brain-dead easy, and those functions go for sure on the "advanced" side of Lua ;)

IMHO, forcing the user to declare full functions makes the code more readable, for sure more than using nested function declarations...
Right, but then it's not Lua anymore, it's just scripted C++ with a slightly different syntax. Pretty much the way I was previously using chained update() calls instead of a more proper Lua-like table.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

On the point of temp Lua functions:

Code: Select all

function createGUI(...)
    ...

    local function button(tex, callback)
        return {
            type = "panel",
            size = vec2(64, 64),
            draggable = false,
            texture = tex,
            onClick = callback
        }
    end

    gui.sheet:update({
        { fileNew = button("media/gui/button_file_new.png") },
        { fileOpen = button("media/gui/button_file_open.png") },
        { fileSave = button("media/gui/button_file_save.png") },
        { undo = button("media/gui/button_undo.png", function() game.actions:act("undo") end) },
        { redo = button("media/gui/button_redo.png", function() game.actions:act("redo") end) },
        ...
Look at how clean and useful this Lua code is. Imagine it if the callbacks were name-based :shock:
Post Reply