It is currently March 28th, 2024, 9:42 pm

Thread for help with the Shape meter

Get help with creating, editing & fixing problems with skins
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Thread for help with the new Shape meter

Post by jsmorley »

FreeRaider wrote:In the manual, under path shape, I have noticed there is a CloseShape parameter, but it is wrong as it should be ClosePath.
Outstanding catch. Fixed. Thanks for reporting.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Thread for help with the new Shape meter

Post by jsmorley »

A note on ClosePath

At its core the purpose of the ClosePath (0/1) parameter on a Path shape is to automatically "close" an open path. This has the benefit of allowing you (if desired) to just leave off the last "segment" of the path definition, and let Rainmeter figure it out for you.

However, there can be one other subtle but important purpose for using ClosePath 1 on your path shapes. Let me demonstrate:

Code: Select all

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

[MeterShape]
Meter=Shape
X=10
Y=10
Shape=Path MyPath | StrokeWidth 15 | Stroke Color 41,4,2,255 | Fill Color 87,149,212,255 | StrokeLineJoin Round
MyPath=0,0 | LineTo 200,0 | ArcTo 200,100 | CurveTo 0,0,100,100
So we start at 0,0 and end at 0.0. That's "closed" right? Well, no, it isn't. Simply ending at the starting point does not in and of itself create a closed shape. For instance, you won't get any default fill color on the shape.

So, let's look at the result. I used a big StrokeWidth in order to more clearly see what is going on:
1.jpg
You will notice that the starting and ending points don't quite "join up" the way you might like. This is due to the fact that in this case the path has additional "outside stroke" on the top and bottom of a segment, but not on the "ends". So while the paths that define the "shape" end up at the same point, the "strokes" don't quite line up in a pleasing way.

Easy to fix:

Code: Select all

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

[MeterShape]
Meter=Shape
X=10
Y=10
Shape=Path MyPath | StrokeWidth 15 | Stroke Color 41,4,2,255 | Fill Color 87,149,212,255 | StrokeLineJoin Round
MyPath=0,0 | LineTo 200,0 | ArcTo 200,100 | CurveTo 0,0,100,100 | ClosePath 1
2.jpg
As you can see, ClosePath will force a properly "closed" shape, including any stroke used.
You do not have the required permissions to view the files attached to this post.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Thread for help with the new Shape meter

Post by jsmorley »

A Note on StrokeLineJoin

The StrokeLineJoin attribute modifier is used to determine what kind of "join" or "corner" you want for the stroke when your shape has "segments" that create an angle.

https://docs.rainmeter.net/manual-beta/meters/shape/#StrokeLineJoin

Let me demonstrate:

Code: Select all

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

[MeterShape]
Meter=Shape
X=20
Y=20
Shape=Path MyPath | StrokeWidth 10 | Stroke Color 41,4,2,255 | Fill LinearGradient MyGradient | StrokeLineJoin Miter
MyPath=0,50 | LineTo 300,0 | ArcTo 300,100 | LineTo 0,50 | ClosePath 1
MyGradient=180 | 247,243,116 ; 0.0 | 158,57,57 ; 1.0
1.jpg
This is with the default value of StrokeLineJoin of Miter. While it works great, and may be just what you want, you will note that where the path comes to a "point" at the left needs a lot of length in order to "miter" that sharp angle. The larger the StrokeWidth is on your shape, the more pronounced this will appear.

So let's look at some alternatives:

Code: Select all

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

[MeterShape]
Meter=Shape
X=20
Y=20
Shape=Path MyPath | StrokeWidth 10 | Stroke Color 41,4,2,255 | Fill LinearGradient MyGradient | StrokeLineJoin Bevel
MyPath=0,50 | LineTo 300,0 | ArcTo 300,100 | LineTo 0,50 | ClosePath 1
MyGradient=180 | 247,243,116 ; 0.0 | 158,57,57 ; 1.0
2.jpg
With StrokeLineJoin set to Bevel, you get a shorter, and somewhat more "squared off" end to the point.

