[solved] GUI: dynamic return values
Moderator: Forum Moderators
-
- Posts: 1253
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
[solved] GUI: dynamic return values
I have a simple button, as part of a page definition, and I want to set the return value in preshow, something like:
I'm guessing this has something to do with return_value_id? I've been messing around trying things and can't figure it out. Every example I can find just has return_value_id = "ok".
devdocs has this to say about return_value_id, which makes no sense to me:
I suspect there's probably an alternative based on selected_item, but I'm trying to demonstrate how to use return_value(_id).
Also, most of what I try gets me "invalid (modifiable) property of widget". Are said properties documented/listed somewhere?
P.S. https://devdocs.wesnoth.org/group__GUIWidgetWML.html has every other widget listed as gui2::<widget>, except gui::button, which means button is the only one that doesn't show up in alphabetical order.
Code: Select all
wml.tag.button { id = "monster_pick" }
...
dialog.monsters_mp[i].monster_pick.label = "Pick me, I'm " .. monster.name
--dialog.monsters_mp[i].monster_pick.return_value = monster.name
devdocs has this to say about return_value_id, which makes no sense to me:
When I still want to use the id that doesn't exist?When the button doesn't have a standard id, but you still want to use the return value of that id, use return_value_id instead. This has a higher precedence as return_value.
I suspect there's probably an alternative based on selected_item, but I'm trying to demonstrate how to use return_value(_id).
Also, most of what I try gets me "invalid (modifiable) property of widget". Are said properties documented/listed somewhere?
P.S. https://devdocs.wesnoth.org/group__GUIWidgetWML.html has every other widget listed as gui2::<widget>, except gui::button, which means button is the only one that doesn't show up in alphabetical order.
Last edited by white_haired_uncle on January 5th, 2024, 2:09 am, edited 2 times in total.
Speak softly, and carry Doombringer.
Re: GUI: dynamic return values
This example is quite low quality and for older version, but maybe useful for concept. https://github.com/ProditorMagnus/Royal ... s/menu.lua
Specific parts I would point out are L225 with return value based on button user used to exit, but there is also L182 which provides additional value based on user selection.
Specific parts I would point out are L225 with return value based on button user used to exit, but there is also L182 which provides additional value based on user selection.
Maintainer of Ageless Era. Ravana's Multiplayer Works
Re: GUI: dynamic return values
return values can only be integers (and not settable in preshow),
And the list of modifiable properties is here https://wiki.wesnoth.org/LuaAPI/types/widget.
what you can do however is to create ac custom on_button_click callback that closes the dialog and sets some variable
And the list of modifiable properties is here https://wiki.wesnoth.org/LuaAPI/types/widget.
what you can do however is to create ac custom on_button_click callback that closes the dialog and sets some variable
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.
Re: GUI: dynamic return values
example code
Code: Select all
local dialog_wml = ...
local res = nil
local function preshow(dialog)
function dialog.some_button.on_button_click()
res = "boo"
dialog:close()
end
end
gui.show_dialog(dialog_wml, preshow)
return res
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.
-
- Posts: 1253
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
- Celtic_Minstrel
- Developer
- Posts: 2258
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: [solved] GUI: dynamic return values
A button's return value cannot be modified at runtime. If you need some sort of dynamic return value, use awhite_haired_uncle wrote: ↑January 4th, 2024, 9:55 pm I suspect there's probably an alternative based on selected_item, but I'm trying to demonstrate how to use return_value(_id).
post_show
function – the function can put your custom return value into a local variable, and you can just ignore the standard dialog return value. This is what gfgtdf's example does.If you're running in 1.17, you can use thewhite_haired_uncle wrote: ↑January 4th, 2024, 9:55 pm Also, most of what I try gets me "invalid (modifiable) property of widget". Are said properties documented/listed somewhere?
wesnoth.print_attributes
function (documented here) to determine what properties are valid and exist in any variable. There might be variables it doesn't work on, but it should certainly work on everything in the GUI2 system. For example, if you add the following:
Code: Select all
wesnoth.print_attributes(dialog.monsters_mp[i].monster_pick)
gui.show_lua_console()
pre_show
, it will pop up the Lua console with a list of all the non-deprecated attributes available on that particular widget. (Note: That probably includes all the functions in the gui.widget
module as well.)The list on the wiki is intended to be comprehensive, so if you find something that's not mentioned on either of the wiki pages (here and here) then you can feel free to add it to the wiki.
white_haired_uncle wrote: ↑January 4th, 2024, 9:55 pm P.S. https://devdocs.wesnoth.org/group__GUIWidgetWML.html has every other widget listed as gui2::<widget>, except gui::button, which means button is the only one that doesn't show up in alphabetical order.
gui::button
is just a legacy thing that's not related to GUI2 at all – it's the button used in the main game UI, such as for "End Turn", the top menubar, etc.-
- Posts: 1253
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
Re: [solved] GUI: dynamic return values
I built 1.17.24 to try this. Everything I try to inspect gives me:Celtic_Minstrel wrote: ↑January 5th, 2024, 8:19 am
If you're running in 1.17, you can use thewesnoth.print_attributes
function (documented here) to determine what properties are valid and exist in any variable. There might be variables it doesn't work on, but it should certainly work on everything in the GUI2 system. For example, if you add the following:in yourCode: Select all
wesnoth.print_attributes(dialog.monsters_mp[i].monster_pick) gui.show_lua_console()
pre_show
, it will pop up the Lua console with a list of all the non-deprecated attributes available on that particular widget. (Note: That probably includes all the functions in thegui.widget
module as well.)
Code: Select all
20240105 10:08:51 error scripting/lua: attempt to call a table value
stack traceback:
[C]: in ?
[C]: in field 'print_attributes'
..._Dark_Master_Project_Resources_beta/lua/gui_tutorial.lua:772: in upvalue 'preshow'
lua/core/gui.lua:143: in function <lua/core/gui.lua:140>
[C]: in upvalue 'old_show_dialog'
lua/core/gui.lua:138: in function 'gui.show_dialog'
..._Dark_Master_Project_Resources_beta/lua/gui_tutorial.lua:781: in local 'cmd'
lua/wml-utils.lua:145: in field 'handle_event_commands'
lua/wml-flow.lua:5: in function <lua/wml-flow.lua:4>
[C]: in ?
The error confuses me a bit, since the wiki says "For tables, by default this iterates the table..."
EDIT: Okay, not everything gets that error. Pass it a table, like wesnoth.(listboxItem) or wesnoth.print_attributes({"a","b","c"}) and it doesn't have much to say, but doesn't error. Maybe I just misunderstand the error.
According to
Code: Select all
wesnoth.type(dialog.monsters_mp[i].monster_pick),
While I want to understand this tool in general, I'm specifically hoping it will show me things like the height of a row/column/cell(?)/widget to help me understand the grow/placement/alignment stuff from another thread.
Code: Select all
function wesnoth.wml_actions.current_test_gui()
local monsters = {
{ image = "units/trolls/grunt.png", label = "A troll", name = _"Bob", race = "Trolls" },
{ image = "units/trolls/whelp.png", label = "A troll whelp", name = "Junior", race = "Trolls" },
{ image = "units/trolls/shaman.png", label = "A troll shaman", name = _"Alice", race = "Trolls" },
{ image = "units/monsters/cuttlefish.png", label = "A cuttlefish", race = "Seamonsters" },
{ image = "units/monsters/yeti.png", label = "A yeti", race = "Coolers" }
}
local listbox_id = "monsters"
local listboxItem = wml.tag.grid {
wml.tag.row {
wml.tag.column {
wml.tag.image { id = "monster_image" }
}
}
}
local listboxDefinition = wml.tag.listbox { id = listbox_id,
wml.tag.list_definition {
wml.tag.row {
wml.tag.column {
wml.tag.toggle_panel { listboxItem }
}
}
}
}
local multi_page = wml.tag.multi_page { id = "monsters_mp",
wml.tag.page_definition { id = "trolls_page",
wml.tag.row {
wml.tag.column {
wml.tag.label { id = "monster_name" }
},
},
wml.tag.row {
wml.tag.column {
wml.tag.image { id = "monster_image" }
},
},
wml.tag.row {
wml.tag.column {
wml.tag.button { id = "monster_pick",label="pick me" }
}
},
wml.tag.row {
wml.tag.column {
wml.tag.label { id = "monster_label" }
}
}
},
wml.tag.page_definition { id = "nottrolls_page",
wml.tag.row {
wml.tag.column {
wml.tag.image { id = "monster_image" }
},
},
wml.tag.row {
wml.tag.column {
wml.tag.label { id = "monster_label" }
}
},
}
}
local dialogDefinition = {
wml.tag.tooltip { id = "tooltip_large" },
wml.tag.helptip { id = "helptip_large" },
wml.tag.grid {
wml.tag.row { -- A header
wml.tag.column {
border = "bottom",
border_size = 10,
wml.tag.label {
use_markup = true,
label = "<span size='large'>" .. _"Here there be " ..
"<span color='yellow'>" ..
_"MONSTERS!" .. "</span></span>"
}
}
},
wml.tag.row { -- The body of our GUI
wml.tag.column {
wml.tag.grid {
wml.tag.row {
wml.tag.column {
listboxDefinition
},
wml.tag.column {
wml.tag.spacer {
width = 30
}
},
wml.tag.column {
multi_page
},
}
}
}
},
wml.tag.row {
wml.tag.column { -- An "OK" button
wml.tag.button { id = "ok",
label = _"OK"
},
}
}
}
}
local function preshow(dialog) -- Prepare the GUI before display
local listbox = dialog[listbox_id]
for i, monster in ipairs(monsters) do
listbox[i].monster_image.label = monster.image
if monster.race == "Trolls" then
dialog.monsters_mp:add_item_of_type("trolls_page")
dialog.monsters_mp[i].monster_name.label = monster.name
wesnoth.print_attributes(dialog.monsters_mp[i].monster_pick)
gui.show_lua_console()
else
dialog.monsters_mp:add_item_of_type("nottrolls_page")
end
dialog.monsters_mp[i].monster_image.label = monster.image
dialog.monsters_mp[i].monster_label.label = monster.label
end
local function switch_page()
dialog.monsters_mp.selected_index = listbox.selected_index
end
listbox.on_modified = switch_page
end
gui.show_dialog(dialogDefinition,preshow)
end
Speak softly, and carry Doombringer.
- Celtic_Minstrel
- Developer
- Posts: 2258
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: [solved] GUI: dynamic return values
In the second case I believe you should see a line with "1 2 3" printed in the console, is that correct? Or it may print nothing if I set it to skip numeric keys. A better basic test case would bewhite_haired_uncle wrote: ↑January 5th, 2024, 3:31 pm EDIT: Okay, not everything gets that error. Pass it a table, like wesnoth.(listboxItem) or wesnoth.print_attributes({"a","b","c"}) and it doesn't have much to say, but doesn't error. Maybe I just misunderstand the error.
wesnoth.print_attributes({a=1,b=2,c=3})
which should print out "a b c".I'm not sure what to think of your error. What's happening is probably that
print_attributes
is trying to call a function from the widget or its metatable that it expects will return a list of valid attributes (or some other internal mechanism), but the function turns out to be a table instead. In short, it seems like a bug inprint_attributes
. I'll see if I can reproduce it myself.- Celtic_Minstrel
- Developer
- Posts: 2258
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: [solved] GUI: dynamic return values
I found the issue. Due to the last-minute change of the function name from "dir" to "wesnoth.print_attributes", grabbing names from a widget object broke. I've pushed a fix to master. Thank you for finding this issue.
Also, as a side note, do you have a reason to be defining your dialog directly in the Lua instead of in a separate WML file, like the example on the wiki?
Also, as a side note, do you have a reason to be defining your dialog directly in the Lua instead of in a separate WML file, like the example on the wiki?
-
- Posts: 1253
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
Re: [solved] GUI: dynamic return values
I didn't really have any expectations, I just wanted to see if passing it a simple table (I tried {} first) would throw an error. Using your better test case I do get "a b c". It also handled listboxItem okay, but hung for a few minutes and then cored when I tried "dialog". Again, no expectations, I was just curious (screwing around).Celtic_Minstrel wrote: ↑January 6th, 2024, 3:22 pmIn the second case I believe you should see a line with "1 2 3" printed in the console, is that correct? Or it may print nothing if I set it to skip numeric keys. A better basic test case would bewhite_haired_uncle wrote: ↑January 5th, 2024, 3:31 pm EDIT: Okay, not everything gets that error. Pass it a table, like wesnoth.(listboxItem) or wesnoth.print_attributes({"a","b","c"}) and it doesn't have much to say, but doesn't error. Maybe I just misunderstand the error.wesnoth.print_attributes({a=1,b=2,c=3})
which should print out "a b c".
This is what I get for a button, which isn't what I expected:
Code: Select all
add_item ƒ add_item_of_type ƒ close ƒ
enabled ! find ƒ focus ƒ
label ! marked_up_text ! on_button_click !
on_left_click ! on_modified ! remove_items_at ƒ
set_callback ƒ set_canvas ƒ tooltip !
type use_markup ! visible !
Code: Select all
20240106 19:15:17 error scripting/lua: invalid property of 'N4gui26buttonE' widget :on_button_click
20240106 19:15:17 error scripting/lua: invalid property of 'N4gui26buttonE' widget :on_left_click
I don't know if any of the above makes any sense, or if I simply don't understand the tool. But that's what I saw.
I just find lua a lot easier to read/write, and I don't like to switch back and forth. I will admit, I did experiment with LISP a good bit in my college days, I suppose that may have had lasting effects.Also, as a side note, do you have a reason to be defining your dialog directly in the Lua instead of in a separate WML file, like the example on the wiki?
Speak softly, and carry Doombringer.
- Celtic_Minstrel
- Developer
- Posts: 2258
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: [solved] GUI: dynamic return values
In what way does it differ from what you expected?white_haired_uncle wrote: ↑January 7th, 2024, 12:41 am This is what I get for a button, which isn't what I expected:
Those errors are a side-effect of how the code determines the type of each property. It's because attempting to read an nonexistent or write-only property on a widget raises that error, but the only way to determine the type of a property is to read it and check the type.
It kind of sounds like you thought the ! meant the property was unset, but if you read the documentation, it clearly states that it means the property is likely write-only.white_haired_uncle wrote: ↑January 7th, 2024, 12:41 am I do have a label set for that widget, if it matters. And I set up an on_button_click to see if that changed anything, but it didn't. If I read the above correctly, it looks like add_item_of_type is an attribute that can be set on this object, which seems odd since it's a button, I wondered if I'm seeing the valid attributes of the button's (grand)parent (a multi_page).
I don't know if any of the above makes any sense, or if I simply don't understand the tool. But that's what I saw.
I see. Since you were writing a guide on the wiki, it might be a good idea to at least try the alternate file method so you can add that to the guide, though someone else could always do it later.white_haired_uncle wrote: ↑January 7th, 2024, 12:41 am I just find lua a lot easier to read/write, and I don't like to switch back and forth. I will admit, I did experiment with LISP a good bit in my college days, I suppose that may have had lasting effects.
-
- Posts: 1253
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
Re: [solved] GUI: dynamic return values
For a button, I would expect to see that on_button_click is a function. I only added a function to see if that made a difference. I would not expect to see add_item_of_type listed as a function, does it make any sense to say my_button:add_item_of_type("foo")?
The wiki says "! if there was an error attempting to determine the type (which includes write-only attributes)". I can't think of anything I would refer to as a write-only attribute, besides a function, so along with the terminal error I assumed there was a problem getting the type of on_button_click, for example.
Right now, I mention that you can use WML, and some would prefer it, but that I am going to use lua. I'm considering adding something like a side by side example of both for a simple gui for comparison.
The wiki says "! if there was an error attempting to determine the type (which includes write-only attributes)". I can't think of anything I would refer to as a write-only attribute, besides a function, so along with the terminal error I assumed there was a problem getting the type of on_button_click, for example.
Right now, I mention that you can use WML, and some would prefer it, but that I am going to use lua. I'm considering adding something like a side by side example of both for a simple gui for comparison.
Speak softly, and carry Doombringer.
Re: [solved] GUI: dynamic return values
In most of these cases there is no deeper reason why these are read only, it's just that no one has implemented the (c++) code to read the attribute (yet?). Unlike "pure" lua objects, these attributes aren't stored in the lua data structures themself, but in the c++ data structures so to support reading writing them we need to add a separate code to make them available to lua which sometimes just isn't there,
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.
- Celtic_Minstrel
- Developer
- Posts: 2258
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: [solved] GUI: dynamic return values
It's not a function, exactly. It's a callback. It shows as ! because you can set it but not query it. You can't manually call the callback, it only exists for the engine to call it at an appropriate time.white_haired_uncle wrote: ↑January 7th, 2024, 3:06 am For a button, I would expect to see that on_button_click is a function. I only added a function to see if that made a difference.
I understand your thought here, but in fact it's entirely valid to write that, though it'll raise an "unsupported widget" error. The reason it's valid is because that function is defined in thewhite_haired_uncle wrote: ↑January 7th, 2024, 3:06 am I would not expect to see add_item_of_type listed as a function, does it make any sense to say my_button:add_item_of_type("foo")?
gui.widget
module, which is treated as if it were the "base class" for all widgets. Thus, all functions in that module can be called on a widget as you demonstrated, though not all of them make sense to be called on any type of widget.Those errors you saw in the terminal are because the attributes are write-only. Thewhite_haired_uncle wrote: ↑January 7th, 2024, 3:06 am The wiki says "! if there was an error attempting to determine the type (which includes write-only attributes)". I can't think of anything I would refer to as a write-only attribute, besides a function, so along with the terminal error I assumed there was a problem getting the type of on_button_click, for example.
print_attributes
function attempted to read those attributes to determine the type, which raised those errors.You're right that many of them don't make sense to be write-only. That's an area where there's still room for improvement in the API. For me, the only ones in your button example that make sense to be write-only are the three callbacks, plus
marked_up_text
. The reason for the latter is because assigning to marked_up_text
is a shorthand that sets label
to the assigned value while also setting use_markup
to true.
Last edited by Celtic_Minstrel on January 8th, 2024, 3:54 am, edited 1 time in total.
Re: [solved] GUI: dynamic return values
For guide purpose it can be converted with wml.tostring.Celtic_Minstrel wrote: ↑January 7th, 2024, 2:11 am I see. Since you were writing a guide on the wiki, it might be a good idea to at least try the alternate file method so you can add that to the guide, though someone else could always do it later.
Maintainer of Ageless Era. Ravana's Multiplayer Works