PDA

View Full Version : Retrieving and Using Options



damned
February 24th, 2015, 01:02
Hi good peoples.

I have added an Option in an Extension. The option shows up in the Options window and the String Cycler works.
I can see the option being stored in the DB.


<options>
<public />
<CTAV type="string">on</CTAV>
<MC4C type="string">2C</MC4C>
<TBOX type="string">on</TBOX>
<TNAM type="string">tooltip</TNAM>
</options>

I need to retrieve the value and use it to set an element to be <invisible /> or not...
Could anyone get me started on this?

thanks!

Trenloe
February 24th, 2015, 05:31
Put some code against the control's onValueChanged() event. https://www.fantasygrounds.com/refdoc/stringcontrol.xcp#onValueChanged

The use getValue() to return the value.

See info in this post here: https://www.fantasygrounds.com/forums/showthread.php?20896-Help-With-button_stringcycler&p=173134&viewfull=1#post173134

The gotcha is that the default will return a value of "".

damned
February 24th, 2015, 06:23
Hey Trenloe - thanks for those examples.

I am retrieving the value ok (wasnt originally but had solved) but Im not sure how to use that value to set an
<invisible />
tag on some elements based on the value retrieved. The value is being retrieved by LUA but the <invisible /> tag is XML.

Looking at the onValueChanged where am I getting the value/name for line 2?


<script>
function onValueChanged()
window.onDamageChanged();
end
</script>

Thanks as always!

Trenloe
February 24th, 2015, 06:29
To set a control invisible use <control name>.setVisible(false) - info here: https://www.fantasygrounds.com/refdoc/windowcontrol.xcp#setVisible

You'll need to get a relative control hierarchy from your stringcycler control to the control/s you want to set visible/invisible.

Not sure what you mean by "Looking at the onValueChanged where am I getting the value/name for line 2?" getValue() in the stringcycler control <script> will return the value of the stringcycler control.

damned
February 24th, 2015, 06:29
I just added this code to my options LUA file;


function onInit()
DB.addHandler("options.*", "onUpdate", onOptionChanged);
end

function onInit()

OptionsManager.registerOption2("MC4C", false, "option_header_combattracker", "option_label_MC4C", "option_entry_cycler",
{ labels = "option_val_MC1C|option_val_MC2C|option_val_MC3C|op tion_val_MC4C", values = "1C|2C|3C|4C", baselabel = "option_val_off", baseval = "off", default = "1C" });

end


Im not sure if that is executing that way or not.

damned
February 24th, 2015, 06:37
Not sure what you mean by "Looking at the onValueChanged where am I getting the value/name for line 2?" getValue() in the stringcycler control <script> will return the value of the stringcycler control.

Doh!
I was referring to the post #173134 forgetting it wasnt in this thread because it was also by you!
Apologies.


To set a control invisible use <control name>.setVisible(false) - info here: https://www.fantasygrounds.com/refdoc/windowcontrol.xcp#setVisible

You'll need to get a relative control hierarchy from your stringcycler control to the control/s you want to set visible/invisible.

So write some LUA within the element that goes something like:

<script>
if sColumnCount == "MC2C" then
field.three.setVisible(0);
end
</script>

Trenloe
February 24th, 2015, 06:39
Ahhhhhhh, OK - it wasn't clear that this was something in the options manager subsystem.

You use the OptionsManager.isOption(<option name>, <option value>) or OptionsManager.getOption(<option name>) within your code to see what the option value is. For example, based off your code above, you can use OptionsManager.getOption("MC4C") to return the value of this option and then use this in a control's onInit() function to set the control visibility with setVisible.

You can also use an OptionsManager.registerCallback(<option name>, <update handler function name>) to register an update handler function that runs when the option value changes. Search in CoreRPG for OptionsManager.registerCallback - there are lots of examples.

damned
February 24th, 2015, 06:46
So I can add a script and oninit() to any XML control?

Trenloe
February 24th, 2015, 15:47
So I can add a script and oninit() to any XML control?
That will only cover you when the control is first created.

If the option is changed after the control is created you will need to create a registerCallback function for the option as well so that when the option is changed you have one set of code that changes all of the controls - this code should be in the same window as the controls so that it can access the controls to use setVisible on each control. you will also need to have code that unregisters the callback so that you don't get errors when windows no longer exist. Search for registerCallback in CoreRPG to see examples - this search should show the register code and the de register code.

If you don't do this registerCallback code then changing the option once a window has been opened will not show the result of that option until the window has been closed and re-opened, perhaps even requiring a restart of FG, depending where the control/s are.

damned
February 24th, 2015, 20:50
Arrrghh - Captcha is nuking my post. twice already.

In my ct_columns.lua file I have added the following:


