It is currently April 19th, 2024, 10:05 am

Optimizing similar Calc measure to sum the meters' width

Get help with creating, editing & fixing problems with skins
User avatar
Active Colors
Moderator
Posts: 1251
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Optimizing similar Calc measure to sum the meters' width

Post by Active Colors »

I need to calculate the total width of desired meters.
They meters are similar except their widths could be different.

The meters are numbered from 1 to, for example 30, but there could be more than 30.
The desired meters to calculate are chosen by a variable N.
If N=N (positive integer) then I need to calculate the total width of the meters from 1 to N.
For example if N=7 then I strictly need to calculate the total width of the meters from 1 to 7.

Example:

Code: Select all

[Variables]
N=4

[Icon1]
Meter=Image
W=40

[Icon2]
Meter=Image
W=15

[Icon3]
Meter=Image
W=20

[Icon4]
Meter=Image
W=55
According to the variable N I need to calculate the total width of the meters ObjIcon1, ObjIcon2, ObjIcon3, and ObjIcon4.

In order to calculate the width of a desired number of meters I am using in the following approach:

Code: Select all

[Variables]
N=4

[W1]
Measure=Calc
Formula=([Icon1:W])
DynamicVariables=1
Disabled=1

[W2]
Measure=Calc
Formula=([Icon1:W]+[Icon2:W])
DynamicVariables=1
Disabled=1

[W3]
Measure=Calc
Formula=([Icon1:W]+[Icon2:W]+[Icon3:W])
DynamicVariables=1
Disabled=1

[W4]
Measure=Calc
Formula=([Icon1:W]+[Icon2:W]+[jIcon3:W]+[Icon4:W])
DynamicVariables=1
Disabled=0
But then because it could also be a lot more meters to calculate then the number of measures would grow. And a hypothetical calc measure [W20] would look like:

Code: Select all

[W20]
Measure=Calc
Formula=([Icon1:W]+[Icon2:W]+[Icon3:W]+[Icon4:W]+[Icon5:W]+[Icon6:W]+[Icon7:W]+[Icon8:W]+[Icon9:W]+[Icon10:W]+[Icon11:W]+[Icon12:W]+[Icon13:W]+[Icon14:W]+[Icon15:W]+[Icon16:W]+[Icon17:W]+[Icon18:W]+[Icon19:W]+[Icon20:W])
DynamicVariables=1
Disabled=0
Because the N is changeable I would need to keep a lot of calc measures like that, making the whole approach very ugly.

I am wondering if there is a possible way to optimize this and have only 1 measure that could be used to calculate any desired amount of meter's widths?
Is there a way to make one calc measure that could understand how many meters it needs to sum and it would sum them?

(I know that it would be simple if all the meters had the same width and I could use simply Formula=(#W#*#N#) but unfortunately that's not the case.)


For the moment I was able to eliminate the repetition to some degree:

Code: Select all

[Variables]
N=4

[W1]
Measure=Calc
Formula=([Icon1:W])
DynamicVariables=1
Disabled=0

[W2]
Measure=Calc
Formula=([&W1]+[Icon2:W])
DynamicVariables=1
Disabled=0

[W3]
Measure=Calc
Formula=([&W2]+[Icon3:W])
DynamicVariables=1
Disabled=0

[W4]
Measure=Calc
Formula=([&W3]+[Icon4:W])
DynamicVariables=1
Disabled=0

And with the help of a lua script made by Yincognito I was able to remove the repetition further:

Code: Select all

[Variables]
N=4
W=(([&W[#*PreviousSectionIndex*]])+([Icon[#*CurrentSectionIndex]:W]))

[W1]
Measure=Calc
Formula=([Icon[#CurrentSectionIndex]:W])
DynamicVariables=1
Disabled=0

[W2]
Measure=Calc
Formula=#W#
DynamicVariables=1
Disabled=0

[W3]
Measure=Calc
Formula=#W#
DynamicVariables=1
Disabled=0

[W4]
Measure=Calc
Formula=#W#
DynamicVariables=1
Disabled=0
I am still looking for a way to have only one measure instead of having numerous of them.
User avatar
ikarus1969
Posts: 571
Joined: February 28th, 2011, 3:20 pm
Location: Vienna, Austria

Re: Optimizing similar Calc measure to sum the meters' width

Post by ikarus1969 »

What about that - a quick -and-dirty thing:

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
BackgroundMode=2
SolidColor=FFFFFFFF

[Variables]
TOTALWIDTH=0
FROM=1
NUMBER_OF_METERS=4


[Measure_Width]
Measure=CALC
Formula=Measure_Width + [&Meter_[#FROM]:W]
IfConditionMode=1
IfCondition=[#FROM]=[#NUMBER_OF_METERS]
IfTrueAction=[!SetVariable "TOTALWIDTH" "[&Measure_Width]"][!PauseMeasure  "[#CURRENTSECTION]"]
IfFalseAction=[!SetVariable "FROM" "([#FROM] + 1)"][!UpdateMeasure "[#CURRENTSECTION]"]
DynamicVariables=1

; --------------------------------------------------------------------------------
; Meters
; --------------------------------------------------------------------------------
[Meter_1]
Meter=STRING
Text=sajh sdkj 
X=0
Y=0
AntiAlias=1

[Meter_2]
Meter=STRING
Text=sajh sdkj 
X=0
Y=0R
AntiAlias=1

[Meter_3]
Meter=STRING
Text=sajh sdkj slkfjdsk ksdflkjsd ksjdfjsdlf
X=0
Y=0R
AntiAlias=1

[Meter_4]
Meter=STRING
Text=sajh
X=0
Y=0R
AntiAlias=1

[Meter_5]
Meter=STRING
Text=sajh sdkj sdkfkjdf
X=0
Y=0R
AntiAlias=1

[Meter_Width]
Meter=STRING
Text=N=[#NUMBER_OF_METERS], Width=[#TOTALWIDTH]
X=0
Y=10R
DynamicVariables=1
User avatar
Brian
Developer
Posts: 2679
Joined: November 24th, 2011, 1:42 am
Location: Utah

Re: Optimizing similar Calc measure to sum the meters' width

Post by Brian »

Or a simple inline lua function:

MeterSize.lua

Code: Select all

function GetWidth()
	local n = SKIN:GetVariable('N', 0)
	local width = 0
	for i = 1, n do width = width + SKIN:GetMeter('Icon'..i):GetW() end
	return width
end
Skin.ini

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1

[Variables]
N=4

[Script]
Measure=Script
ScriptFile=#@#MeterSize.lua
Disabled=1

[Icon1]
Meter=Image
W=10

[Icon2]
Meter=Image
W=1

[Icon3]
Meter=Image
W=2

[Icon4]
Meter=Image
W=3

[Meter]
Meter=String
FontColor=FFFFFF
SolidColor=000000
Padding=5,5,5,5
Text=Size = [Script:GetWidth()]
DynamicVariables=1
-Brian
User avatar
Yincognito
Rainmeter Sage
Posts: 7125
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Optimizing similar Calc measure to sum the meters' width

Post by Yincognito »

Active Colors wrote: February 18th, 2022, 2:47 pmI am wondering if there is a possible way to optimize this and have only 1 measure that could be used to calculate any desired amount of meter's widths?
Is there a way to make one calc measure that could understand how many meters it needs to sum and it would sum them?

(I know that it would be simple if all the meters had the same width and I could use simply Formula=(#W#*#N#) but unfortunately that's not the case.)
[...]
I am still looking for a way to have only one measure instead of having numerous of them.
Yes, yes, yes, and here it is - it doesn't even need a measure, just a variable, a meter where you initialize the said variable to 0 (could have been the 1st icon meter as well, by the way), some MeterStyle to avoid copy pasting, and a synchronous updating of the icon meters which I assume you already have (the rest in the code - including the measure, the max or the hide/show toggling - is entirely optional, just to beautify and make the whole thing a bit dynamic via mouse scroll):

Code: Select all

[Variables]
N=9
MAXN=9
TW=0

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
DefaultUpdateDivider=-1

---Measures---

[TW]
Measure=Calc
Formula=(#TW#)
DynamicVariables=1

---Styles---

[SumStyle]
SolidColor=255,0,0,255
Y=15r
H=10
DynamicVariables=1
OnUpdateAction=[!SetVariable TW (#TW#+[#CURRENTSECTION#:W])][!UpdateMeasure TW]

---Meters---

[Background]
Meter=Shape
Shape=Rectangle 0,0,100,160 | Fill Color 0,0,0,255 | StrokeWidth 0
OnUpdateAction=[!SetVariable TW 0]
MouseScrollUpAction=[!SetVariable N (Clamp(#N#+1,1,#MAXN#))][!ShowMeter Icon#N#][!UpdateMeter *][!Redraw]
MouseScrollDownAction=[!SetVariable N (Clamp(#N#-1,1,#MAXN#))][!HideMeter Icon#N#][!UpdateMeter *][!Redraw]
DynamicVariables=1

[Icon1]
Meter=Image
MeterStyle=SumStyle
W=20

[Icon2]
Meter=Image
MeterStyle=SumStyle
W=10

[Icon3]
Meter=Image
MeterStyle=SumStyle
W=12

[Icon4]
Meter=Image
MeterStyle=SumStyle
W=31

[Icon5]
Meter=Image
MeterStyle=SumStyle
W=1

[Icon6]
Meter=Image
MeterStyle=SumStyle
W=7

[Icon7]
Meter=Image
MeterStyle=SumStyle
W=19

[Icon8]
Meter=Image
MeterStyle=SumStyle
W=43

[Icon9]
Meter=Image
MeterStyle=SumStyle
W=36
Sum.jpg
Basically, all you need to do is add the currently updated meter's width to the already existing sum value, and of course, reset it that sum to 0 in the beginning. You can even count those meters like that, by the way, by adding 1 to the sum instead of the meter's width.

P.S. If you want to be able to update individual icon meters without messing up with the resulting sum via duplicate additions, you can create, say, a #NeedSum# variable that you can set or toggle according to your needs (1 to add meter width to the sum, 0 to not do that), and only reset the sum to 0 or add widths to the #TW# (total width) "on demand", by doing something similar to:

Code: Select all

[!SetVariable TW (#NeedSum#=1?#TW#+[#CURRENTSECTION#:W]:#TW#)]
P.S.S. This does not depend on the name of the meters, it can be used with any meter that you use the style (or better said, the OnUpdateAction bangs) on, and it doesn't choke if self updating a measure for a couple of hundreds or thousands of meters (assuming you'd have that in your skin, that is). It simply attaches itself to the natural Rainmeter updating process and only requires a bit of attention when you update meters, so as to not yield an incorrect result, that's all.

EDIT: Played a bit with the code to make it compute the widths sum properly when individually updating meters - again, this is entirely optional, since I have no idea what is the context where you want this to be applied on:

Code: Select all

[Variables]
N=9
MAXN=9
TW=0
MAXW=100

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
DefaultUpdateDivider=-1

---Measures---

[TW]
Measure=Calc
Formula=([#TW])
DynamicVariables=1

---Styles---

[SumStyle]
SolidColor=255,0,0,255
Y=15r
H=10
OnUpdateAction=[!SetVariable TW ([#TW]+[#CURRENTSECTION#:W])][!UpdateMeasure TW]
MouseScrollUpAction=[!SetVariable TW ([#TW]-[#CURRENTSECTION#:W])][!UpdateMeasure TW][!SetOption #CURRENTSECTION# W (Clamp([#CURRENTSECTION#:W]+1,1,#MAXW#))][!UpdateMeter #CURRENTSECTION#][!Redraw]
MouseScrollDownAction=[!SetVariable TW ([#TW]-[#CURRENTSECTION#:W])][!UpdateMeasure TW][!SetOption #CURRENTSECTION# W (Clamp([#CURRENTSECTION#:W]-1,1,#MAXW#))][!UpdateMeter #CURRENTSECTION#][!Redraw]
DynamicVariables=1

---Meters---

[Background]
Meter=Shape
Shape=Rectangle 0,0,100,160 | Fill Color 0,0,0,255 | StrokeWidth 0
OnUpdateAction=[!SetVariable TW 0]
MouseScrollUpAction=[!SetVariable N (Clamp(#N#+1,1,#MAXN#))][!ShowMeter Icon#N#][!UpdateMeter *][!Redraw]
MouseScrollDownAction=[!SetVariable N (Clamp(#N#-1,1,#MAXN#))][!HideMeter Icon#N#][!UpdateMeter *][!Redraw]
DynamicVariables=1

[Icon1]
Meter=Image
MeterStyle=SumStyle
W=20

[Icon2]
Meter=Image
MeterStyle=SumStyle
W=10

[Icon3]
Meter=Image
MeterStyle=SumStyle
W=12

[Icon4]
Meter=Image
MeterStyle=SumStyle
W=31

[Icon5]
Meter=Image
MeterStyle=SumStyle
W=1

[Icon6]
Meter=Image
MeterStyle=SumStyle
W=7

[Icon7]
Meter=Image
MeterStyle=SumStyle
W=19

[Icon8]
Meter=Image
MeterStyle=SumStyle
W=43

[Icon9]
Meter=Image
MeterStyle=SumStyle
W=36
What happens here is that besides scrolling on the blank background to simulate changing the number of icon meters, I added scrolling on individual meters to simulate such meters dynamically changing their width (updating individually, in this case, for the sake of argument). The changes to the code are switching to the nested syntax for [#TW] (total width) in order to get its current value without having to update the respective meter, and subtracting the meter width value from the sum before dynamically changing it, followed by individually updating the meter as usual (which will add back its newly modified width to the sum) after the dynamic adjustment. Even with such (potential) code changes, the idea remains that the key to the process is a simple [!SetVariable TW ([#TW]+[#CURRENTSECTION#:W])] on update.
You do not have the required permissions to view the files attached to this post.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
balala
Rainmeter Sage
Posts: 16144
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Optimizing similar Calc measure to sum the meters' width

Post by balala »

Even if a little bit late, I'm also adding my code. Here I have the N variable, which obviously is the number of meters to be counted and TotalWidth, which is the sum of widths of meters. At the beginning, this TotalWidth variable is initialized to the width of first meter (TotalWidth=[Icon1:W]). Then I have a Calc measure ([MeasureWidth]) which in fact is a simple counting measure. On each change of the value of this measure, you get added to the TotalWidth variable the width of next meter. An IfCondition checks if the value of the measure reached the value of the N variable. If it did, the [MeasureWidth] measure is disabled, because we don't really need it anymore. The remaining value of the TotalWidth variable is exactly the sum of widths.
I don't post the [IconX] meters, because from the point of view of the measure, these are not important. So you have to add the following variables to the [Variables] section and the following measure. The result is returned by the TotalWidth variable:

Code: Select all

[Variables]
N=7
TotalWidth=[Icon1:W]

[MeasureWidth]
Measure=Calc
Formula=( MeasureWidth + 1 )
OnChangeAction=[!SetVariable TotalWidth "(#TotalWidth#+[Icon[MeasureWidth]:W])"]
IfCondition=(#CURRENTSECTION#=#N#)
IfTrueAction=[!DisableMeasure "#CURRENTSECTION#"]
DynamicVariables=1
User avatar
Yincognito
Rainmeter Sage
Posts: 7125
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Optimizing similar Calc measure to sum the meters' width

Post by Yincognito »

balala wrote: February 18th, 2022, 8:18 pmOn each change of the value of this measure, you get added to the TotalWidth variable the width of next meter.
Great idea! One question though: doesn't such counting require a number of skin updates equal to the number of icon meters to reach to the total sum? :???:
Unless the measure is updated very fast compared to the meters, that is, which is more or less what ikarus1969 proposed with self updating the measure (that would be ok in principle but gets heavy on Rainmeter after a couple hundreds or thousands iterations - around 300 or 3000 if I recall correctly from my experience a long time ago, depending on the overall environment).
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
balala
Rainmeter Sage
Posts: 16144
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Optimizing similar Calc measure to sum the meters' width

Post by balala »

Yincognito wrote: February 18th, 2022, 9:04 pm Great idea! One question though: doesn't such counting require a number of skin updates equal to the number of icon meters to reach to the total sum? :???:
Yes, it requires. To avoid this add a [!UpdateMeasure "MeasureWidth"] bang to the OnChangeAction option of the [MeasureWidth] measure: OnChangeAction=[!SetVariable TotalWidth "(#TotalWidth#+[Icon[MeasureWidth]:W])"][!UpdateMeasure "MeasureWidth"].
User avatar
Yincognito
Rainmeter Sage
Posts: 7125
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Optimizing similar Calc measure to sum the meters' width

Post by Yincognito »

balala wrote: February 18th, 2022, 10:12 pm Yes, it requires. To avoid this add a [!UpdateMeasure "MeasureWidth"] bang to the OnChangeAction option of the [MeasureWidth] measure: OnChangeAction=[!SetVariable TotalWidth "(#TotalWidth#+[Icon[MeasureWidth]:W])"][!UpdateMeasure "MeasureWidth"].
Eureka! :thumbup:
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Active Colors
Moderator
Posts: 1251
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Re: Optimizing similar Calc measure to sum the meters' width

Post by Active Colors »

ikarus1969, Brian, Yincognito, balala
Thank you guys for your help! THANKS! For a while, this was an unmovable stone for me. Your code makes total sense and the initial task now does not seem as hard as before. Thank you so much! I tested everyone's codes and everything works and everything can be easily integrated into my projects. Now I just need to choose which one to go with :D
Thank you very much again, ikarus1969, Brian, Yincognito, and balala. :rosegift:
User avatar
Yincognito
Rainmeter Sage
Posts: 7125
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Optimizing similar Calc measure to sum the meters' width

Post by Yincognito »

Active Colors wrote: February 20th, 2022, 9:24 pm ikarus1969, Brian, Yincognito, balala
Thank you guys for your help! THANKS! For a while, this was an unmovable stone for me. Your code makes total sense and the initial task now does not seem as hard as before. Thank you so much! I tested everyone's codes and everything works and everything can be easily integrated into my projects. Now I just need to choose which one to go with :D
Thank you very much again, ikarus1969, Brian, Yincognito, and balala. :rosegift:
I believe we're all glad to help - feel free to choose whatever variant suits your project best. Yeah, it happens sometimes that we're stuck in a certain mindset about how to solve a problem and can't see any other way out to achieve an objective, I've been there before. For me, a good night sleep usually refreshes my brain and provides me with alternatives, but one takes something useful from various places (like this forum). ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth