It is currently March 19th, 2024, 8:05 am

LUA GetOption() - How to preserve variable references?

Discuss the use of Lua in Script measures.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA
Contact:

LUA GetOption() - How to preserve variable references?

Post by raiguard »

I am using the GetOption() function with a meter object in my LUA script. The idea is to get the "Fill" key from a shape so I can create a generalized hover logic for my color picker buttons:
color picker hovers.gif
It works perfectly! However, I soon discovered that upon changing the color with my ColorPickerPlus skin (which is what clicking one of these buttons allows you to do), the new color wasn't being represented on the icon without a skin refresh.

After some digging, it turns out that the GetOption() meter function does not preserve variable references. So if I have a meter with Fill=Fill Color #colorCore1#, instead of retrieving that string, the function is retrieving Fill=Fill Color 107,238,98 (being the value of #colorCore1# at that given time).

Is there some method of retrieving a key while preserving the variable references, without resorting to straight-up reading the file with something akin to ReadIni()?

Here is an over-simplified example skin. The button is supposed to turn green when clicked, but since the variable reference is lost, it doesn't:
shape hover.gif
Hover.ini:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]
colorButton=255,50,50

[MeasureScript]
Measure=Script
ScriptFile=#@#Scripts\Hover.lua

[MeterHoverShape]
Meter=Shape
Shape=Rectangle 0,0,25,25,3 | StrokeWidth 0 | Extend Fill
Fill=Fill Color #colorButton#
MouseOverAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:GetKey('[#CURRENTSECTION]', 'Fill')],230"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:Gsub('[&MeasureScript:GetKey('[#CURRENTSECTION]', 'Fill')]',',230')]"][!UpdateMeter #CURRENTSECTION#][!Redraw]
LeftMouseUpAction=[!SetVariable colorButton "50,255,50"][!UpdateMeter #CURRENTSECTION#][!Redraw]
DynamicVariables=1
Hover.lua:

Code: Select all

function Initialize() end

function Update() end

function GetKey(name, key) return SKIN:GetMeter(name):GetOption(key) end

function Gsub(string, pattern, replacement) return string:gsub(pattern, replacement or '') end
rxtd
Posts: 100
Joined: April 30th, 2017, 11:51 am

Re: LUA GetOption() - How to preserve variable references?

Post by rxtd »

raiguard wrote: May 25th, 2019, 12:38 am Is there some method of retrieving a key while preserving the variable references
I believe there isn't. I've only found an API function for plugins that does it, which only works with plugin measures.
However, you can get around it by creating a separate option with same value, but with all formulas and variables in escaped form.

Also, for me modifying options this way looks like overengineereing. If I needed to do some sort of complex modification to the option I would add another option with variable name in it, and then either modify variable itself or reconstruct option value using this name.
Or maybe it's just me hating string parsing too much.
Last edited by rxtd on May 25th, 2019, 4:11 pm, edited 1 time in total.
User avatar
balala
Rainmeter Sage
Posts: 16091
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: LUA GetOption() - How to preserve variable references?

Post by balala »

Although this doesn't fix the problem, there are some missing characters in the code: in the parameters of the GetKey function (MouseOverAction and MouseLeaveAction options of the [MeterHoverShape] meter), the last # character of the #CURRENTSECTION# variables is missing. Adding them back, will at least make the variable to properly work:

Code: Select all

[MeterHoverShape]
...
MouseOverAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:GetKey('[#CURRENTSECTION#]', 'Fill')],230"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:Gsub('[&MeasureScript:GetKey('[#CURRENTSECTION#]', 'Fill')]',',230')]"][!UpdateMeter #CURRENTSECTION#][!Redraw]
Again, unfortunately this doesn't fix the problem.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA
Contact:

Re: LUA GetOption() - How to preserve variable references?

Post by raiguard »

balala wrote: May 25th, 2019, 3:01 pm Although this doesn't fix the problem, there are some missing characters in the code: in the parameters of the GetKey function (MouseOverAction and MouseLeaveAction options of the [MeterHoverShape] meter), the last # character of the #CURRENTSECTION# variables is missing. Adding them back, will at least make the variable to properly work:

Code: Select all

[MeterHoverShape]
...
MouseOverAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:GetKey('[#CURRENTSECTION#]', 'Fill')],230"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:Gsub('[&MeasureScript:GetKey('[#CURRENTSECTION#]', 'Fill')]',',230')]"][!UpdateMeter #CURRENTSECTION#][!Redraw]
Again, unfortunately this doesn't fix the problem.
Actually, I was using the nested variables syntax, which only uses one # at the beginning. Thanks anyway though!
User avatar
balala
Rainmeter Sage
Posts: 16091
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: LUA GetOption() - How to preserve variable references?

Post by balala »

raiguard wrote: May 25th, 2019, 4:32 pm Actually, I was using the nested variables syntax, which only uses one # at the beginning.
HUHUH...
Right! My fault. Please forgive my ignorance.
User avatar
balala
Rainmeter Sage
Posts: 16091
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: LUA GetOption() - How to preserve variable references?

Post by balala »

raiguard wrote: May 25th, 2019, 12:38 am Is there some method of retrieving a key while preserving the variable references, without resorting to straight-up reading the file with something akin to ReadIni()?
I think there is. The solution is the following one:

Code: Select all

[MeterHoverShape]
Meter=Shape
Shape=Rectangle 0,0,25,25,3 | StrokeWidth 0 | Extend Fill
Fill=Fill Color #colorButton#
MouseOverAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:GetKey('[#CURRENTSECTION]', 'Fill')],230"][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseLeaveAction=[!SetOption #CURRENTSECTION# Fill "[&MeasureScript:Gsub('[&MeasureScript:GetKey('[#CURRENTSECTION]', 'Fill')]',',230')]"][!UpdateMeter #CURRENTSECTION#][!Redraw]
LeftMouseUpAction=[!SetOption #CURRENTSECTION# Fill "Fill Color #*colorButton*#"][!SetVariable colorButton "50,255,50"][!UpdateMeter #CURRENTSECTION#][!Redraw]
DynamicVariables=1
As you can see, the magic is that you have to escape the colorButton variable when you click the meter. This is done through a !SetOption bang ([!SetOption #CURRENTSECTION# Fill "Fill Color #*colorButton*#"]) added to the LeftMouseUpAction bang, which once the meter clicked, sets its Fill option to #*colorButton*#. Now the script measure and through it the meter, will interact properly, setting the desired color.
A much simpler possibility would be to set from start the Fill option to Fill=Fill Color #*colorButton*#, but in this case at the beginning, the color of the meter isn't properly set. That1s why we need that !SetOption bang.

Additional tipp: when using InlineLua, the Script measure can be disabled. Add a Disabled=1 option to the [MeasureScript] measure.
rxtd
Posts: 100
Joined: April 30th, 2017, 11:51 am

Re: LUA GetOption() - How to preserve variable references?

Post by rxtd »

balala wrote: May 25th, 2019, 6:25 pm I think there is. The solution is the following one:
Not really a method of retrieving current option value without substituting variables.
One of many workarounds, but nothing to do with retrieving.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA
Contact:

Re: LUA GetOption() - How to preserve variable references?

Post by raiguard »

Here is a slightly more complicated example showing why I am doing it the way I am:
shape hover 2.gif
Hover.ini:

Code: Select all

[Rainmeter]
MiddleMouseUpAction=[!Refresh]
AccurateText=1

[Variables]
colorButton1=255,50,50
colorButton2=50,255,50
colorButton3=50,50,255

hoverAlpha=200

[StyleButtonIcon]
Shape=Rectangle 0,0,15,15,3 | StrokeWidth 0 | Extend Fill
DynamicVariables=1
X=5
Y=5R

[StyleButtonLabel]
FontFace=Segoe UI
FontSize=9
FontWeight=500
FontColor=220,220,220
Antialias=1
X=4R
Y=r
Padding=0,-1,0,0

[StyleButtonMouseRegion]
X=[&[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon:X]
Y=[&[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon:Y]
W=([&[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon:W] + [&[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label:W] + 2)
H=[&[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon:H]
DynamicVariables=1
MouseOverAction=[!SetOption [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon Fill "[&MeasureScript:GetKey('[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon','Fill')],#hoverAlpha#"][!SetOption [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label FontColor "[&MeasureScript:GetKey('[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label','FontColor')],#hoverAlpha#"][!UpdateMeter [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon][!UpdateMeter [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label][!Redraw]
MouseLeaveAction=[!SetOption [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon Fill "[&MeasureScript:Gsub('[&MeasureScript:GetKey('[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon','Fill')]', ',#hoverAlpha#')]"][!SetOption [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label FontColor "[&MeasureScript:Gsub('[&MeasureScript:GetKey('[&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label','FontColor')]', ',#hoverAlpha#')]"][!UpdateMeter [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon][!UpdateMeter [&MeasureScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label][!Redraw]

; Dummy Meters to prevent first-update log errors
[0Icon]
Meter=Image

[0Label]
Meter=Image

; ==================================================
; MEASURES

[MeasureScript]
Measure=Script
ScriptFile=#@#Scripts\Hover.lua

; ==================================================
; METERS

[MeterBackground]
Meter=Shape
Shape=Rectangle 0,0,80,65,3 | StrokeWidth 0 | Fill Color 25,25,25

; Button 1
[MeterButton1Icon]
Meter=Shape
MeterStyle=StyleButtonIcon
Fill=Fill Color #colorButton1#
Y=5

[MeterButton1Label]
Meter=String
MeterStyle=StyleButtonLabel
Text=Button 1

[MeterButton1MouseRegion]
Meter=Image
MeterStyle=StyleButtonMouseRegion
LeftMouseUpAction=[!SetVariable colorButton1 "255,255,255"][!Update]

; Button 2
[MeterButton2Icon]
Meter=Shape
MeterStyle=StyleButtonIcon
Fill=Fill Color #colorButton2#

[MeterButton2Label]
Meter=String
MeterStyle=StyleButtonLabel
Text=Button 2

[MeterButton2MouseRegion]
Meter=Image
MeterStyle=StyleButtonMouseRegion
LeftMouseUpAction=[!SetVariable colorButton2 "255,255,255"][!Update]

; Button 3
[MeterButton3Icon]
Meter=Shape
MeterStyle=StyleButtonIcon
Fill=Fill Color #colorButton3#

[MeterButton3Label]
Meter=String
MeterStyle=StyleButtonLabel
Text=Button 3

[MeterButton3MouseRegion]
Meter=Image
MeterStyle=StyleButtonMouseRegion
LeftMouseUpAction=[!SetVariable colorButton3 "255,255,255"][!Update]
Hover.lua:

Code: Select all

function GetKey(name, key) return SKIN:GetMeter(name):GetOption(key) end

function Gsub(string, pattern, replacement) return string:gsub(pattern, replacement or '') end
As you can see, my method allows me to, with just a few overcomplicated MeterStyles, quickly and efficiently create dozens of color picker buttons without repeating too much code. In my suite, which has over 50 of these buttons, and where several of the skins are many thousands of lines long, saving space in an INI file is very important.

I do have a workaround that would work: I could add another option to each button icon with the plaintext name of the variable. Then I could edit the MeterStyle to pull this value when changing the Fill option. This would work, but would require me to add an additional line to each icon meter, which would be inefficient.

This is why I am trying to find another solution. Thanks for the help thus far!
User avatar
balala
Rainmeter Sage
Posts: 16091
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: LUA GetOption() - How to preserve variable references?

Post by balala »

raiguard wrote: May 30th, 2019, 12:43 am This is why I am trying to find another solution.
And how the color of those shapes should have to change when they are clicked?
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA
Contact:

Re: LUA GetOption() - How to preserve variable references?

Post by raiguard »

balala wrote: May 30th, 2019, 6:32 am And how the color of those shapes should have to change when they are clicked?
In the actual implementation, I use my ColorPickerPlus skin to change the option. The problem was that since the reference was destroyed, I could not easily apply the new color to the meter without redefining the mouseactions for every meter, or refreshing the skin (which I'm trying to avoid doing as much as possible, due to the sheer size of the skin involved).

I went ahead and implemented my workaround until I can find a better solution. Here is a before and after I implemented the workaround, respectively:

Broken:
shapehover-broken.gif
Worked around:
shapehover-fixed.gif
My workaround was to add a new parameter to each icon called FillRef, which would contain the plaintext variable name. For example:

Code: Select all

Fill=Fill Color #colorRam#
FillRef=colorRam
Then I created an alternate version of the MeterStyle with these mouse actions:

Code: Select all

MouseOverAction=[!SetOption [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon Fill "Fill Color [#*[&MeasureSettingsScript:GetKey('[&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon','FillRef')]*],#*hoverAlpha*#"][!SetOption [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label FontColor "[&MeasureSettingsScript:GetKey('[&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label','FontColor')],#hoverAlpha#"][!UpdateMeter [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon][!UpdateMeter [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label][!Redraw]
MouseLeaveAction=[!SetOption [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon Fill "Fill Color [#*[&MeasureSettingsScript:GetKey('[&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon','FillRef')]*]"][!SetOption [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label FontColor "[&MeasureSettingsScript:Gsub('[&MeasureSettingsScript:GetKey('[&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label','FontColor')]', ',#hoverAlpha#')]"][!UpdateMeter [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Icon][!UpdateMeter [&MeasureSettingsScript:Gsub('[#CURRENTSECTION]','MouseRegion')]Label][!Redraw]
It's ugly, but it works. I'll keep thinking about a proper solution, but for now I can put this behind me...
Post Reply