ActionTimer plugin


Plugin=ActionTimer

Executes a series of Rainmeter actions independent of the normal skin Update cycle. This can allow the series of actions to be executed faster (or slower) than the rate defined in Update in [Rainmeter] and can be executed as fast as 1 millisecond apart.

Overview

To understand the purpose of ActionTimer, it helps to have some understanding of how Rainmeter runs a skin. On each skin Update, the value set in the [Rainmeter] section of the skin, Rainmeter does the following:

  • Update all measures
  • Execute measure actions
  • Update all meters
  • Redraw the skin

Update has a lower limit of 16, or once every 16 milliseconds. This means that any series of separate actions can only execute every 16 milliseconds. In addition, setting a very low Update rate in [Rainmeter] can cause the entire skin to use a lot of CPU resources, when you may only need it to be "fast" for a specific purpose, perhaps some animation or transition effect. Finally, any series of actions you take in the context of the Update cycle are "blocking", in the sense that Rainmeter must complete them before it is able to continue with other normal skin processing.

While you can "stack up" actions in a single action option:

IfTrueAction=[!SetOption SomeMeter X "5"][!SetOption SomeMeter X "10"]

Rainmeter will run both of the actions in the same Update cycle, before it updates the meters and redraws the skin, and so in effect they both visibly happen "at once". The meter won't visibly move to "5" and then "10", but will just jump straight to "10". The only current solution is to have the two actions take place in two Update cycles, and thus the fastest the series can ever execute is every 16 milliseconds.

Now 16 milliseconds seems pretty fast, and it is. However, if you have some animation with 100 "frames" or want to do some "transition" of a meter; fading the opacity, shifting the color or sliding the position, it is in fact visibly quite slow.

Don't forget as well, that that 16 millisecond lower limit is the time Rainmeter will have to do everything in the skin. Update all measures, take all actions, update all meters, and redraw the skin. In reality, even a moderately complicated skin isn't really going to update every 16 milliseconds in any case, it will at best "try to".

What ActionTimer does is execute the list of actions defined in ActionListN, one after the other, in a separate thread outside the normal Update cycle, as fast as it possibly can. This is REALLY fast. The Wait N values that you put in between each action in the list is what stops them from appearing to just happen all at once, and allows you to completely control the speed of the series of actions. Wait can be any number, from 1 (one millisecond) to whatever you need.

Since the actions in ActionListN are executed in a separate thread from the main Rainmeter process, the skin will carry on updating normally, while the ActionTimer plugin will control the actions in the list.

Important Note

While ActionTimer is very CPU efficient, it is not "free". The actions are executed by the plugin in a separate thread from the rest of the Rainmeter skin, allowing the skin to continue to process normally while the plugin actions are executing, with the plugin communicating with the skin via window "messages" to the Rainmeter message queue. This allows the plugin to instruct the skin to "do this now", much as a MouseOverAction is recognized and acted upon immediately.

Some care must be taken however, not to overwhelm the message queue. Things done with ActionTimer in general should be short targeted actions, like a meter transition or short animation. Ensure that there is at least some "wait" time between actions, so Rainmeter has time to handle other messages in the message queue. In addition, keep in mind that !Redraw actions can be relatively CPU expensive, particularly if a lot of image resizing is involved.

ActionTimer does not support, and should not be used, to do anything "endless" or otherwise of a very long duration combined with a very rapid update. If the Rainmeter message queue becomes overwhelmed, the skin can get laggy and unresponsive to mouse actions you might take.

Options

General measure options

All general measure options are valid.

ActionList1, ActionList2 .. ActionListN

A numbered option, starting with ActionList1.

Each ActionListN will execute one or more Actions separated by the pipe | character. In addition there are two list commands, Repeat and Wait, that can be used in the ActionList. In a sense, this option is a "script" of what you want the plugin to do when the ActionList is triggered. In its most simple expression, it is

ActionList1=Do this | Wait this long | Do that

ActionList components

  • Action name
    The plugin will execute what is defined in the named Action option. The action name can be anything. This is simply the name of the Action option, and should never be actual bangs or commands itself. The actual skin bangs or commands to be executed are defined in the Action option.
  • Repeat Action name, Wait time number, Repeat count number
    This will repeat the named Action option Repeat count times, with a wait of Wait time milliseconds between each. Note that Wait time is not applied after the last execution of Action name, only between each.
  • Wait number of milliseconds
    This is used to create a pause or wait in milliseconds between each named Action or other component in the ActionList. There should always be a Wait of at least 1 millisecond between each ActionList component.
  • The pipe | character is used to separate each of the ActionList components.

Examples:

ActionList1=FirstAction | Wait 5 | SecondAction
Execute everything defined in the FirstAction option, wait 5 milliseconds, and execute everything defined in the SecondAction option.

ActionList1=Repeat FirstAction, 5, 20 | Wait 5 | SecondAction
Execute everything defined in the FirstAction option 20 times, with a wait of 5 milliseconds between each execution of FirstAction. Wait 5 milliseconds, and execute everything defined in the SecondAction option.

Action Any unique name=[!bang or command]

