balala wrote: ↑May 31st, 2023, 8:27 pmPlain Rainmeter code would be much more nice in my opinion. Anyway I need time to study how this can be implemented. But unfortunately, now that summer came, I have extremely little time. But let's see, sooner or later I hope I'm gonna try this out.

Take your time. In case it helps, I already done it, via my string manipulation method in plain Rainmeter...

**Code**:

Code: Select all

```
; Reference: https://apoorvaj.io/cubic-bezier-through-four-points/
[Variables]
BGSize=600
Style0=Lines
Style1=Curve
Style=0
IdxMx=5
Index=0
Points0=((200)),((300));300,100;400,300;300,500;200,300;300,100;((400)),((300));
Points1=((65*1-1)),((26*5));(65*1),(26*5);(65*2),(19*5);(65*3),(16*5);(65*4),(18*5);((65*4+1)),((18*5));
Points2=((65*1-1)),((13*5));(65*1),(13*5);(65*2),(8*5);(65*3),(11*5);(65*4),(13*5);((65*4+1)),((13*5));
Points3=((65*1-1)),((25*5));(65*1),(25*5);(65*2),(27*5);(65*3),(27*5);(65*4),(20*5);((65*4+1)),(20*5);
Points4=((65*1-1)),((12*5));(65*1),(12*5);(65*2),(14*5);(65*3),(13*5);(65*4),(9*5);((65*4+1)),((9*5));
Alpha=0.5
[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
---Measures---
[PathL]
Group=PathGroup
Measure=String
String=[#Points[#Index]]
UpdateDivider=-1
RegExpSubstitute=1
Substitute="(?U)(.*),(.*);":" | LineTo \1,\2","^ [|] LineTo ":""
DynamicVariables=1
[PathC]
Group=PathGroup
Measure=String
String=[#Points[#Index]]
UpdateDivider=-1
RegExpSubstitute=1
Substitute="(?U)(.*),(.*);(?=(.*),(.*);(.*),(.*);(.*),(.*);)":"PointAt \3,\4 | CurveTo \5,\6,(((Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)**2*\5-(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2*\1+(2*(Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)**2+3*(Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)*(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2)*\3)/(3*(Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)*((Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)))),(((Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)**2*\6-(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2*\2+(2*(Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)**2+3*(Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)*(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2)*\4)/(3*(Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)*((Sqrt((\3-\1)**2+(\4-\2)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)))),(((Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)**2*\3-(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2*\7+(2*(Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)**2+3*(Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)*(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2)*\5)/(3*(Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)*((Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)))),(((Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)**2*\4-(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2*\8+(2*(Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)**2+3*(Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)*(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)**2)*\6)/(3*(Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)*((Sqrt((\7-\5)**2+(\8-\6)**2)**#Alpha#)+(Sqrt((\5-\3)**2+(\6-\4)**2)**#Alpha#)))) | ","^PointAt (.*) [|].*$":"\1","(?U)PointAt .* [|] ":"","(?:^\\\d+|\\\d+$)":""
DynamicVariables=1
---Meters---
[Background]
Meter=Shape
Shape=Rectangle 0,0,#BGSize#,#BGSize# | StrokeWidth 0 | Stroke Color 0,0,0,0 | Fill Color 0,0,0,128
UpdateDivider=-1
MouseScrollUpAction=[!SetVariable Index ((#IdxMx#+#Index#-1)%#IdxMx#)][!UpdateMeasure *][!UpdateMeter *][!Redraw]
MouseScrollDownAction=[!SetVariable Index ((#IdxMx#+#Index#+1)%#IdxMx#)][!UpdateMeasure *][!UpdateMeter *][!Redraw]
LeftMouseUpAction=[!SetVariable Style (1-#Style#)][!ToggleMeter GraphLines][!ToggleMeter GraphCurve][!UpdateMeasure *][!UpdateMeter *][!Redraw]
DynamicVariables=1
[GraphLines]
Meter=Shape
Shape=Path PathL | StrokeWidth 2 | Stroke Color 0,255,0,255 | Fill Color 87,149,212,0
PathL=[PathL]
UpdateDivider=-1
DynamicVariables=1
[GraphCurve]
Hidden=1
Meter=Shape
Shape=Path PathC | StrokeWidth 2 | Stroke Color 0,255,0,255 | Fill Color 87,149,212,0
PathC=[PathC]
UpdateDivider=-1
DynamicVariables=1
[Info]
Meter=String
X=#BGSize#
Y=#BGSize#
SolidColor=0,0,0,1
FontColor=255,255,255,255
FontEffectColor=0,0,0,255
StringEffect=Shadow
StringAlign=RightBottom
FontFace=Consolas
FontSize=16
AntiAlias=1
Text=Graph: No. #Index##CRLF#Style: [#Style[#Style]]
UpdateDivider=-1
DynamicVariables=1
```

**Preview**:

ezgif.com-optimize.gif

I included more examples / graphs (both "open" and "closed" visually) to better see the effects - you can scroll through them with the mouse wheel and click to toggle between lines and curve styles for the graph. The set of points is defined as an "X1,Y1;X2,Y2;..." virtually unlimited list, which is then converted to strings of either line or curve paths in the two measures, to be used in the two graph meters to display the results, along with some short info for conveniency. As expected, since a cubic Bezier curve needs at least 4 points to compute the control points for the 2 points in the middle, the set of points need two "fake" / "phantom" points at the beginning and end of the set in order to have the graph extend to its "real" / "actual" beginning and end - I marked them by enclosing them in double round brackets in [Variables], for better awareness of the principle (e.g. if you want to graph between P1 and P7, you need to create proper P0 and P8 along the desired path).

In your case (or any case except this "showcase" one, for that matter), only the [PathC] measure and [GraphCurve] meter equivalents are needed, assuming you set the String option of the former to the desired comma (,) and semicolon (;) separated list of points and add the "phantom" points at the beggining and end of the list by simply duplicating the actual beginning and end points and subtracting or adding 1 to one of the coordinates, respectively, like illustrated in [Variables]. I could have automated this in the Substitute, of course, but the thing is that for other cases (like my rhombus, intended to show that any closed plygon can be similarly smoothed and curved) the machine cannot anticipate the proper position for the phantom points because they depend on what the user wants the shape to look like (e.g. for the "closed" rhombus I had to continue the "enclosing" of the shape to get the egg / ellipse like shape, otherwise it would have turned into a raindrop like shape).

Feel free to use this if you want. Obviously, it can be done via formulas entered manually in the Path option, but considering the length such a formula can have in plain Rainmeter, the automated version - itself using a very simple but very long Substitute, is the better choice IMHO, since you don't need to write it anymore, just enter the points and stuff gets done. The Lua choice helps in writing less too, but of course, why bother when it can be all done in a single String measure with zero effort (at least from anyone else but me, lol).

You do not have the required permissions to view the files attached to this post.