It is currently March 29th, 2024, 4:01 pm

Centering relatively to other meter

Tips and Tricks from the Rainmeter Community
User avatar
Active Colors
Moderator
Posts: 1251
Joined: February 16th, 2012, 3:32 am
Location: Berlin, Germany

Centering relatively to other meter

Post by Active Colors »

This topic prompted me to write a trick for positioning meter relatively to the center of other meter. I thought just simple positioning won't be tricky enough and decided to go deeper and as an example make:

An image meter that will be resized based on string's meter Text which stays centered based on Width of the image meter.
and:
An image meter that will be resized based on string's meter Text and will be centered relatively to the string meter's Text.

And in both cases we don't have Width and Height values for the string meter. What only we will depend on is a Text itself!


Don't see the difference between two? See the spoiler.
First case implies that every meter will be centered, therefore in the second case image meter would be sticked to the left or right fringe while text would be centered and placed inside the image.
Still don't see any difference? See the next spoiler then.
In the first case whatever Text you write your image meter will be resized based on that Text and this Text will stay centered inside the image meter whatever width it obtains from that Text.

In the second case whatever Text you write your image meter will be resized based on that Text and image meter will stay centered outside the string meter whatever Text string meter has.
Still? Last one.
In the first case as a center point we take image's position and in the second case as a center point we take text's position. So, in the first case will be centered the text and in the second will be centered the image. Plus in both cases image's width are depending on text itself and not on it's width.


I decided to eliminate width and height values because in this way it is more tricky to obtain centering. And this trick will be handy in different situations.

Depending on different alignments code should be little or drastically changed.
For my examples as an image meter I will use prepared button below:
BTNgreen.png
Center Alignment

Code: Select all

[Image1C]
Meter=IMAGE
ImageName=BTNgreen.png
ScaleMargins=10,10,10,10
X=(([Text1C:X])-([Image1C:W]/2))
Y=45
W=(([Text1C:W])+22)       ;22 additional pixels will be added to the edges in order to make image look like real button. If not added then the width would be same as text's width.
H=([Text1C:H]+20)       ;20 additional pixels will be added for the same reason as in W.
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1
Hidden=0

[Text1C]
Meter=STRING
X=120
Y=(([Image1C:H]/2)-([Text1C:H]/2)+([Image1C:Y]))
StringAlign=CENTER
FontFace=Arial
FontSize=10
FontColor=255,255,255
StringStyle=NORMAL
AntiAlias=1
Text="Example"
DynamicVariables=1
UpdateDivider=-1
Hidden=0
cc1.png
cc2.png
cc3.png
X is controled from string, Y is controlled from image.
If you want to make the whole thing to auto-center inside the background or any other image, you can add this lines:

Code: Select all

[Image1C]
Y=([YourBackground:Y]+([YourBackground:H]/2)-([Text1C:H]/2)-10)      ;10 is exactly half of added additional 20 pixels in the H of [Image1C] meter

[Text1C]
X=([YourBackground:X]+([YourBackground:W]/2))
Notice that in this situation we have not to update these meters. Otherwise "construction" would be broken. Though if you need meters updated look at the following approach:

Code: Select all

[Image2]
Meter=IMAGE
ImageName=BTNgreen.png
ScaleMargins=10,10,10,10
X=(120-([Image2:W]/2))
Y=(70-([Image2:Y]/2))
W=(([Text2:W])+22)
H=([Text2:H]+20)
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1
Hidden=0

[Text2]
Meter=STRING
X=(([Image2:X])+([Image2:W]/2))
Y=(([Image2:Y])+([Image2:H]/2)-([Text2:H]/2))
StringAlign=CENTER
FontFace=Arial
FontSize=10
FontColor=255,255,255
StringStyle=NORMAL
AntiAlias=1
Text="Example"
DynamicVariables=1
UpdateDivider=-1
Hidden=0
In this approach we have to add !UpdateMeter bang into [Rainmeter] section. If not added then the placement points would be messed up:

Code: Select all

[Rainmeter]
OnRefreshAction=[!UpdateMeter Image2][!UpdateMeter Text2][!Redraw]

Left Alignment
In comparison to center alignment, left alignment is only one alignment that works flawless updated it or not.

Code: Select all

[Image3L]
Meter=IMAGE
ImageName=BTNgreen.png
ScaleMargins=10,10,10,10
X=10
Y=40
W=([Text3L:W]+22)
H=([Text3L:H]+20)
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1
Hidden=0

[Text3L]
Meter=STRING
X=(([Image3L:X])+([Image3L:W]/2))
Y=([Image3L:Y]+([Image3L:H]/2)-([Text3L:H]/2))
StringAlign=CENTER
FontFace=Arial
FontSize=10
FontColor=255,255,255
StringStyle=NORMAL
AntiAlias=1
Text="Example"
DynamicVariables=1
UpdateDivider=-1
Hidden=0
l1.png
l2.png