These can be any unique name, in any order. They will contain the skin bangs or other actions that will be executed by the plugin when the named action is called by an ActionList.

They are defined and executed exactly the same as any other Action option in Rainmeter, for instance LeftMouseUpAction or OnChangeAction.

Examples:

[MeasureChangeFont]
Measure=Plugin
Plugin=ActionTimer
ActionList1=SetFontSmall | Wait 1000 | SetFontBig
SetFontSmall=[!SetOption SomeMeter FontSize "10"][!UpdateMeter SomeMeter][!Redraw]
SetFontBig=[!SetOption SomeMeter FontSize "15"][!UpdateMeter SomeMeter][!Redraw]

Notes:

  • Since the actions are being done independent of the Update cycle of the skin, you must explicitly do any !UpdateMeter and !Redraw commands needed to have the skin actually reflect any changes to meters made in the action.
  • If you are using !SetVariable to change and use any dynamic #Variables# in the action, you will need to !UpdateMeasure the plugin measure between each execution of the action option, to ensure the measure has the most current value for the #Variable#.

This can be simplified by setting and using a #Variable# that will take the appropriate update actions, and then just execute that #Variable# at the end of each action option.

[Variables]
U=[!UpdateMeasure MeasureChangeFont][!UpdateMeter *][!Redraw]
[MeasureChangeFont]
Measure=Plugin
Plugin=ActionTimer
ActionList1=SetFontSmall | Wait 1000 | SetFontBig
SetFontSmall=[!SetOption SomeMeter FontSize "10"]#U#
SetFontBig=[!SetOption SomeMeter FontSize "15"]#U#
IgnoreWarnings Default: 0

Any ActionListN must completely finish all actions in the list before it can be executed again. Any command to execute the list while it is still performing actions will be ignored, and a warning message will be generated in the log. There may be occasions where this is in fact desired behavior, and the log error messages can be suppressed.

  • 0 - Warnings in the log are produced. (default)
  • 1 - Warnings in the log are suppressed.

Plugin Commands

The plugin will take no action unless triggered with one of these commands.

Execute ActionList number

Execute the correspondingly numbered ActionListN.

Example:

LeftMouseUpAction=[!CommandMeasure MeasureName "Execute 1"]

Stop ActionList number

Stop the correspondingly numbered ActionListN.

As noted above, Any ActionListN must completely finish all actions in the list before it can be executed again. Any command to execute the list while it is still performing actions will be ignored, and a warning message will be generated in the log.

The Stop N command will immediately terminate and reset the corresponding running ActionListN, so it may be executed again.

Example:

LeftMouseUpAction=[!CommandMeasure SomeMeasure "Stop 1"][!CommandMeasure SomeMeasure "Execute 1"]

Examples

Several example skins are included in the .rmskin download. Take a look at the code to see some different ways you might use the plugin.

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
[Variables]
W=15
U=[!UpdateMeasureGroup Sizers][!UpdateMeter MeterText][!Redraw]
Size=8
[MeasureSizeUp]
Measure=Plugin
Plugin=ActionTimer
Group=Sizers
ActionList1=ChangeSizeStart|Wait #W#|Repeat ChangeSizeCalc,#W#,11
ChangeSizeStart=[!SetVariable Size "#Size#"]#U#
ChangeSizeCalc=[!SetVariable Size "(Clamp(#Size#+5,8,60))"]#U#
IfCondition=#Size# = 8
IfTrueAction=[!SetOption MeterText Text "small"]#U#
IfCondition2=(#Size# > 8) && (#Size# < 60)
IfTrueAction2=[!SetOption MeterText Text "Changing"]#U#
IfCondition3=#Size# = 60
IfTrueAction3=[!SetOption MeterText Text "BIG"]#U#
DynamicVariables=1
[MeasureSizeDown]
Measure=Plugin
Plugin=ActionTimer
Group=Sizers
ActionList1=ChangeSizeStart|Wait #W#|Repeat ChangeSizeCalc,#W#,11
ChangeSizeStart=[!SetVariable Size "#Size#"]#U#
ChangeSizeCalc=[!SetVariable Size "(Clamp(#Size#-5,8,60))"]#U#
IfCondition=#Size# = 8
IfTrueAction=[!SetOption MeterText Text "small"]#U#
IfCondition2=(#Size# > 8) && (#Size# < 60)
IfTrueAction2=[!SetOption MeterText Text "Changing"]#U#
IfCondition3=#Size# = 60
IfTrueAction3=[!SetOption MeterText Text "BIG"]#U#
DynamicVariables=1
[MeterText]
Meter=String
W=400
H=90
X=200
Y=45
StringAlign=CenterCenter
FontSize=#Size#
FontColor=255,255,255,255
SolidColor=0,0,0,1
AntiAlias=1
Text=Small
UpdateDivider=-1
DynamicVariables=1
MouseOverAction=[!CommandMeasure MeasureSizeDown "Stop 1"][!CommandMeasure MeasureSizeUp "Execute 1"]
MouseLeaveAction=[!CommandMeasure MeasureSizeUp "Stop 1"][!CommandMeasure MeasureSizeDown "Execute 1"]