It is currently May 19th, 2022, 3:42 pm

[BUG?] Double variable nesting and bang variables

Report bugs with the Rainmeter application and suggest features.
User avatar
Yincognito
Rainmeter Sage
Posts: 4694
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

[BUG?] Double variable nesting and bang variables

Post by Yincognito »

Skin:

Code: Select all

[Variables]
Ex=2
LC=[!SetVariable Ex (3-[#*Ex*])][!UpdateMeasure *][!UpdateMeter *][!Redraw][!CommandMeasure AT "Stop 1"][!CommandMeasure AT "Stop 2"][!CommandMeasure AT "Execute [#*Ex*]"]

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255

---Measures---

[AT]
Measure=Plugin
Plugin=ActionTimer
ActionList1=LogEx1 | Wait 10
LogEx1=[!Log "LogEx1: [#Ex]"][!UpdateMeasure *][!UpdateMeter *][!Redraw]
ActionList2=LogEx2 | Wait 10
LogEx2=[!Log "LogEx2: [#Ex]"][!UpdateMeasure *][!UpdateMeter *][!Redraw]
UpdateDivider=-1
DynamicVariables=1

---Meters---

[ATTest]
Meter=String
FontFace=Consolas
FontColor=255,255,255,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
Text="AT Test"
UpdateDivider=-1
LeftMouseUpAction=[#LC]
DynamicVariables=1
Expected result:
- the log should alternate / toggle between printing LogEx1 = 1 and LogEx2 = 2 on left click
Actual result:
- the [#Ex] variable only updates starting with the 2nd click in the LC bang variable, so the log alternates / toggles between printing LogEx2 = 1 and LogEx1 = 2, in effect executing the opposite actions in [AT]
Notes:
- if I make [!SetVariable Ex (3-#*Ex*#)] the LC bang variable, the log yields an error that "#Ex# is unknown in the formula", although it is properly declared and all, basically forcing me to use the nested variable syntax there, although it's not that critical in that place
- if I make LeftMouseUpAction=#LC# in [ATTest], everything works properly in terms of printed results, except the strange behavior related to the previous note

-----------

Unrelated to this, but since it happens in the same code I have to mention it, as it drives me crazy: please, please, please, add an option to the Image (or Image related) meters to freaking ignore the errors related to missing images. You can default it to not ignore them, but just give the option to the user to control logging those errors if he wants to. I said it before, and I say it again: there are times when missing image files actually have a purpose in a skin (like in a dock system where you dynamically reuse a 5 image "submenu" to avoid copy pasting dozens of additional meters and each submenu has a different number of "entries", like 2, 0, 3, 5, 1 or something like this; such a system throws errors for images belonging to submenu entries which are already invalid as per the submenu entries count and such) and nobody needs his log window spamming these errors - it makes finding real log messages a very difficult and annoying task:
MissingImages.jpg
Such similar options already exist in other places (mostly measures, not meters, apparently) in Rainmeter, like LogSubstringErrors in WebParser, IgnoreWarnings in ActionTimer, etc. It doesn't affect backward compatibility, it has no drawback, only positives.
You do not have the required permissions to view the files attached to this post.
User avatar
Brian
Developer
Posts: 2414
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: [BUG?] Double variable nesting and bang variables

Post by Brian »

We had another issue like this a little while ago.
https://forum.rainmeter.net/viewtopic.php?t=37693#p191846

Short answer: Everytime a variable is parsed and encounters an "escape" sequence, the variable is not resolved - however the escape sequence is removed (the asterisks) under the assumption that the "next" parse is where you want to use the "real" value of the variable.

In your case, there are 2 solutions.
  1. Double escape the variable(s). In your case: LC=[!SetVariable Ex (3-[#**Ex**])] ... [!CommandMeasure AT "Execute [#**Ex**]"]
  2. Use a regular variable in your action. Example: LeftMouseUpAction=#LC#

At the end of the day, it's impossible to "know" where the user or skin author really "wants" the variable to be resolved, so there really is no "fix" to this. So in this specific case, one of the 2 workarounds above is probably the only way to accomplish this "double" variable replacement.



As far as the image meter error message....I am not sure there is a real need. I understand the frustration of the same message being "spammed" at times, but honestly I don't buy the "it can be on purpose" argument. That just seems like bad skin design. Obviously, the same message being sent over and over is something we can work on, but I don't think turning off specific messages is the way to go. Like you mentioned, we did add a few options to ignore some messages, but those were mostly informational messages and did not impact any of the visuals to the skin (at least in most cases).

BTW - finding "real" messages in the log is super easy. Log to file then Show log file (I usually turn on "Debug mode" as well).

-Brian
User avatar
Yincognito
Rainmeter Sage
Posts: 4694
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?] Double variable nesting and bang variables

Post by Yincognito »

Brian wrote: March 21st, 2022, 8:10 amIn your case, there are 2 solutions.
  1. Double escape the variable(s). In your case: LC=[!SetVariable Ex (3-[#**Ex**])] ... [!CommandMeasure AT "Execute [#**Ex**]"]
  2. Use a regular variable in your action. Example: LeftMouseUpAction=#LC#
Many thanks, the multiple (triple, in my case) escaping is perfect for my code, since I need to use nested syntax for the #LC# equivalent in my real code below (see the #Execute#, [#[#CURRENTSECTION]Set] and [#[#CURRENTSECTION]Run] variables). :rosegift:
Brian wrote: March 21st, 2022, 8:10 amAs far as the image meter error message....I am not sure there is a real need. I understand the frustration of the same message being "spammed" at times, but honestly I don't buy the "it can be on purpose" argument. That just seems like bad skin design. Obviously, the same message being sent over and over is something we can work on, but I don't think turning off specific messages is the way to go. Like you mentioned, we did add a few options to ignore some messages, but those were mostly informational messages and did not impact any of the visuals to the skin (at least in most cases).

BTW - finding "real" messages in the log is super easy. Log to file then Show log file (I usually turn on "Debug mode" as well).
Well, regular skin designers won't dynamically reuse a "layout pattern" of maximum number of elements like I do, they prefer to copy paste thousands of lines with hardcoded indexes, but I don't think you can call an advanced technique "bad design" just because it isn't used by the majority of folks. This is my skin as it is now, ironically it's inspired by one of yours from when you released the ActionTimer plugin:
Dock_1.0.0.rmskin
Disregard the 2 bugs that still exist in the implementation, and just take a look at how I reuse the [Item...] meters to have "submenus" of up to (but NOT exactly!) 5 icons for each of the [Dock...] meters, just by changing the X and H values based on the particularities of a "dock" identified by [#DockIndex] - don't worry, it's a little skin, it won't take much time.

If you call that bad design just because I avoided creating a hardcoded number of "items" for each of those "docks" to make it 2000 lines of code instead of just 200 or because I similarly reused just 2 ActionTimer measures instead of having dozens and dozens of them for each single "dock" or "item", then I'm the Pope from Rome, really. I just can't understand why adding such a little option to "give control to the user" as you say by avoiding acknowledged and accepted errors about missing images since not all "docks" have the same (or exactly the maximum, aka 5) number of items would be such a big problem. If I was (hypothetically, of course) spamming this topic over and over on the forum even though you acknowledged and already took a decision to disregard it (like a skin designer using such methods would when it comes to missing images), then maybe you'd understand how that feels. Also, bear in mind that every meter already has UpdateDivider=-1 on it, and it still floods the log like in Noah times, LOL - you can imagine if I didn't add a negative update divider, how would that look and feel...

I'm terribly dissapointed by this part, I have to say - especially since you can't even workaround this, since hiding meters won't avoid the errors and one can't disable meters. :(
You do not have the required permissions to view the files attached to this post.
User avatar
Active Colors
Moderator
Posts: 1120
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Re: [BUG?] Double variable nesting and bang variables

Post by Active Colors »

Yincognito,
can you explain what is your specific condition when Image meter is trying to load an unexisting image?
User avatar
Yincognito
Rainmeter Sage
Posts: 4694
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?] Double variable nesting and bang variables

Post by Yincognito »

Active Colors wrote: March 21st, 2022, 12:08 pm Yincognito,
can you explain what is your specific condition when Image meter is trying to load an unexisting image?
Well, the code is right above. There is no condition per se (since you can't test whether an image exists from native Rainmeter). It just loads an image based on current section name and a few other things, really. Like:

Code: Select all

[sDockIcon]
Group=IconGroup | DockIconGroup
Container=DockContainer
Hidden=0
X=(#Indent#)R
Y=(0)r
ImageName=#CURRENTSECTION#.png

[sItemIcon]
Group=IconGroup | ItemIconGroup
Container=ItemContainer
Hidden=0
X=(0)r
Y=(#Indent#)R
ImageName=DockIcon#DockIndex##CURRENTSECTION#.png
These are the styles I use for "docks" (aka menu images) and "items" (aka submenu images). Like I said, hiding images doesnt stop the error spamming at all, so the whole argument that it somehow impacts the visuals in the skin is really thin when you're intentionally and actively hiding them. If there was a workaround for it, I would not care much, but there isn't, or at least I can't see it. Anyway, at least it's only log spamming, I'll just don't use the log anymore and that's it.
User avatar
Active Colors
Moderator
Posts: 1120
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Re: [BUG?] Double variable nesting and bang variables

Post by Active Colors »

Yincognito wrote: March 21st, 2022, 2:02 pm Well, the code is right above. There is no condition per se (since you can't test whether an image exists from native Rainmeter). It just loads an image based on current section name and a few other things, really. Like:

Code: Select all

[sDockIcon]
Group=IconGroup | DockIconGroup
Container=DockContainer
Hidden=0
X=(#Indent#)R
Y=(0)r
ImageName=#CURRENTSECTION#.png

[sItemIcon]
Group=IconGroup | ItemIconGroup
Container=ItemContainer
Hidden=0
X=(0)r
Y=(#Indent#)R
ImageName=DockIcon#DockIndex##CURRENTSECTION#.png
These are the styles I use for "docks" (aka menu images) and "items" (aka submenu images). Like I said, hiding images doesnt stop the error spamming at all, so the whole argument that it somehow impacts the visuals in the skin is really thin when you're intentionally and actively hiding them. If there was a workaround for it, I would not care much, but there isn't, or at least I can't see it. Anyway, at least it's only log spamming, I'll just don't use the log anymore and that's it.
If there are no images, can you hide those meters based on an if-condition formula?
Hidden=If [[#CURRENTSECTION]:W] > 0 then Hidden=0 otherwise Hidden=1
User avatar
Yincognito
Rainmeter Sage
Posts: 4694
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?] Double variable nesting and bang variables

Post by Yincognito »

Active Colors wrote: March 21st, 2022, 3:33 pm If there are no images, can you hide those meters based on an if-condition formula?
Hidden=If [[#CURRENTSECTION]:W] > 0 then Hidden=0 otherwise Hidden=1
Sorry, my mistake, I should have posted the whole code instead of attaching the RMSKIN for clarity, but didn't because of the bugs at that time and to ease testing if one doesn't have the images (or didn't name them properly). However, since in the meantime I corrected the bugs, here is how the code looks:

Code: Select all

[Variables]
DockSet=[!CommandMeasure Move "Stop 1"][!CommandMeasure Move "Stop 2"][!SetVariable Offset ([#***DockIndex***]=[#**DockIndex**]?[#***Offset***]:0)][!CommandMeasure Move "Execute [#***Execute***]"]
DockRun=[!CommandMeasure Move "Stop 1"][!CommandMeasure Move "Stop 2"][!SetVariable Execute (3-[#***Execute***])][!CommandMeasure Move "Execute [#***Execute***]"]
ScaleIcon=([#*Scale*]);0;0;([#*Scale*]);((1-[#*Scale*])*([[#*MeterName*]:X]+[[#*MeterName*]:W]/2));((1-[#*Scale*])*([[#*MeterName*]:Y]+[[#*MeterName*]:H]/2))
Scale=1
Value=0.05
DockBackColor=0,0,0,128
ItemBackColor=0,0,0,128
NoTintColor=255,255,255,255
TintedColor=128,128,128,255
Indent=8
IconSize=48
MeterName=
Offset=0
Execute=2
DockIndex=1
DockCount=5
ItemCount1=2
ItemCount2=0
ItemCount3=1
ItemCount4=3
ItemCount5=1
DockIcon1Set=[!SetVariable DockIndex 1][#DockSet]
DockIcon2Set=[!SetVariable DockIndex 2][#DockSet]
DockIcon3Set=[!SetVariable DockIndex 3][#DockSet]
DockIcon4Set=[!SetVariable DockIndex 4][#DockSet]
DockIcon5Set=[!SetVariable DockIndex 5][#DockSet]
DockIcon1Run=[#DockRun]
DockIcon2Run=[#DockRun]
DockIcon3Run=[#DockRun]
DockIcon4Run=[#DockRun]
DockIcon5Run=[#DockRun]
ItemIcon1Run=[#*DockIcon[#*DockIndex*]ItemIcon1App*]
ItemIcon2Run=[#*DockIcon[#*DockIndex*]ItemIcon2App*]
ItemIcon3Run=[#*DockIcon[#*DockIndex*]ItemIcon3App*]
ItemIcon4Run=[#*DockIcon[#*DockIndex*]ItemIcon4App*]
ItemIcon5Run=[#*DockIcon[#*DockIndex*]ItemIcon5App*]
DockIcon1ItemIcon1App=["C:\Program Files\Google\Chrome\Application\chrome.exe"]
DockIcon1ItemIcon2App=[msedge.exe]
DockIcon3ItemIcon1App=[notepad.exe]
DockIcon4ItemIcon1App=[wmplayer.exe]
DockIcon4ItemIcon2App=[mspaint.exe]
DockIcon4ItemIcon3App=[taskmgr.exe]
DockIcon5ItemIcon1App=["C:\Program Files\Rainmeter\Rainmeter.exe" !Manage]

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
MouseLeaveAction=[!CommandMeasure Move "Stop 1"][!CommandMeasure Move "Stop 2"][!SetVariable Execute 2][!CommandMeasure Move "Execute [#Execute]"]

---Measures---

[Size]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat SizeUp,10,5
SizeUp=[!SetVariable Scale (Clamp([#Scale]+[#Value],1.25-[#Value]*5,1.25))][!SetOption [#MeterName] TransformationMatrix "#ScaleIcon#"][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
ActionList2=Repeat SizeDn,10,5
SizeDn=[!SetVariable Scale (Clamp([#Scale]-[#Value],1.25-[#Value]*5,1.25))][!SetOption [#MeterName] TransformationMatrix "#ScaleIcon#"][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
UpdateDivider=-1
DynamicVariables=1

[Move]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat MoveUp,100,8
MoveUp=[!SetVariable Offset (Clamp([#Offset]+[&ItemContainer:H]/8,0,[&ItemContainer:H]))][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
ActionList2=Repeat MoveDn,100,8
MoveDn=[!SetVariable Offset (Clamp([#Offset]-[&ItemContainer:H]/8,0,[&ItemContainer:H]))][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
UpdateDivider=-1
DynamicVariables=1

---Styles---

[sIcon]
W=(#IconSize#)
H=(#IconSize#)
ImagePath=#@#Images\
PreserveAspectRatio=1
ImageTint=#TintedColor#
UpdateDivider=-1
MouseOverAction=[!SetOption #CURRENTSECTION# ImageTint "#NoTintColor#"][!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup IconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw][!CommandMeasure Size "Execute 1"][#[#CURRENTSECTION]Set]
MouseLeaveAction=[!SetOption #CURRENTSECTION# ImageTint "#TintedColor#"][!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup IconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw][!CommandMeasure Size "Execute 2"]
LeftMouseDownAction=[!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1.25][!SetVariable Value 0.10][!CommandMeasure Size "Execute 2"]
LeftMouseUpAction=[!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 0.75][!SetVariable Value 0.10][!CommandMeasure Size "Execute 1"][#[#CURRENTSECTION]Run]
DynamicVariables=1

[sDockIcon]
Group=IconGroup | DockIconGroup
Container=DockContainer
Hidden=0
X=(#Indent#)R
Y=(0)r
ImageName=#CURRENTSECTION#.png

[sItemIcon]
Group=IconGroup | ItemIconGroup
Container=ItemContainer
Hidden=0
X=(0)r
Y=(#Indent#)R
ImageName=DockIcon#DockIndex##CURRENTSECTION#.png

---Meters---

[DockContainer]
Group=DockIconGroup
Hidden=0
Meter=Image
X=(0)
Y=(0)R
W=((#IconSize#+#Indent#)*#DockCount#+#Indent#)
H=((#IconSize#+#Indent#)*1+#Indent#)
SolidColor=0,0,0,255
UpdateDivider=-1
MouseLeaveAction=[!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup DockIconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw]
DynamicVariables=1

[DockBackground]
Group=DockIconGroup
Container=DockContainer
Hidden=0
Meter=Image
X=(0)r
Y=(0)r
W=([DockContainer:W])
H=([DockContainer:H])
SolidColor=#DockBackColor#
UpdateDivider=-1
DynamicVariables=1

[DockIcon1]
Meter=Image
MeterStyle=sIcon | sDockIcon
X=(#Indent#)r
Y=(#Indent#)r

[DockIcon2]
Meter=Image
MeterStyle=sIcon | sDockIcon

[DockIcon3]
Meter=Image
MeterStyle=sIcon | sDockIcon

[DockIcon4]
Meter=Image
MeterStyle=sIcon | sDockIcon

[DockIcon5]
Meter=Image
MeterStyle=sIcon | sDockIcon

[ItemContainer]
Group=ItemIconGroup
Hidden=0
Meter=Image
X=((#IconSize#+#Indent#)*([#DockIndex]-1))
Y=(0)R
W=((#IconSize#+#Indent#)*1+#Indent#)
H=((#IconSize#+#Indent#)*[#ItemCount[#DockIndex]]+#Indent#*Sgn([#ItemCount[#DockIndex]]))
SolidColor=0,0,0,255
UpdateDivider=-1
MouseLeaveAction=[!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup ItemIconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw]
DynamicVariables=1

[ItemBackground]
Group=ItemIconGroup
Container=ItemContainer
Hidden=0
Meter=Image
X=(0)r
Y=([#Offset]-[ItemContainer:H])r
W=([ItemContainer:W])
H=([ItemContainer:H])
SolidColor=#ItemBackColor#
UpdateDivider=-1
DynamicVariables=1

[ItemIcon1]
Meter=Image
MeterStyle=sIcon | sItemIcon
X=(#Indent#)r
Y=(#Indent#)r

[ItemIcon2]
Meter=Image
MeterStyle=sIcon | sItemIcon

[ItemIcon3]
Meter=Image
MeterStyle=sIcon | sItemIcon

[ItemIcon4]
Meter=Image
MeterStyle=sIcon | sItemIcon

[ItemIcon5]
Meter=Image
MeterStyle=sIcon | sItemIcon
and the zipped @Resources folder with the images:
@Resources.zip
Dock.jpg
While I could use an IfCondition like you said, it wouldn't help much since errors appear even if the (missing) images are hidden. Also, can't really use the :W parameter since I control the icons / images size via the IconSize variable above, in order to freely adjust how big the images are AND calculate the dimensions of the "bars" / "backgrounds" I'm placing those images on with the help of the -Count variables.

Thankfully, now with the bugs fixed, I can focus more on finding a working solution here. Unfortunately, almost all solutions I can think of now involve hardcoding something for each of those images, and I don't want that. In a way, this problem is similar to the one you had with the context menus in the other thread: I simply want to be able to dynamically have as many existing images as I want (from 1 to the Dock- and Item- Count variables). The thing is, while for your case there, the custom context menu behaved and didn't spam countless errors in the log if made "" or [], seamlessly invalidating empty entries, with images this isn't the case... because reasons. :confused:
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 4694
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?] Double variable nesting and bang variables

Post by Yincognito »

Managed to find an atrocious workaround, but a workaround nevertheless:
- commented out the ImageName options from the [sDockIcon] and [sItemIcon] styles, effectively making the options initially empty:

Code: Select all

[sDockIcon]
...
;ImageName=#CURRENTSECTION#.png

[sItemIcon]
...
;ImageName=DockIcon#DockIndex##CURRENTSECTION#.png
- added a [ValidateImages] measure where I constructed the bangs to reset to empty and populate the ImageName options when updating meters at runtime, with the help of a RegExp Substitute to eliminate setting the said options for image indexes greater than the corresponding image count values:

Code: Select all

[ValidateImages]
Measure=String
String=[!SetOption DockIcon1 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon2 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon3 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon4 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon5 ImageName "#*CURRENTSECTION*#.png"][\x200B][!SetOption ItemIcon1 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon2 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon3 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon4 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon5 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"]
UpdateDivider=-1
RegExpSubstitute=1
Substitute="^(?siU)((?:\[.*\]){[#DockCount]}).*[\x200B]((?:\[.*\]){[#ItemCount[#DockIndex]]}).*$":"\1\2","(?:^\\1|\\2$)":"","^(.*)$":'[!SetOptionGroup DockIconGroup ImageName ""][!SetOptionGroup ItemIconGroup ImageName ""]\1',"\\1$":""
DynamicVariables=1
- updated the above measure and executed the constructed bangs in the first meter's OnUpdateAction:

Code: Select all

[DockContainer]
...
OnUpdateAction=[!UpdateMeasure ValidateImages][ValidateImages]
Full code:

Code: Select all

[Variables]
DockSet=[!CommandMeasure Move "Stop 1"][!CommandMeasure Move "Stop 2"][!SetVariable Offset ([#***DockIndex***]=[#**DockIndex**]?[#***Offset***]:0)][!CommandMeasure Move "Execute [#***Execute***]"]
DockRun=[!CommandMeasure Move "Stop 1"][!CommandMeasure Move "Stop 2"][!SetVariable Execute (3-[#***Execute***])][!CommandMeasure Move "Execute [#***Execute***]"]
ScaleIcon=([#*Scale*]);0;0;([#*Scale*]);((1-[#*Scale*])*([[#*MeterName*]:X]+[[#*MeterName*]:W]/2));((1-[#*Scale*])*([[#*MeterName*]:Y]+[[#*MeterName*]:H]/2))
Scale=1
Value=0.05
DockBackColor=0,0,0,128
ItemBackColor=0,0,0,128
NoTintColor=255,255,255,255
TintedColor=128,128,128,255
Indent=8
IconSize=48
MeterName=
Offset=0
Execute=2
DockIndex=1
DockCount=5
ItemCount1=2
ItemCount2=0
ItemCount3=1
ItemCount4=3
ItemCount5=1
DockIcon1Set=[!SetVariable DockIndex 1][#DockSet]
DockIcon2Set=[!SetVariable DockIndex 2][#DockSet]
DockIcon3Set=[!SetVariable DockIndex 3][#DockSet]
DockIcon4Set=[!SetVariable DockIndex 4][#DockSet]
DockIcon5Set=[!SetVariable DockIndex 5][#DockSet]
DockIcon1Run=[#DockRun]
DockIcon2Run=[#DockRun]
DockIcon3Run=[#DockRun]
DockIcon4Run=[#DockRun]
DockIcon5Run=[#DockRun]
ItemIcon1Run=[#*DockIcon[#*DockIndex*]ItemIcon1App*]
ItemIcon2Run=[#*DockIcon[#*DockIndex*]ItemIcon2App*]
ItemIcon3Run=[#*DockIcon[#*DockIndex*]ItemIcon3App*]
ItemIcon4Run=[#*DockIcon[#*DockIndex*]ItemIcon4App*]
ItemIcon5Run=[#*DockIcon[#*DockIndex*]ItemIcon5App*]
DockIcon1ItemIcon1App=["C:\Program Files\Google\Chrome\Application\chrome.exe"]
DockIcon1ItemIcon2App=[msedge.exe]
DockIcon3ItemIcon1App=[notepad.exe]
DockIcon4ItemIcon1App=[wmplayer.exe]
DockIcon4ItemIcon2App=[mspaint.exe]
DockIcon4ItemIcon3App=[taskmgr.exe]
DockIcon5ItemIcon1App=["C:\Program Files\Rainmeter\Rainmeter.exe" !Manage]

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
MouseLeaveAction=[!CommandMeasure Move "Stop 1"][!CommandMeasure Move "Stop 2"][!SetVariable Execute 2][!CommandMeasure Move "Execute [#Execute]"]

---Measures---

[ValidateImages]
Measure=String
String=[!SetOption DockIcon1 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon2 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon3 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon4 ImageName "#*CURRENTSECTION*#.png"][!SetOption DockIcon5 ImageName "#*CURRENTSECTION*#.png"][\x200B][!SetOption ItemIcon1 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon2 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon3 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon4 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"][!SetOption ItemIcon5 ImageName "DockIcon#*DockIndex*##*CURRENTSECTION*#.png"]
UpdateDivider=-1
RegExpSubstitute=1
Substitute="^(?siU)((?:\[.*\]){[#DockCount]}).*[\x200B]((?:\[.*\]){[#ItemCount[#DockIndex]]}).*$":"\1\2","(?:^\\1|\\2$)":"","^(.*)$":'[!SetOptionGroup DockIconGroup ImageName ""][!SetOptionGroup ItemIconGroup ImageName ""]\1',"\\1$":""
DynamicVariables=1

[Size]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat SizeUp,10,5
SizeUp=[!SetVariable Scale (Clamp([#Scale]+[#Value],1.25-[#Value]*5,1.25))][!SetOption [#MeterName] TransformationMatrix "#ScaleIcon#"][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
ActionList2=Repeat SizeDn,10,5
SizeDn=[!SetVariable Scale (Clamp([#Scale]-[#Value],1.25-[#Value]*5,1.25))][!SetOption [#MeterName] TransformationMatrix "#ScaleIcon#"][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
UpdateDivider=-1
DynamicVariables=1

[Move]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat MoveUp,100,8
MoveUp=[!SetVariable Offset (Clamp([#Offset]+[&ItemContainer:H]/8,0,[&ItemContainer:H]))][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
ActionList2=Repeat MoveDn,100,8
MoveDn=[!SetVariable Offset (Clamp([#Offset]-[&ItemContainer:H]/8,0,[&ItemContainer:H]))][!UpdateMeasure #CURRENTSECTION#][!UpdateMeter *][!Redraw]
UpdateDivider=-1
DynamicVariables=1

---Styles---

[sIcon]
W=(#IconSize#)
H=(#IconSize#)
ImagePath=#@#Images\
PreserveAspectRatio=1
ImageTint=#TintedColor#
UpdateDivider=-1
MouseOverAction=[!SetOption #CURRENTSECTION# ImageTint "#NoTintColor#"][!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup IconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw][!CommandMeasure Size "Execute 1"][#[#CURRENTSECTION]Set]
MouseLeaveAction=[!SetOption #CURRENTSECTION# ImageTint "#TintedColor#"][!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup IconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw][!CommandMeasure Size "Execute 2"]
LeftMouseDownAction=[!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1.25][!SetVariable Value 0.10][!CommandMeasure Size "Execute 2"]
LeftMouseUpAction=[!SetVariable MeterName "#CURRENTSECTION#"][!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 0.75][!SetVariable Value 0.10][!CommandMeasure Size "Execute 1"][#[#CURRENTSECTION]Run]
DynamicVariables=1

[sDockIcon]
Group=IconGroup | DockIconGroup
Container=DockContainer
X=(#Indent#)R
Y=(0)r
;ImageName=#CURRENTSECTION#.png

[sItemIcon]
Group=IconGroup | ItemIconGroup
Container=ItemContainer
X=(0)r
Y=(#Indent#)R
;ImageName=DockIcon#DockIndex##CURRENTSECTION#.png

---Meters---

[DockContainer]
Meter=Image
X=(0)
Y=(0)R
W=((#IconSize#+#Indent#)*#DockCount#+#Indent#)
H=((#IconSize#+#Indent#)*1+#Indent#)
SolidColor=0,0,0,255
UpdateDivider=-1
OnUpdateAction=[!UpdateMeasure ValidateImages][ValidateImages]
MouseLeaveAction=[!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup DockIconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw]
DynamicVariables=1

[DockBackground]
Container=DockContainer
Meter=Image
X=(0)r
Y=(0)r
W=([DockContainer:W])
H=([DockContainer:H])
SolidColor=#DockBackColor#
UpdateDivider=-1
DynamicVariables=1

[DockIcon1]
Meter=Image
MeterStyle=sIcon | sDockIcon
X=(#Indent#)r
Y=(#Indent#)r

[DockIcon2]
Meter=Image
MeterStyle=sIcon | sDockIcon

[DockIcon3]
Meter=Image
MeterStyle=sIcon | sDockIcon

[DockIcon4]
Meter=Image
MeterStyle=sIcon | sDockIcon

[DockIcon5]
Meter=Image
MeterStyle=sIcon | sDockIcon

[ItemContainer]
Meter=Image
X=((#IconSize#+#Indent#)*([#DockIndex]-1))
Y=(0)R
W=((#IconSize#+#Indent#)*1+#Indent#)
H=((#IconSize#+#Indent#)*[#ItemCount[#DockIndex]]+#Indent#*Sgn([#ItemCount[#DockIndex]]))
SolidColor=0,0,0,255
UpdateDivider=-1
MouseLeaveAction=[!CommandMeasure Size "Stop 1"][!CommandMeasure Size "Stop 2"][!SetVariable Scale 1][!SetVariable Value 0.05][!SetOptionGroup ItemIconGroup TransformationMatrix "#ScaleIcon#"][!UpdateMeter *][!Redraw]
DynamicVariables=1

[ItemBackground]
Container=ItemContainer
Meter=Image
X=(0)r
Y=([#Offset]-[ItemContainer:H])r
W=([ItemContainer:W])
H=([ItemContainer:H])
SolidColor=#ItemBackColor#
UpdateDivider=-1
DynamicVariables=1

[ItemIcon1]
Meter=Image
MeterStyle=sIcon | sItemIcon
X=(#Indent#)r
Y=(#Indent#)r

[ItemIcon2]
Meter=Image
MeterStyle=sIcon | sItemIcon

[ItemIcon3]
Meter=Image
MeterStyle=sIcon | sItemIcon

[ItemIcon4]
Meter=Image
MeterStyle=sIcon | sItemIcon

[ItemIcon5]
Meter=Image
MeterStyle=sIcon | sItemIcon
Now I have no errors regarding missing images that I intentionally don't or want to have, but the workaround is still atrocious because the string used to construct the bangs in [ValidateImages] grows proportionally with the count / number of both docks / menus and items / submenus, considering I can't use groups and still remove individual bangs. Basically, it's just like using hardcoded option values for each meter I have, which is the very thing I wanted to avoid by using #CURRENTSECTION# based values. So much for dynamically controlling things... :Whistle

And this is, folks, how "hideously complicated code" and "bad design" come into existence. Not because I code that way or the INI format is somehow not suited for the job, but because circumstances demand it by not having the right tools to write it in a smooth fashion. Missing a one line option in native Rainmeter and a few lines of code in C++, and skin designers will write that tenfold afterwards. Well, hell, at least it's possible for some, not possible for others. The devs more than compensate such shortcommings in other ways anyway, see the other issue described above, so it is what it is. :)