Right Alignment
In this case meters shouldn't be updated. Otherwise positioning would be destroyed.

Code: Select all

[Image1R]
Meter=IMAGE
ImageName=BTNgreen.png
ScaleMargins=10,10,10,10
X=(([Text1R:X])-([Image1R:W]/2))
Y=40
W=(([Text1R:W])+22)
H=([Text1R:H]+20)
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1
Hidden=0

[Text1R]
Meter=STRING
X=220
Y=([Image1R:Y]+([Image1R:H]/2)-([Text1R:H]/2))
StringAlign=RIGHT
FontFace=Arial
FontSize=10
FontColor=255,255,255
StringStyle=NORMAL
AntiAlias=1
Text="Example"
DynamicVariables=1
UpdateDivider=-1
Hidden=0
r1.png
r2.png
You do not have the required permissions to view the files attached to this post.
ZXCVBOT

Re: Centering relatively to other meter

Post by ZXCVBOT »

Hi! I was having trouble in positioning a meter in relation to 2 meters - in the center. What's more, I can't understand why basic maths is not working out for this situation. Or even CurrentConfigWidth - althought this might be due to the fact the entire skin has been centered by use of this or by the meters being dynamic in nature.

Code: Select all

[Variables]

PlayerName=AIMP
Font=Din Next LT Pro
FontColor=255,255,255,200
FontSize=(13*#ConfigScale#)
ConfigScale=1.1
ProgressScale=2
Scale=(1*#ConfigScale#)
Outline=(1*#ConfigScale#)

; ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

[MeasurePosition]
Measure=Plugin
Plugin=NowPlaying
PlayerName=#PLayerName#
PlayerType=POSITION

[MeasureDuration]
Measure=Plugin
Plugin=NowPlaying
PlayerName=#PLayerName#
PlayerType=DURATION

[MeasureRemaining]
Measure=Calc
Formula=( MeasureDuration - MeasurePosition )

[MeasureRemainingMinutes]
Measure=Calc
Formula=Trunc((MeasureRemaining)/60)
RegExpSubstitute=1
Substitute="^(.)$":"0\1"
DynamicVariables=1

[MeasureRemainingSeconds]
Measure=Calc
Formula=((MeasureRemaining) % 60)
RegExpSubstitute=1
Substitute="^(.)$":"0\1"
DynamicVariables=1

[MeasureMinutesRemaining]
Measure=Calc
Formula=Trunc((MeasurePosition)/60)
RegExpSubstitute=1
Substitute="^(.)$":"0\1"
DynamicVariables=1

[MeasureSecondsRemaining]
Measure=Calc
Formula=((MeasurePosition) % 60)
RegExpSubstitute=1
Substitute="^(.)$":"0\1"
DynamicVariables=1

[MeasureMinutes]
Measure=Calc
Formula=Trunc((MeasureDuration)/60)
RegExpSubstitute=1
Substitute="^(.)$":"0\1"
DynamicVariables=1

[MeasureSeconds]
Measure=Calc
Formula=((MeasureDuration) % 60)
RegExpSubstitute=1
Substitute="^(.)$":"0\1"
DynamicVariables=1

[MeasureNowPlaying]
Measure=Plugin
Plugin=NowPlaying
PlayerName=#PlayerName#
PlayerType=Progress
AverageSize=#AverageSize#
MinValue=0
MaxValue=100

; ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

[M_Bar]
Meter=Shape
;X=(([M_Duration_Played:X]+[M_Duration_Played:W]+7*#ConfigScale#))
X=((([M_Total_Duration:X]+[M_Total_Duration:W])-([M_Duration_Played:X][M_Duration_Played:W]))/2)
Y=([M_Duration_Played:Y]+8)

Shape=Rectangle 0,0,(132*#ProgressScale#*#ConfigScale#),(1.6*#ProgressScale#),(1*#ProgressScale#) | Fill Color #FontColor#,200 | StrokeWidth #Outline# | Stroke Color 128,128,128,200
Shape2=Rectangle 0,0,([MeasureNowPlaying]*1.32*#ProgressScale#*#ConfigScale#),(1.5*#ProgressScale#),(1*#ProgressScale#) | Fill Color #Color#,220 | StrokeWidth #Outline# | Stroke Color #Glow#
Shape3=Ellipse ([MeasureNowPlaying]*1.32*#ProgressScale#*#ConfigScale#),(0.8*#ProgressScale#),(4*#Scale#) |Fill Color #FONTCOLOR# | StrokeWidth (#Outline#+0.5) | Stroke Color #HighlightColor#

DynamicVariables=1
Group=Progress Group
TooltipText=Track Completion: [MeasureNowPlaying:%,0]%
SolidColor=0,0,0,1

[M_Total_Duration]
Meter=STRING
MeasureName=MeasureMinutes
MeasureName2=MeasureSeconds
X=((384*#Scale#*#ConfigScale#))
Y=([M_Duration_Played:Y])
StringAlign=Right
SolidColor=0,0,0,1
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=10
Text="%1:%2"
AntiAlias=1
DynamicVariables=1
Group=Progress Group

[M_Duration_Played]
Meter=String
MeasureName=MeasureRemainingMinutes
MeasureName2=MeasureRemainingSeconds
MeasureName3=MeasureMinutesRemaining
MeasureName4=MeasureSecondsRemaining
X=(39*#Scale#)
;Y=(([M_ALBUM:Y]+(20*#Scale#)*#ConfigScale#))
Y=2
StringAlign=Center
SolidColor=0,0,0,1
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=10
Text="%1:%2 | %3:%4"
AntiAlias=1
DynamicVariables=1
Group=Progress Group

; ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The above code has 3 meters, I want to center the meter M_Bar in center - in relation to the remaining meters M_Duration_Played and M_Total_Duration. I can easily set the position more absolute in nature, but I wanted to test out ConfigScale, so, I decided not to put a fixed value here.

PS: I think this forum's subject should be Alignments - Relative to Other Meter instead of Centering relatively to other meter. Because this does not only teach about centering, but other alignments too.
User avatar
Yincognito
Rainmeter Sage
Posts: 7031
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Centering relatively to other meter

Post by Yincognito »

ZXCVBOT wrote: November 3rd, 2023, 11:46 amWhat's more, I can't understand why basic maths is not working out for this situation. Or even CurrentConfigWidth - althought this might be due to the fact the entire skin has been centered by use of this or by the meters being dynamic in nature.
Short answer:
Cause it's not proper math.

Long answer: I'm not going into your code too much, but you omitted an operator (the + I assume) towards the end of the X option from your M_Bar meter. Even so, the math is wrong, the above will not give you the position you expect. For the standard left aligned String meters, what you designed there can be represented on a piece of paper like this (SX = Skin X aka #CURRENTCONFIGX#, SW = Skin W aka #CURRENTCONFIGWIDTH#, M1X = M1's X, M1W = M1's W, M2X = M2's X, M2W = M2's W, with M1 and M2 the two meters in relation to which you want to center the M3 meter, and C the desired center):

Code: Select all

SX                  M1X          M1X+M1W                 M2X                      M2X+M2W           SX+SW
|--------------------|------M1------|---------------------|------------M2------------|----------------|
                     |-------------------------------C-------------------------------|
                                          |-----An M3 Meter-----|
It can be clearly seen from the schematics above that C is at the middle between M1X and M2X+M2W (so it's the difference of the reverse of this we want to divide by 2)... but we must add M1X to that as well. Thus, a simpleton code would look like this:

Code: Select all

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

[M1]
Meter=String
X=50
StringAlign=Left
;StringAlign=Center
;StringAlign=Right
Y=0r
AntiAlias=1
Text=A meter

[M2]
Meter=String
X=200
StringAlign=Left
;StringAlign=Center
;StringAlign=Right
Y=0r
AntiAlias=1
Text=A second meter

[M3]
Meter=String

;---Center this meter's contents in the X option and not in the StringAlign option---
; X=([M1:X]+([M2:X]+[M2:W]-[M1:X]-[M3:W])/2)
; StringAlign=Left

;---OR---

;---Center this meter's contents in the StringAlign option and not in the X option---
X=([M1:X]+([M2:X]+[M2:W]-[M1:X])/2)
StringAlign=Center

Y=20R
AntiAlias=1
Text=A centered meter
DynamicVariables=1
Interestingly, despite the fact that X doesn't represent the same visual point in regards to a meter's contents for different StringAlign values in a String meter, as explained here (which is why I left commented variants of those alignments to test out for M1 and M2), the formula for centering the M3 meter in its X option holds true regardless of the StringAlign in M1 and / or M2 (but not regardless of the StringAlign in M3, of course). :sly:
ZXCVBOT wrote: November 3rd, 2023, 11:46 amOr even CurrentConfigWidth - althought this might be due to the fact the entire skin has been centered by use of this or by the meters being dynamic in nature.
The above has no connection with centering the skin. The latter is done via !SetWindowPosition or the similar options from the said skin's section from the Rainmeter.ini file.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
ZXCVBOT

Re: Centering relatively to other meter

Post by ZXCVBOT »

Yincognito wrote: November 3rd, 2023, 7:12 pmEven so, the math is wrong, the above will not give you the position you expect. For the standard left aligned String meters, what you designed there can be represented on a piece of paper like this (SX = Skin X aka #CURRENTCONFIGX#, SW = Skin W aka #CURRENTCONFIGWIDTH#, M1X = M1's X, M1W = M1's W, M2X = M2's X, M2W = M2's W, with M1 and M2 the two meters in relation to which you want to center the M3 meter, and C the desired center):

Code: Select all

SX                  M1X          M1X+M1W                 M2X                      M2X+M2W           SX+SW
|--------------------|------M1------|---------------------|------------M2------------|----------------|
                     |-------------------------------C-------------------------------|
                                          |-----An M3 Meter-----|
It can be clearly seen from the schematics above that C is at the middle between M1X and M2X+M2W (so it's the difference of the reverse of this we want to divide by 2)... but we must add M1X to that as well.
Damn! I understood that clearly... Thanks for the diagram for making it clear.

Yincognito wrote: November 3rd, 2023, 7:12 pm X=([M1:X]+([M2:X]+[M2:W]-[M1:X]-[M3:W])/2)
How in the simple math problem did I miss this :-( . I tried doing one with sum of all meter X's and W's - M_Bar's W - That was the closest to this answer :rolmfao: - just a "-" would have prevented this thread pollution by me.....
  I think the meters name had something to with it :x . I found M1, M2, M3 part much more easy - maybe I really should take your earlier advice and use more "functional" names.  
Yincognito wrote: November 3rd, 2023, 7:12 pm Long answer: I'm not going into your code too much, but you omitted an operator (the + I assume) towards the end of the X option from your M_Bar meter.
Yeah, just noticed.

I always thought that doing a #CurrentConfigWidth#-[<SomeMeter>:W]/2 would put it in the center of the entire skin. Never thought it won't be helpful in some meter.
User avatar
Yincognito
Rainmeter Sage
Posts: 7031
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Centering relatively to other meter

Post by Yincognito »

ZXCVBOT wrote: November 4th, 2023, 9:53 am Damn! I understood that clearly... Thanks for the diagram for making it clear.



How in the simple math problem did I miss this :-( . I tried doing one with sum of all meter X's and W's - M_Bar's W - That was the closest to this answer :rolmfao: - just a "-" would have prevented this thread pollution by me.....
  I think the meters name had something to with it :x . I found M1, M2, M3 part much more easy - maybe I really should take your earlier advice and use more "functional" names.  

Yeah, just noticed.

I always thought that doing a #CurrentConfigWidth#-[<SomeMeter>:W]/2 would put it in the center of the entire skin. Never thought it won't be helpful in some meter.
No problem. It's not necessarily about giving meters a functional name, it's about simplifying the matter as much as you can when trying to solve a slightly more confusing issue. Math is essentially about numerical logic, so it's key to have a clear picture of the logic of it before using the said numbers. This can usually be tested in a simple skin or a piece of paper, before applying it to more complex environments like your actual skin.

That being said, there are other not so helpful things in your skin, like the not so logical order of meters in the code (e.g. you have the meter with the bigger X aka total duration before the one with the smaller X aka duration played, you reference a meter's Y aka duration played's Y in a preceding one aka total duration so before the former has the chance to update and receive its Y, etc). It's not that it's wrong per se, it's just that it doesn't make things as clear and functional as they could be.

Generally, clarity and efficiency are emphasized if you arrange meters in the code in a way that replicates the way they are arranged visually in the skin, e.g. from top to bottom and from left to right (similar with how you write text on a piece of paper), and from the ones "behind" to the ones "in front" (like drawing the farthest objects first and then overriding them with the nearest ones in a painting program) - you get the idea. The properties of a meter cannot possibly be known by another meter in the same update cycle if the latter is not AFTER the former in the code (i.e. if the former is not updated BEFORE the latter through either the placement in the code or some bangs forcing that regardless).
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
ZXCVBOT

Re: Centering relatively to other meter

Post by ZXCVBOT »

Wow! People still use paper?
Just kidding. I understand what you mean.

I've never noticed this in the main skin (mainly due to the low update rate), but, now that you mention that, I have seen it happen in a skin.
I'll remember "from top to bottom and from left to right". And now, I have much more work than I anticipated.

PS: Drawing is something that is not same for everyone (I won't get in too much details); I draw the subject/foreground first then, the background/non-essentials.
User avatar
Yincognito
Rainmeter Sage
Posts: 7031
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Centering relatively to other meter

Post by Yincognito »

ZXCVBOT wrote: November 4th, 2023, 1:47 pm I'll remember "from top to bottom and from left to right". And now, I have much more work than I anticipated.
This is not a rule set in stone (yep, people still use stone today, haha), just some guideline to make things clearer in the code.
ZXCVBOT wrote: November 4th, 2023, 1:47 pm I draw the subject/foreground first then, the background/non-essentials.
I know what you mean, though I referred more to a "layer by layer" kind of drawing. Like in Photoshop or GIMP, for example.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth