It is currently April 19th, 2024, 10:46 pm

ActionSlideClock

Clocks and timer skins
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

ActionSlideClock

Post by jsmorley »

ActionSlideClock_2.0.rmskin
test.gif
Requires the Rainmeter 3.3 beta or better from http://rainmeter.net.
Simply change [MeasureHours] to Format=%H for a 24-hour clock instead of 12-hour.

Code: Select all

[Rainmeter]
Update=50
DynamicWindowSize=1
AccurateText=1
SkinHeight=45
OnRefreshAction=[!SetVariable CurrentHours "[MeasureHours]"][!SetVariable CurrentMinutes "[MeasureMinutes]"][!SetVariable CurrentSeconds "[MeasureSeconds]"][!UpdateMeter *][!Redraw]

[Variables]
LinesColor=0,0,0,255
NumberColor=255,255,255,255
BackColor=19,43,77,255
CurrentHoursY=2
NewHoursY=-40
CurrentMinutesY=2
NewMinutesY=-40
CurrentSecondsY=2
NewSecondsY=-40
U=[!UpdateMeasureGroup Sliders][!UpdateMeterGroup Numbers][!Redraw]

[MeasureHours]
Measure=Time
Format=%I
OnChangeAction=[!CommandMeasure HoursSlide "Execute 1"]

[MeasureMinutes]
Measure=Time
Format=%M
OnChangeAction=[!CommandMeasure MinutesSlide "Execute 1"]

[MeasureSeconds]
Measure=Time
Format=%S
OnChangeAction=[!CommandMeasure SecondsSlide "Execute 1"]

[HoursSlide]
Measure=Plugin
Plugin=ActionTimer
Group=Sliders
IgnoreWarnings=1
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 20, 21 | Wait 1| SwapThem
SetThem=[!SetVariable CurrentHoursY "2"][!SetVariable NewHoursY "-40"]#U#
SlideThem=[!SetVariable CurrentHoursY "(Clamp(#CurrentHoursY#+2,2,45))"][!SetVariable NewHoursY "(Clamp(#NewHoursY#+2,-40,2))"]#U#
SwapThem=[!SetVariable CurrentHoursY "2"][!SetVariable NewHoursY "-40][!SetVariable CurrentHours "[MeasureHours]"]#U#
DynamicVariables=1

[MinutesSlide]
Measure=Plugin
Plugin=ActionTimer
Group=Sliders
IgnoreWarnings=1
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 20, 21 | Wait 1| SwapThem
SetThem=[!SetVariable CurrentMinutesY "2"][!SetVariable NewMinutesY "-40"]#U#
SlideThem=[!SetVariable CurrentMinutesY "(Clamp(#CurrentMinutesY#+2,2,45))"][!SetVariable NewMinutesY "(Clamp(#NewMinutesY#+2,-40,2))"]#U#
SwapThem=[!SetVariable CurrentMinutesY "2"][!SetVariable NewMinutesY "-40][!SetVariable CurrentMinutes "[MeasureMinutes]"]#U#
DynamicVariables=1

[SecondsSlide]
Measure=Plugin
Plugin=ActionTimer
Group=Sliders
IgnoreWarnings=1
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 20, 21 | Wait 1| SwapThem
SetThem=[!SetVariable CurrentSecondsY "2"][!SetVariable NewSecondsY "-40"]#U#
SlideThem=[!SetVariable CurrentSecondsY "(Clamp(#CurrentSecondsY#+2,2,45))"][!SetVariable NewSecondsY "(Clamp(#NewSecondsY#+2,-40,2))"]#U#
SwapThem=[!SetVariable CurrentSecondsY "2"][!SetVariable NewSecondsY "-40][!SetVariable CurrentSeconds "[MeasureSeconds]"]#U#
DynamicVariables=1

[MeterNewHours]
Meter=String
Group=Numbers
MeasureName=MeasureHours
W=30
H=32
X=22
Y=#NewHoursY#
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCurrentHours]
Meter=String
Group=Numbers
W=30
H=32
X=22
Y=#CurrentHoursY#
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
Text=#CurrentHours#
UpdateDivider=-1
DynamicVariables=1

[MeterNewMinutes]
Meter=String
Group=Numbers
MeasureName=MeasureMinutes
W=30
X=64
Y=#NewMinutesY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCurrentMinutes]
Meter=String
Group=Numbers
MeasureName=MeasureMinutes
W=30
X=64
Y=#CurrentMinutesY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
Text=#CurrentMinutes#
UpdateDivider=-1
DynamicVariables=1

[MeterNewSeconds]
Meter=String
Group=Numbers
MeasureName=MeasureSeconds
W=30
X=106
Y=#NewSecondsY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCurrentSeconds]
Meter=String
Group=Numbers
W=30
X=106
Y=#CurrentSecondsY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
Text=#CurrentSeconds#
UpdateDivider=-1
DynamicVariables=1

[MeterTopLine]
Meter=Image
X=0
Y=0
H=2
W=128
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterLeftLine]
Meter=Image
X=0
Y=0
H=43
W=2
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterMidLine1]
Meter=Image
X=42
Y=2
W=2
H=41
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterMidLine2]
Meter=Image
X=84
Y=2
W=2
H=41
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterRightLine]
Meter=Image
X=126
Y=0
H=43
W=2
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterBottomLine]
Meter=Image
X=0
Y=43
H=2
W=128
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1
You do not have the required permissions to view the files attached to this post.
Milamber33
Posts: 12
Joined: October 31st, 2015, 6:30 pm

Re: ActionSlideClock

Post by Milamber33 »

Hi jsmorley, I was having a look at this clock, and for me, if I just used it as posted, the transitions went really really fast, blink and you'd miss it. This was happening for both the AM/PM version and the seconds version. I had to edit the ActionList lines to make the transition slower, as follows:

Code: Select all

; Original line, was going lightning fast for me.
; ActionList1=SetThem | Wait 1 | Repeat SlideThem, 1, 21 | Wait 1| SwapThem

; Edited line, slower transition
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 7, 21 | Wait 1| SwapThem
I chose the value of 7 for the SlideThem command as it's a bit faster (for me) than the preview in your post, but still looks good IMO. I've also tried this on the Seconds version and haven't seen the issue you describe.
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ActionSlideClock

Post by jsmorley »

Milamber33 wrote:Hi jsmorley, I was having a look at this clock, and for me, if I just used it as posted, the transitions went really really fast, blink and you'd miss it. This was happening for both the AM/PM version and the seconds version. I had to edit the ActionList lines to make the transition slower, as follows:

Code: Select all

; Original line, was going lightning fast for me.
; ActionList1=SetThem | Wait 1 | Repeat SlideThem, 1, 21 | Wait 1| SwapThem

; Edited line, slower transition
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 7, 21 | Wait 1| SwapThem
I chose the value of 7 for the SlideThem command as it's a bit faster (for me) than the preview in your post, but still looks good IMO. I've also tried this on the Seconds version and haven't seen the issue you describe.
I think the difference between 1ms and 7ms delay between each action is not terribly significant. I don't see a huge difference either way really. What I do see is that if the seconds change, and the transition has time to entirely complete before the next change of the seconds, then it works well. However sooner or later, the difference between the elapsed time of the transition, which is not exact, due to differences in the speed of your computer and the load on Rainmeter at any given time, and the "ticking" of the actual computer clock, cause the change to the seconds to happen in the middle of the transition. As long as this is true, it will then "interrupt" the current transition, setting the most current values, and then attempt to start over. This causes a "jerkiness", where for some number of seconds the transition happens much faster than it should.

Changing the approach so that a conflict causes a transition to be "skipped" instead of it interrupting the current one is one idea, but it has its own ugliness. Having a clock that sits on "12" too long, and then skips to "14" isn't any better.

The problem is that the Time measure is precise, but limited to a granularity of one-second. It's not "tracking" the current time, but simply "reporting" on it when asked. It will always be correct, but when it says "12" seconds, the real time might be anywhere between 12 and 13, which in computer terms is a long time. On the other hand, any transition that you do simply can't be precise. You just can't create a transition that always takes exactly one-second, and any difference, if for instance the transition takes 9/10th of a second, will cause a "difference creep" between them that will sooner or later cause conflict. Having a low Update rate on the skin seems to help "some", as you are asking for the time much more often. It doesn't really solve the problem though, just somewhat reduces the likelihood of it occurring.

What is really needed is a transition that is entirely driven by the clock. That would require a Time measure that has a granularity greater than one-second, a clock that can return milliseconds. Then in theory, you don't even need ActionTimer. You just drive the transition directly with OnChangeAction on the milliseconds. That, as far as I know, is just not possible, or at least practical, in the Rainmeter design.

As I said, I'm not sure there is a reliable solution. If you have a transition that is driven by a value like "seconds", sooner or later you are going to have this issue. It can be reduced by making the transition really fast, so the odds are greater that you won't get into a conflict, (or more to the actual point that the conflict is much, much less visibly jarring) but there comes a point where the visual effect of the transition is so fast it is not terribly valuable.

That is not to say that there isn't some flaw in my logic, or that there isn't some clever way to work around this, I just don't see it yet myself. Maybe something where what is displayed are both "saved values" and the clock is always one second behind the real clock time. Then you don't base the transition on OnChangeAction on the time measure, but base it on the "more or less one second" behavior of Update=1000 in the skin. Not sure this really helps. Somewhere you simply are going to have to have OnChangeAction play some role. I'll have to explore it.

---------------

This skin does something similar, but if you look at it, I "cheat". This is not a real transition from the "old" value to the "new" value. What it does is just instantly hide the "old" value, then change to the "new" value and fade that in. So due at least in part to the "persistence of vision", you get the appearance of a stable, reliable transition between the two, but it's really just half a transition. There is never a need to "interrupt" the transition, at worst you might "start it sooner". That isn't going to work with the flip-clock idea...

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
OnRefreshAction=[!CommandMeasure MeasureFadeTime "Execute 1"][!CommandMeasure MeasureFadeTime "Execute 2"][!CommandMeasure MeasureFadeTime "Execute 3"]

[Variables]
W=20
U=[!UpdateMeasureGroup Faders][!UpdateMeterGroup Faders][!Redraw]
MinuteAlpha=255
HourAlpha=255

[MeasureHour]
Measure=Time
Format=%#I
OnChangeAction=[!CommandMeasure MeasureFadeTime "Execute 1"]

[MeasureMinute]
Measure=Time
Format=%M
OnChangeAction=[!CommandMeasure MeasureFadeTime "Execute 2"]

[MeasureSecond]
Measure=Time
Format=%S
OnChangeAction=[!CommandMeasure MeasureFadeTime "Execute 3"]

[MeasureAMPM]
Measure=Time
Format=%p

[MeasureFadeTime]
Measure=Plugin
Plugin=ActionTimer
Group=Faders
; Hours
ActionList1=SetHoursTo1|Wait #W#|Repeat SetHoursCalc, #W#, 13
SetHoursTo1=[!SetVariable HourAlpha "1"]#U#
SetHoursCalc=[!SetVariable HourAlpha "(Min(#HourAlpha#+20,255))"]#U#
; Minutes
ActionList2=SetMinutesTo1|Wait #W#|Repeat SetMinutesCalc, #W#, 13
SetMinutesTo1=[!SetVariable MinuteAlpha "1"]#U#
SetMinutesCalc=[!SetVariable MinuteAlpha "(Min(#MinuteAlpha#+20,255))"]#U#
; Seconds
ActionList3=SetSecondsTo1|Wait #W#|Repeat SetSecondsCalc, #W#, 13
SetSecondsTo1=[!SetVariable SecondAlpha "1"]#U#
SetSecondsCalc=[!SetVariable SecondAlpha "(Min(#SecondAlpha#+20,255))"]#U#
DynamicVariables=1

[MeterHour]
Meter=String
MeasureName=MeasureHour
Group=Faders
FontSize=70
FontColor=255,255,255,#HourAlpha#
SolidColor=0,0,0,1
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterColon]
Meter=String
X=R
FontSize=70
FontColor=255,255,255,255
SolidColor=0,0,0,1
AntiAlias=1
Text=:

[MeterMinute]
Meter=String
MeasureName=MeasureMinute
Group=Faders
X=R
FontSize=70
FontColor=255,255,255,#MinuteAlpha#
SolidColor=0,0,0,1
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterAMPM]
Meter=String
MeasureName=MeasureAMPM
X=42R
Y=13
FontSize=15
FontColor=255,255,255,255
SolidColor=0,0,0,1
AntiAlias=1

[MeterSecond]
Meter=String
MeasureName=MeasureSecond
Group=Faders
X=-31r
Y=31
FontSize=44
FontColor=255,255,255,#SecondAlpha#
SolidColor=0,0,0,1
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCounter]
Meter=String
MeasureName=MeasureCounter
X=0
Y=10R
FontSize=30
FontColor=255,255,255,255
SolidColor=0,0,0,1
AntiAlias=1
test.gif
You do not have the required permissions to view the files attached to this post.
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ActionSlideClock

Post by jsmorley »

Actually, I think this works quite a bit better:

Code: Select all

[Rainmeter]
Update=50
DynamicWindowSize=1
AccurateText=1
SkinHeight=45
OnRefreshAction=[!SetVariable CurrentHours "[MeasureHours]"][!SetVariable CurrentMinutes "[MeasureMinutes]"][!SetVariable CurrentSeconds "[MeasureSeconds]"][!UpdateMeter *][!Redraw]

[Variables]
LinesColor=0,0,0,255
NumberColor=255,255,255,255
BackColor=19,43,77,255
CurrentHoursY=2
NewHoursY=-40
CurrentMinutesY=2
NewMinutesY=-40
CurrentSecondsY=2
NewSecondsY=-40
U=[!UpdateMeasureGroup Sliders][!UpdateMeterGroup Numbers][!Redraw]

[MeasureHours]
Measure=Time
Format=%I
OnChangeAction=[!CommandMeasure HoursSlide "Execute 1"]

[MeasureMinutes]
Measure=Time
Format=%M
OnChangeAction=[!CommandMeasure MinutesSlide "Execute 1"]

[MeasureSeconds]
Measure=Time
Format=%S
OnChangeAction=[!CommandMeasure SecondsSlide "Execute 1"]