function onInit()
local nodeWin = window.getDatabaseNode();
if nodeWin then
Debug.console("nodeWin:");
Debug.console(nodeWin);
local sColumnCount = nodeWin.getChild("..options.MC4C").getValue()
Debug.console("sColumnCount:");
Debug.console(sColumnCount);

This is successfully grabbing the database node combattracker and the option MC4C value of 1.

Runtime Notice: s'nodeWin:'
Runtime Notice: databasenode = { combattracker }
Runtime Notice: s'sColumnCount:'
Runtime Notice: s'1'

The following code successfully compares sColumnCount

if sColumnCount == "-" then Debug.console("None 0.");
label_three.setVisible(false);
field.three.setVisible(false);
label_two.setVisible(false);
field.two.setVisible(false);
label_one.setVisible(false);
field.one.setVisible(false);
end;

But fails to "find" any of the XML values such as label_three and field.three
Script Error: [string "ct/scripts/ct_columns.lua"]:28: attempt to index global 'field' (a nil value)

At the moment Im calling the ct_columns.lua file inside ct_host.xml by doing this:

<anchor_ctbox_host_header >
<!-- Damian Script to Count Columns from Options -->
<script file="ct/scripts/ct_columns.lua" />
</anchor_ctbox_host_header >

Its executing from there...

So -
1. Where/How should I be calling the script?
2. How do I reference my XML controls from the script?

I have not yet looked at this:

If you don't do this registerCallback code then changing the option once a window has been opened will not show the result of that option until the window has been closed and re-opened, perhaps even requiring a restart of FG, depending where the control/s are.

thanks.

Trenloe
February 24th, 2015, 21:07
1) Is MC4C an option registered using OptionsManager.registerOption2 like you showed on past #5? If so, just use the OptionsManager.getOption("MC4C") like I said in post #7 - use the OptionsManager public functions that are available to you. This makes it easier for you now and more supportable going forwards.

And, you should be calling the code from within the window onInit code - not the onInit code of anchor_ctbox_host_header, this is just an anchor control.

2) attempt to index global 'field' (a nil value) means that it can't find field. Look in your code, where is "field" being used? As I've mentioned before, if you are getting these error messages start putting debug code in the script to report exactly what you can access. Debug code to show window.getClass() is a good one to start with and then work from there. For example, window.getClass() might report combattracker_host - if so, look for <windowclass name="combattracker_host"> in your ruleset and work out how you'd get from there to the control/s you want to hide/show. Then use window.<path to the control> to get to the control.

damned
February 25th, 2015, 01:47
Ok - switched to OptionsManager.getOption("MC4C") and that works nicely - thanks.

Ok - I was running my script in the wrong WindowClass to get access to field_three.
Moved the script to the correct WindowClass but there is an existing script there and it seems to be only executing the first script there - is that correct?
Assuming that it is correct I started taking code from ct_columns.lua and putting into ct_entry.lua and OptonsManager works but again it cant find window...

local sWhereAmI = window.getClass();
Debug.console("sWhereAmI:");
Debug.console(sWhereAmI);


Runtime Notice: Reloading ruleset
Runtime Notice: s'sColumnCount:'
Runtime Notice: s'1'
Script Error: [string "ct/scripts/ct_entry.lua"]:30: attempt to index global 'window' (a nil value)

And I may as well ask the next question - am i using setVisible() correctly because it doesnt seem to work how I have done it.

if sColumnCount == "1" then Debug.console("One 1.");
label_three.setVisible(false);
field.three.setVisible(false);
label_two.setVisible(false);
field.two.setVisible(false);
label_one.setVisible(true);
field.one.setVisible(true);
end;
or

if sColumnCount == "1" then Debug.console("One 1.");
ct_entry.label_three.setVisible(false);
ct_entry.field.three.setVisible(false);
ct_entry.label_two.setVisible(false);
ct_entry.field.two.setVisible(false);
ct_entry.label_one.setVisible(true);
ct_entry.field.one.setVisible(true);
end;
Should be hiding 2 labels and 2 fields based on a return value of 1.