Code: Select all

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

[MeterShape]
Meter=Shape
X=20
Y=20
Shape=Path MyPath | StrokeWidth 10 | Stroke Color 41,4,2,255 | Fill LinearGradient MyGradient | StrokeLineJoin Round
MyPath=0,50 | LineTo 300,0 | ArcTo 300,100 | LineTo 0,50 | ClosePath 1
MyGradient=180 | 247,243,116 ; 0.0 | 158,57,57 ; 1.0
3.jpg
With StrokeLineJoin set to Round, you get a somewhat shorter, and "rounded" end to the point.

Entirely up to you what effect you are going for, but just be aware that you have a fair amount of control over this.
You do not have the required permissions to view the files attached to this post.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Using Rotate to "Orbit" a shape

Post by jsmorley »

Using Rotate to "orbit" a shape.

One of the things you might want to do is "orbit" a shape around another shape. This is not hard at all to do, using the Rotate Transform Modifier on your shape.

Code: Select all

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

[Variables]
ScaleFactor=1.0

[MeasureRotate]
Measure=Loop
StartValue=0
EndValue=359
Increment=3

[MeterSunAndEarth]
Meter=Shape
W=(152 * #ScaleFactor#)
H=(152 * #ScaleFactor#)
X=(52 * #ScaleFactor#)
Y=(52 * #ScaleFactor#)
Shape=Ellipse 50,50,50 | StrokeWidth 0 | Fill RadialGradient SunGrad
SunGrad=0,0 | 252,239,151,255 ; 0.0 | 171,43,43,255 ; 1.5
Shape2=Ellipse 110,110,15 | StrokeWidth 0 | Fill RadialGradient EarthGrad | Rotate [MeasureRotate], -45, -45
EarthGrad=0,0,-20,-20,30,30 | 200,226,250,255 ; 0.0 | 36,93,145,255 ; 1.0
DynamicVariables=1
TransformationMatrix=#ScaleFactor#;0;0;#ScaleFactor#;0;0
GIF.gif
So the trick is to imagine a line, a "connecting rod" drawn from the center of the static shape (the sun in this case) to the center of the moving shape (the earth in this case).

Then you want to rotate the moving shape, using an anchor based on the distance from the ending point of that imaginary line back to the start of it. Back to the center of the static shape. The goal is to rotate around the center of the static shape.

That is going to be a formula like this:

Rotate degree, (CenterBigX - CenterSmallX + CenterSmallRadiusX), (CenterBigY - CenterSmallY + CenterSmallRadiusY)

So in this example, we arrive at -45 as the X and Y anchors.
50 - 110 + 15 = -45

A note on scaling with TransformationMatrix:

Remember that TransformmationMatrix does not change the size of the meter, only the contents, and so DynamicWindowSize won't be effective when you scale up a shape meter with TransformationMatrix. You need to dynamically set the meter size large enough, so DynamicWindowSize can enlarge the overall skin as needed.
You do not have the required permissions to view the files attached to this post.
User avatar
rbriddickk84
Rainmeter Sage
Posts: 276
Joined: February 17th, 2014, 12:39 pm
Location: Hungary

Re: Using Rotate to "Orbit" a shape

Post by rbriddickk84 »

jsmorley wrote:Using Rotate to "orbit" a shape.
You guys are unbelievable! Keep up the awesome work!! :D
User avatar
ikarus1969
Posts: 571
Joined: February 28th, 2011, 3:20 pm
Location: Vienna, Austria

Re: Thread for help with the new Shape meter

Post by ikarus1969 »

Hi!

I have some difficulties to integrate shapes in existing skins. Altough it's of course possible in the usual ways to position a meter related to a shape using its width and height that's not so easy when i want to use the shapes x- and y-position.

i made a simple test-skin to demonstrate: i wanted to position the second text related to the top left corner of the shape with an offset of (50, 50)

Code: Select all

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

[Meter_Text_before_shape]
Meter=STRING
Text="Text before Shape"
X=#WORKAREAX#
Y=#WORKAREAY#
InlineSetting=Face | Arial
InlineSetting2=Size | 24
InlineSetting3=Color | 004080FF
InlineSetting4=Weight | 600
SolidColor=00000040
AntiAlias=1
DynamicVariables=1

[Meter_Shape]
Meter=SHAPE
Shape=Ellipse ([Meter_Text_before_shape:X] + 0.5 * [Meter_Text_before_shape:W] + 60), ([Meter_Text_before_shape:Y] + [Meter_Text_before_shape:H] + 40), 60, 40 | StrokeWidth 2 | Fill Color 008000FF
SolidColor=FF8000C0
DynamicVariables=1

[Meter_Text_after_shape]
Meter=STRING
Text="Text after Shape"
; X=([Meter_Shape:X] + 50)
; Y=([Meter_Shape:Y] + 50)
X=([Meter_Shape:X] + [Meter_Shape:W] - 2 * 60 + 50)
Y=([Meter_Shape:Y] + [Meter_Shape:H] - 2 * 40 + 50)
InlineSetting=Face | Arial
InlineSetting2=Size | 24
InlineSetting3=Color | 004080FF
InlineSetting4=Weight | 600
SolidColor=00000040
AntiAlias=1
DynamicVariables=1
That is what happened - SolidColor shows why:
Screenshot Rainmeter - shape positioning #1.jpg
On this simple and very basic shape i can use a workaround and then i will get what i intended:
Screenshot Rainmeter - shape positioning #2.jpg
On simple shapes like ellipse, rectangle or line this would help a little bit but on combined shapes or when i use the Path-feature i am completely lost when i don't have static shapes (where i can follow some trial and error to get the right values for offset).

Can you image some way, some "scary math" to get the "real" top-left corner of a shape or even (i hardly dare to ask) to integrate that in rainmeter?

I somewhat can remember from my time in school (long time ago) something called "konexe Hülle" which translates to "convex casing" or "convex wrapper" which possibly can be used for calculating the top and/or left corner of a shape but i admit that's completely out of the bounds my math is in... :confused:
You do not have the required permissions to view the files attached to this post.
User avatar
FreeRaider
Posts: 826
Joined: November 20th, 2012, 11:58 pm

Re: Thread for help with the new Shape meter

Post by FreeRaider »

This is one of the reasons why I do not like this new meter.

I would have preferred a meter that uses the same method of reasoning (for example as it is used Roundline) of the others, with the numerical certainty of "Where it starts, where it ends, the starting position X and Y" and especially StrokeWidth used as the border of the geometric figure included totally in it.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Thread for help with the new Shape meter

Post by jsmorley »

Given the nature of how the geometry of shapes work, it does take a little thought when you are designing your skin, but I really do think it can make sense once you wrap you head around it.

Let's look at how to consider all this:

Rule 1 : A meter can and will expand as needed to the right and down to hold the entire shape, including any stroke. A meter can NEVER expand to the top and left. X and Y define the "top left" corner of both skins and meters. Skins and meters are always drawn from there down and right. That's just a fact of life. That can't possibly be changed.

First let's draw a 200 X 200 Ellipse:

Code: Select all

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

[MeterEllipse]
Meter=Shape
Shape=Ellipse 0,0,100 | Extend Attrib
Attrib=StrokeWidth 1 | Fill Color 255,255,255,255
1.png
Whoa... That doesn't look right does it. Ah, see an Ellipse is drawn from the "center out" in all directions. So the top and left are being drawn "outside the skin" and thus truncated.

Let's fix that. We can set the X and Y of the meter to 100 and we are good, right?

Code: Select all

[MeterEllipse]
Meter=Shape
X=100
Y=100
Shape=Ellipse 0,0,100 | Extend Attrib
Attrib=StrokeWidth 1 | Fill Color 255,255,255,255
2.png
Well, yes and no. The size of the "shape" is 200 x 200, That's what we want, and that's what we get. However any "stroke" on the shape is not part of that size. You want a 200 x 200 circle, you got it. The size of the "pen tip" you use to draw the circle has nothing to do with it. A stroke is NOT, NOT a "border". So although it may be hard to see, the 1/2 of the stroke that is "outside" the defined size of the shape is truncated. Just on the top and left.

Anyway, we can fix that too:

Code: Select all

[MeterEllipse]
Meter=Shape
X=101
Y=101
Shape=Ellipse 0,0,100 | Extend Attrib
Attrib=StrokeWidth 1 | Fill Color 255,255,255,255
3.png
So we added 1/2 the StokeWidth (rounded up to an integer) to the X and Y, and we get exactly what we expect.

We can do the same thing by setting the "starting point" of the shape as well, while leaving the X and the Y of the meter as "0":

Code: Select all

[MeterEllipse]
Meter=Shape
X=0
Y=0
Shape=Ellipse 101,101,100 | Extend Attrib
Attrib=StrokeWidth 1 | Fill Color 255,255,255,255
3.png
Exactly the same result.

So what if we increase the StrokeWidth:

Code: Select all

[MeterEllipse]
Meter=Shape
X=0
Y=0
Shape=Ellipse 101,101,100 | Extend Attrib
Attrib=StrokeWidth 6 | Fill Color 255,255,255,255
4.png
Not good. We need to account for 1/2 the StrokeWidth, rounded up to an integer.

So we can:

Code: Select all

[MeterEllipse]
Meter=Shape
X=0
Y=0
Shape=Ellipse 103,103,100 | Extend Attrib
Attrib=StrokeWidth 6 | Fill Color 255,255,255,255
5.png
Or:

Code: Select all

[MeterEllipse]
Meter=Shape
X=103
Y=103
Shape=Ellipse 0,0,100 | Extend Attrib
Attrib=StrokeWidth 6 | Fill Color 255,255,255,255
5.png
Same thing..

So it seems to me that as long as you consider the geometry of your shape, and any impact Rotate, Scale, Skew has on them, and factor in 1/2 the StrokeWidth rounded up to an integer, you can end up being able to set other meters relative to this one just fine. It's not as straightforward as a String meter perhaps, but this is nothing like a String meter. A String meter can never be drawn from the "staring point" either up or left. A shape in a shape meter can, and very often will. Ellipses, Arcs, Curves, and Paths, as well as Rotate, Scale and Skew, can all cause that.
You do not have the required permissions to view the files attached to this post.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Thread for help with the new Shape meter

Post by jsmorley »

I don't know how best to stress that StrokeWidth can never just be part of the size of the shape. That just doesn't make sense.

Consider this analogy.

The border between the US and Mexico. How wide is it? The answer is zero. The two countries "abut", there is no width to the border between them.

That is a StrokeWidth of 0. See?

Now you want to draw that border on a map. No matter how sharp a pencil you use, the "line" you draw will have some width. The width of the tip of the pencil. The StrokeWidth. Does that make either the US or Mexico "smaller", Of course not. The size of the US and Mexico are exactly the same as they always were, you just measure them from the "center" of that stroke. Half the stroke is in Mexico, and half is in the US. Half is "inside" the US and half if "outside" the US.

If you consider StrokeWidth to be a "border around your shape", you will never get this... ;-)
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Thread for help with the new Shape meter

Post by jsmorley »

I think I understand the issue the original poster is having, but I don't see any way to get there from here.

Things like X=10r or X=([MeterName:X] + 10) are based on the "meter", not the shape. If we look at our shape above:
5.png
We can know the X and Y of the meter, but what is the X and Y of the "shape"? That has no meaning. An Ellipse is based on "center and radius", not "top left and width and height". There just is no sensible definition of X and Y for that shape. I mean there is, but it's the center of the ellipse.

So while you can certainly make another meter "relative" to a shape's "meter" pretty readily, I'm not sure there is anything but "trial and error" that can help with making another meter relative to the "shape".
You do not have the required permissions to view the files attached to this post.