[HoursSlide]
Measure=Plugin
Plugin=ActionTimer
Group=Sliders
IgnoreWarnings=1
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 20, 21 | Wait 1| SwapThem
SetThem=[!SetVariable CurrentHoursY "2"][!SetVariable NewHoursY "-40"]#U#
SlideThem=[!SetVariable CurrentHoursY "(Clamp(#CurrentHoursY#+2,2,45))"][!SetVariable NewHoursY "(Clamp(#NewHoursY#+2,-40,2))"]#U#
SwapThem=[!SetVariable CurrentHoursY "2"][!SetVariable NewHoursY "-40][!SetVariable CurrentHours "[MeasureHours]"]#U#
DynamicVariables=1

[MinutesSlide]
Measure=Plugin
Plugin=ActionTimer
Group=Sliders
IgnoreWarnings=1
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 20, 21 | Wait 1| SwapThem
SetThem=[!SetVariable CurrentMinutesY "2"][!SetVariable NewMinutesY "-40"]#U#
SlideThem=[!SetVariable CurrentMinutesY "(Clamp(#CurrentMinutesY#+2,2,45))"][!SetVariable NewMinutesY "(Clamp(#NewMinutesY#+2,-40,2))"]#U#
SwapThem=[!SetVariable CurrentMinutesY "2"][!SetVariable NewMinutesY "-40][!SetVariable CurrentMinutes "[MeasureMinutes]"]#U#
DynamicVariables=1

[SecondsSlide]
Measure=Plugin
Plugin=ActionTimer
Group=Sliders
IgnoreWarnings=1
ActionList1=SetThem | Wait 1 | Repeat SlideThem, 20, 21 | Wait 1| SwapThem
SetThem=[!SetVariable CurrentSecondsY "2"][!SetVariable NewSecondsY "-40"]#U#
SlideThem=[!SetVariable CurrentSecondsY "(Clamp(#CurrentSecondsY#+2,2,45))"][!SetVariable NewSecondsY "(Clamp(#NewSecondsY#+2,-40,2))"]#U#
SwapThem=[!SetVariable CurrentSecondsY "2"][!SetVariable NewSecondsY "-40][!SetVariable CurrentSeconds "[MeasureSeconds]"]#U#
DynamicVariables=1

[MeterNewHours]
Meter=String
Group=Numbers
MeasureName=MeasureHours
W=30
H=32
X=22
Y=#NewHoursY#
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCurrentHours]
Meter=String
Group=Numbers
W=30
H=32
X=22
Y=#CurrentHoursY#
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
Text=#CurrentHours#
UpdateDivider=-1
DynamicVariables=1

[MeterNewMinutes]
Meter=String
Group=Numbers
MeasureName=MeasureMinutes
W=30
X=64
Y=#NewMinutesY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCurrentMinutes]
Meter=String
Group=Numbers
MeasureName=MeasureMinutes
W=30
X=64
Y=#CurrentMinutesY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
Text=#CurrentMinutes#
UpdateDivider=-1
DynamicVariables=1

[MeterNewSeconds]
Meter=String
Group=Numbers
MeasureName=MeasureSeconds
W=30
X=106
Y=#NewSecondsY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
UpdateDivider=-1
DynamicVariables=1

[MeterCurrentSeconds]
Meter=String
Group=Numbers
W=30
X=106
Y=#CurrentSecondsY#
H=32
StringAlign=Center
FontFace=Fira Sans
FontSize=20
FontColor=#NumberColor#
SolidColor=#BackColor#
Padding=5,5,5,5
AntiAlias=1
Text=#CurrentSeconds#
UpdateDivider=-1
DynamicVariables=1

[MeterTopLine]
Meter=Image
X=0
Y=0
H=2
W=128
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterLeftLine]
Meter=Image
X=0
Y=0
H=43
W=2
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterMidLine1]
Meter=Image
X=42
Y=2
W=2
H=41
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterMidLine2]
Meter=Image
X=84
Y=2
W=2
H=41
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterRightLine]
Meter=Image
X=126
Y=0
H=43
W=2
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1

[MeterBottomLine]
Meter=Image
X=0
Y=43
H=2
W=128
SolidColor=#LinesColor#
UpdateDivider=-1
DynamicVariables=1
I removed any "interrupt" from the process, and just let the transition complete even if another one happens during it. I increased the "wait" between actions to that the total transition is about 1/2 a second. So in theory, the "second" is split into two parts, the "transition" for half-a-second, and the "display" of the current second for half-a-second. This seems to work somewhat better, but I need to watch it for a while to see if the "difference creep" still rears its ugly head. One advantage to this approach is that any "conflict" that does happen should in a sense be "self-correcting" after one hiccup.

Edit: I do think this works much, much better. Milamber33, I think you actually tumbled to the real problem, and I just wasn't seeing it. I now think the problem wasn't so much any "conflict" with the transition and the seconds, but that I was just setting way too "low" a "wait" time between actions, and Rainmeter was struggling to keep up with the message queue, and was in a sense "throwing away" some actions. By letting the transition be at a more reasonable rate, Rainmeter seems to be able to gracefully handle this transition without issues.

test.gif
I will update the .rmskin in the first post...
You do not have the required permissions to view the files attached to this post.