[GUI] display-only listbox?

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

Post Reply
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

[GUI] display-only listbox?

Post by doofus-01 »

Hi,

I should start out by saying I barely know what I'm doing here, so this may be a stupid question, but is there some disconnect between what Lua can access and what is seen in :inspect?

Code: Select all

local uor = wesnoth.get_recall_units({ side = "1" })
--  these work:
      wesnoth.message(string.format("%s", uor[i].type))
      wesnoth.message(string.format("%s", uor[i].id))  
--   there is no uor[i].profile, it seems, this does not work, no matter how you assign the profile with wml:
      wesnoth.message(string.format("%s", uor[i].profile))
But using :inspect, I can see there is an entry for the profile image for that unit
I can print a profile image path by getting it from the unit_type...

Code: Select all

        local uort = wesnoth.unit_types[uor[i].type].__cfg
        wesnoth.message(string.format("%s", uort.profile))
... but that's not what I want - I want the image for that specific unit, not the unit-type.
Spoiler:
EDIT: Forgot to say, I'm using BfW 1.12.1 (and shall be updating...)
Last edited by doofus-01 on May 25th, 2015, 6:59 pm, edited 3 times in total.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: wesnoth.get_recall_units - not all unit keys valid?

Post by gfgtdf »

It is indeed not possible to get the profile via unit.profile most likeley is was just an oversight. You should file a bug report, most likeley it will then be implemented in 1.13.x.

You still can get the units profile with unit.__cfg.profile.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

Re: wesnoth.get_recall_units - not all unit keys valid?

Post by doofus-01 »

gfgtdf wrote:You still can get the units profile with unit.__cfg.profile.
Thanks, that works.
gfgtdf wrote:It is indeed not possible to get the profile via unit.profile most likeley is was just an oversight. You should file a bug report, most likeley it will then be implemented in 1.13.x.
OK, done: http://gna.org/bugs/index.php?23467
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

accessing traits attributes

Post by doofus-01 »

How would one access the trait values of a unit, say "unit.modifications.trait[1].male_name"? I've tried doing it directly, and also with wesnoth.get_child, and while the wiki example of getting some unit's forest movement cost works fine, it doesn't work for unit.modifications.

I've found some add-ons that are good for examples of Lua/GUI/WML stuff, like "Era of High Sorcery" and "Scenario with robots", but they are confusing, and I understand just about nothing in EoHS.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: accessing traits attributes

Post by gfgtdf »

The documentation for lua unit proxies: http://wiki.wesnoth.org/LuaWML:Units shows which unit propoerties are directly accesible from lua, for everything not listed there you need to read them via unit.__cfg and write to them via wesnoth.put_unit/wesnoth.create_unit which are the lua versions of [unstore_unit] (or using wesnoth.add_modification which is similar to [object])
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

Re: accessing WML unit data

Post by doofus-01 »

gfgtdf wrote:for everything not listed there you need to read them via unit.__cfg
Right, if I want to get something like, say, "jamming" value or "profile" value, that works fine. But if it's buried further, like the traits, I'm not having much luck.
unit[i].__cfg.modifications.trait[1].male_name causes error scripting/lua: ....wesnoth1_12_1/data/add-ons/LuaGUI_Test/lua/GUI_Test.lua:100: attempt to index field 'modifications' (a nil value)

How would you reference the "male_name" field of the first trait of a unit?
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
mattsc
Inactive Developer
Posts: 1217
Joined: October 13th, 2010, 6:14 pm

Re: accessing WML unit data

Post by mattsc »

Hi doofus-01,

I don't have time to reply in detail right now (or ever, it seems :P ), but if I may make a couple suggestions, I'd strongly suggest that you get the Wesnoth Lua Pack (WLP) and check out the dbms() function in the debug library. Alternatively, you could get "AI modification demos" (yes, shameless plug here) and start the test scenario with
./wesnoth -t aid_test

That will give you a right-click option (with keyboard shortcut) to execute the code in AI-demos/lua/test_lua.lua to test lua code without reloading; just change the code and right-click again and the new version will be executed. This also includes an (also entirely shameless) copy of the dbms function from the WLP.

If you do that, you can see that modifications are implemented in Lua as shown below, and you can access them with helper.get_child or helper.child_range.

I apologize for this not being a very comprehensive reply, but maybe it helps by pointing you in the right direction a little... I can add more detail later...

Code: Select all

    [18] = {
                   [1] = "modifications",
                   [2] = {
                                 [1] = {
                                               [1] = "trait",
                                               [2] = {
                                                             [1] = {
                                                                           [1] = "effect",
                                                                           [2] = {
                                                                                         apply_to = "attack",
                                                                                         increase_damage = 1,
                                                                                         range = "melee"
                                                                                     }
                                                                       },
                                                             [2] = {
                                                                           [1] = "effect",
                                                                           [2] = {
                                                                                         apply_to = "hitpoints",
                                                                                         increase_total = 1
                                                                                     }
                                                                       },
                                                             female_name = "strong",
                                                             id = "strong",
                                                             male_name = "strong"
                                                         }
                                           },
                                 [2] = {
                                               [1] = "trait",
                                               [2] = {
                                                             [1] = {
                                                                           [1] = "effect",
                                                                           [2] = {
                                                                                         apply_to = "max_experience",
                                                                                         increase = "-20%"
                                                                                     }
                                                                       },
                                                             female_name = "intelligent",
                                                             id = "intelligent",
                                                             male_name = "intelligent"
                                                         }
                                           }
                             }
               },
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: accessing WML unit data