https://www.fg-con.com/wp-content/uploads/2015/02/fg-con-6-150-14.jpg (https://www.fg-con.com/events/)
FG Con 6 – April 17-19th 2015 - register at www.fg-con.com (https://www.fg-con.com/) for all the latest info.

damned
February 25th, 2015, 01:49
edit:
When I run this in a different windowclass it works so I believe the syntax is correct:

local sWhereAmI = window.getClass();
Debug.console("sWhereAmI:");
Debug.console(sWhereAmI);

Trenloe
February 25th, 2015, 02:27
ct_entry is the code that runs in the ct_entry class - this is each entry within the windowlist within the combat tracker, i.e. a PC or NPC. Don't run the code there as it will run for each entry in the CT, run it once in the combattracker_host windowclass.

damned
February 25th, 2015, 02:40
grnack!

What am I doing wrong?
I moved my script back up to combattracker_host but it still errors on window.
I took that code out and put it in ct_host.xml in <script> tags and it runs.
But I need to be able to refer to the value from OptionsManager.getOption("MC4C") and the window values in the same place so I moved the OptionsManager.getOption("MC4C") in between the <script> tags and it doesnt work there.

I cant see to get access to OptionsManager from within XML executing LUA and I cant access Window from within script executed LUA.

damned
February 25th, 2015, 03:14
urk.
Its not even that.
Ive done something and I cant work out what.
No matter where i run
local sWhereAmI = window.getClass();
I get attempt to inex global 'window' (a nil value) and I have tried in a LUA file called from combattracker_host and ct_entry and also between script tags in both combattracker_host and ct_entry.
Something is amiss in paradise...

Trenloe
February 25th, 2015, 03:15
OptionsManager global package calls should work in XML.

Trenloe
February 25th, 2015, 03:16
It was never paradise...

damned
February 25th, 2015, 03:44
OptionsManager global package calls should work in XML.

I hear you - but when I enclose it in script tags in the XML file I get errors - not just with my code - if I copy and paste a similar call from elsewhere in CoreRPG it does the same.


It was never paradise...

Sure - but no need to rub it in...
Im already feeling great!

Trenloe
February 25th, 2015, 03:47
Are you putting it in an onInit() function within the XML <script> section?

damned
February 25th, 2015, 04:21
Are you putting it in an onInit() function within the XML <script> section?

Gawd I make the stupidest mistakes often!.
So yes - OptionsManager.getOption("MC4C") is working again now with the onInit() back included.
Additionally I needed to move
local sWhereAmI = window.getClass();
to somewhere within the <sheetdata> tags and not just within the <windowclass>

Thank you, thank you.

Any pointers on the setVisible()?
No errors - no impact either.

damned
February 25th, 2015, 04:46
Some more progress.
If I execute a slightly modified version of the whole script in the actual element Im trying to hide it works.

<script>
function onInit()
local sColumnCount = OptionsManager.getOption("MC4C");
local sWhereAmI = window.getClass();
Debug.console("sWhereAmI (f3):");
Debug.console(sWhereAmI);
if sColumnCount == "-" then Debug.console("None 0.");
setVisible(false);
end;
if sColumnCount == "1" then Debug.console("One 1.");
setVisible(false);
end;
if sColumnCount == "12" then Debug.console("One Two 1 2.");
setVisible(false);
end;
if sColumnCount == "123" then Debug.console("One Two Three 1 2 3.");
setVisible(true);
end;
end;
</script>

I can add a modified version to each element and it appears to be working...

damned
February 25th, 2015, 06:00
Wow!

Thanks for your guidance.... and patience.... :(
I think that it is probably possible to do with 2 sets of code (one for labels in combattracker_host windowclass and one in ct_entry windowclass) but for now it works.
I can read the Options and show/hide elements based on the Option Value.

Is there a way to cause the various Combat Tracker onInit scripts to rerun after changing an Option. At the moment I have to restart the session to update the column view.

Looking at the CoreRPG Improved Character Sheet if an element has been initialised already option changes dont take effect until a restart.


https://www.fg-con.com/wp-content/uploads/2015/02/fg-con-6-150-13.jpg (https://www.fg-con.com/events/)
FG Con 6 – April 17-19th 2015 - register at www.fg-con.com (https://www.fg-con.com/) for all the latest info.

Trenloe
February 25th, 2015, 14:39
Is there a way to cause the various Combat Tracker onInit scripts to rerun after changing an Option. At the moment I have to restart the session to update the column view.Aa
See post #9

If you use OptionsManager.registerCallback you MUST also have an unregisterCallback command that removes the callback when the control closes (usually using the onClose() event). You must have this otherwise FG can crash if it tries to run a callback that no longer exists.

Trenloe
February 25th, 2015, 15:12
Here's an example:


<mylabel name="label_four" source="label.four">
<anchored to="label_init" width="38" height="20">
<top />
<right anchor="left" relation="relative" offset="-2" />
</anchored>
<tooltip textres="ct_label_label_description" />
<center />
<script>
function onInit()

OptionsManager.registerCallback("MC4C", StateChanged);

StateChanged();

end

function onClose()
OptionsManager.unregisterCallback("MC4C", StateChanged);
end

function StateChanged()
local sColumnCount = OptionsManager.getOption("MC4C");
if sColumnCount == "-" then Debug.console("None 0.");
setVisible(false);
elseif sColumnCount == "1" then Debug.console("One 1.");
setVisible(false);
elseif sColumnCount == "12" then Debug.console("One Two 1 2.");
setVisible(false);
elseif sColumnCount == "123" then Debug.console("One Two Three 1 2 3.");
setVisible(false);
elseif sColumnCount == "1234" then Debug.console("One Two Three Four 1 2 3 4.");
setVisible(true);
end;
end
</script>
</mylabel>