Post by Elvish_Hunter »

doofus-01 wrote:
gfgtdf wrote:for everything not listed there you need to read them via unit.__cfg
Right, if I want to get something like, say, "jamming" value or "profile" value, that works fine. But if it's buried further, like the traits, I'm not having much luck.
unit[i].__cfg.modifications.trait[1].male_name causes error scripting/lua: ....wesnoth1_12_1/data/add-ons/LuaGUI_Test/lua/GUI_Test.lua:100: attempt to index field 'modifications' (a nil value)

How would you reference the "male_name" field of the first trait of a unit?
In this case, you can't access directly a sub-tag, like [modifications]. You need to first acquire it with helper.get_child.
Once that you acquired it, you'll notice that [modifications] usually has two [trait] sub-tags, but helper.get_child returns only the first. If there is more than one tag with the same name, you need to use helper.child_range, which returns an iterator that can be read with a for cycle.
Here there is a concrete example:

Code: Select all

local helper = wesnoth.require "lua/helper.lua"
local unit = wesnoth.get_units( { side = 1 } )[1]
local mods = helper.get_child( unit.__cfg, "modifications" ) -- get the only [modifications] child tag

for trait in helper.child_range( mods, "trait" ) do -- iterate through all the [trait] children tags
	wesnoth.message( trait.id )
end
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

Re: accessing WML unit data

Post by doofus-01 »

Elvish_Hunter wrote:In this case, you can't access directly a sub-tag, like [modifications]. You need to first acquire it with helper.get_child.
Once that you acquired it, you'll notice that [modifications] usually has two [trait] sub-tags, but helper.get_child returns only the first. If there is more than one tag with the same name, you need to use helper.child_range, which returns an iterator that can be read with a for cycle.
Here there is a concrete example:
Thanks, Elvish_Hunter, that works. I didn't get it earlier, but now that I see what you did, the LuaWML wiki entry on those child things makes perfect sense.
mattsc wrote:I apologize for this not being a very comprehensive reply, but maybe it helps by pointing you in the right direction a little... I can add more detail later...
Thanks, mattsc, that helps. I don't know why I didn't think to look at the AI demos, I'll give those and dbms() a try.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

WML array into unit.variables

Post by doofus-01 »

I'm trying to insert a container into a unit's [variables] tag, so, something like this (WML):

Code: Select all

[unit]
...
    [variables]
         [donuts]
             id = "bearclaw"
             text = "this is good"
         [/donuts]
         [donuts]
             id = "cruller"
             text = "this is bad"
         [/donuts]
     [/variables]
...
[/unit]
I can insert "bearclaw" just fine with (lua):

Code: Select all

     wesnoth.fire("store_unit", { variable="my_unit", { "filter", { id = unit_id } } })
     wesnoth.set_variable("my_unit.variables", { {"donuts", { id = "bearclaw", text= "this is good"}}})   
     wesnoth.fire("unstore_unit", { variable="my_unit", find_vacant = "no"})
but then when I move on to assigning "cruller", "bearclaw" gets overwritten. Is there a way to reference indexes? Whenever I try something like wesnoth.get_variable("unit.variables.donuts[$index].id"), where "index" is a wml (not lua) variable, I'm told it's an "invalid WML array index"

Using table.insert(unit[1].__cfg[6][2], {{"donuts", {id = "bearclaw", text = "..."}}}) doesn't do anything, (leave off the [2] doesn't matter), I checked unit[1].__cfg[6] before and after with Wesnoth Lua pack's dbms() function (that's how I got the [6] index, I realize that may change and I shouldn't hard-code it).

Does it have anything to do with helper.set_wml_var_metatable? That sounds promising, but I find the wiki section on that to be useless, and none of the add-ons I've got as examples seem to use it, really.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: WML array into unit.variables

Post by gfgtdf »

doofus-01 wrote: I'm trying to insert a container into a unit's [variables] tag, so, something like this (WML):

Code: Select all

[unit]
...
    [variables]
         [donuts]
             id = "bearclaw"
             text = "this is good"
         [/donuts]
         [donuts]
             id = "cruller"
             text = "this is bad"
         [/donuts]
     [/variables]
...
[/unit]
I can insert "bearclaw" just fine with (lua):

Code: Select all

     wesnoth.fire("store_unit", { variable="my_unit", { "filter", { id = unit_id } } })
     wesnoth.set_variable("my_unit.variables", { {"donuts", { id = "bearclaw", text= "this is good"}}})   
     wesnoth.fire("unstore_unit", { variable="my_unit", find_vacant = "no"})
but then when I move on to assigning "cruller", "bearclaw" gets overwritten.
This code

Code: Select all

wesnoth.set_variable("my_unit.variables", { {"donuts", { id = "bearclaw", text= "this is good"}}})   
overwrites the whole [variables] tag from your unit.
doofus-01 wrote: Whenever I try something like wesnoth.get_variable("unit.variables.donuts[$index].id"), where "index" is a wml (not lua) variable, I'm told it's an "invalid WML array index"
Yes thats becasue wesnoth.get_variable doesn't do variable substitution. If you want to use a wml variable value inside set_variable you need to do it manually:

Code: Select all

wesnoth.get_variable("unit.variables.donuts[" .. wesnoth.get_variable("index") .. "].id")
ofc this is easier if you already ahve index as a lua variable since you can just use that instead of wesnoth.get_variable
doofus-01 wrote: Using table.insert(unit[1].__cfg[6][2], {{"donuts", {id = "bearclaw", text = "..."}}}) doesn't do anything, (leave off the [2] doesn't matter), I checked unit[1].__cfg[6] before and after with Wesnoth Lua pack's dbms() function (that's how I got the [6] index, I realize that may change and I shouldn't hard-code it).
Yes __cfg retruns a wml table that is a copy of that unit. just like changing the wml of a wml gained by [store_unit] does not change the original unit this doesn't neigher.
doofus-01 wrote: Does it have anything to do with helper.set_wml_var_metatable? That sounds promising, but I find the wiki section on that to be useless, and none of the add-ons I've got as examples seem to use it, really.
helper.set_wml_var_metatable is just a way save typing if you use a lot of wesnoth.set/get_variable. so for example if you have a wml variable named "index" and have 'V = H.set_wml_var_metatable {}' you can write 'local a = V.index' instead of 'local a = wesnoth.get_variable("index")'


Do you use that [donuts] variable from wml and from lua or just from lua?
If the [donuts] variable is never used by wml code, then another way to do it is just to store serialized lua tables in the units variables, thats he way i usually do it.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

Re: WML array into unit.variables

Post by doofus-01 »

gfgtdf wrote:If you want to use a wml variable value inside set_variable you need to do it manually:
Code: [ Select all ]
wesnoth.get_variable("unit.variables.donuts[" .. wesnoth.get_variable("index") .. "].id")
I forgot you could split & append things like that, that solved it.

But now I've got either a problem understanding table types, or there is a bug. What is wrong with this?

Code: Select all


uor = wesnoth.get_recall_units( { side = "1"})
...
wesnoth.put_recall_unit(uor[1])

I get this error.
bad argument #1 to 'put_recall_unit' (unit not found)
But if I look at uor[1] with debug_utils.dbms(), it looks like what I expected.

Code: Select all

uor[1] is of type userdata, value userdata: 0x9826708, length 9: 
...
with a metatable:

The metatable unit is of type string, value unit, length 4
...
And what I'm doing doesn't look that different from the example in http://wiki.wesnoth.org/LuaWML:Units#we ... ecall_unit

EDIT: Turns out I don't actually need to use it, just editing uor[1].variables.key, which is what I was trying to do, automatically affects the unit - no need to unstore or write out the "proxy unit". This is confusing.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

Re: [GUI] display-only listbox?

Post by doofus-01 »

Is there a way to get a display-only listbox? I want to draw something for information only, I don't know how many rows/elements ahead of time. A listbox is almost perfect, but then the player can highlight a panel (because you must use toggle_panel or toggle_button), and it looks like you should be able to select something. I tried scrollbar_panel, but whatever that is supposed to do, it doesn't seem to work the same way.

I don't know of any examples to look at, though I'm sure some exist. Does anyone know?

As a last resort, I suppose I could append strings and newlines into a long string, but I'd rather use something like a grid.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: [GUI] display-only listbox?

Post by gfgtdf »

What you could try to do is using a normal [grid] and creating its content dynamicly
untested code:

Code: Select all

function get_grit(entries)
-- entries is a list of strings
  local grid = {}
  for k, v in pairs(entries) do
    table.insert(grid, T.row { T.column { T.label { label = v } } })
  end
  return grid
end

wesnoth.show_dialog {
  T.helptip { id = "tooltip_large" }, -- mandatory field
  T.tooltip { id = "tooltip_large" }, -- mandatory field
  T.grid (get_grit {"Apples", "Bananas", "Strawberries"})
}
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
User avatar
doofus-01
Art Director
Posts: 4122
Joined: January 6th, 2008, 9:27 pm
Location: USA

Re: [GUI] display-only listbox?

Post by doofus-01 »

Thanks gfgtdf. I just went the text-only route for now, but I'll give that a try later.
BfW 1.12 supported, but active development only for BfW 1.13/1.14: Bad Moon Rising | Trinity | Archaic Era |
| Abandoned: Tales of the Setting Sun
GitHub link for these projects
Post Reply