It is currently January 20th, 2019, 12:04 pm

What happens in a lua cycle.

Discuss the use of Lua in Script measures.
User avatar
kyriakos876
Posts: 908
Joined: January 30th, 2017, 2:01 am
Location: Greece

What happens in a lua cycle.

kyriakos876 » December 12th, 2018, 1:01 pm

Hello,
I want to know what happens in one cycle of lua.
Say I have

Code: Select all

function Testing()

	for i = 1 , 5 do
		SKIN:Bang('!SetVariable Something "Hello" ')
		SKIN:Bang('!UpdateMeasure SomeMeasure ')
		SKIN:Bang('!SetVariable Something "World" ')
		SKIN:Bang('!UpdateMeasure SomeMeasure ')
	end	

end
Will the skin see the Variable "Something" as "Hello" and then as "World" or will it only see the last thing which is "World"?
User avatar
jsmorley
Developer
Posts: 18663
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: What happens in a lua cycle.

jsmorley » December 12th, 2018, 1:19 pm

kyriakos876 wrote:
December 12th, 2018, 1:01 pm
Hello,
I want to know what happens in one cycle of lua.
Say I have

Code: Select all

function Testing()

	for i = 1 , 5 do
		SKIN:Bang('!SetVariable Something "Hello" ')
		SKIN:Bang('!UpdateMeasure SomeMeasure ')
		SKIN:Bang('!SetVariable Something "World" ')
		SKIN:Bang('!UpdateMeasure SomeMeasure ')
	end	

end
Will the skin see the Variable "Something" as "Hello" and then as "World" or will it only see the last thing which is "World"?
"World".

The Lua script is "blocking", so Rainmeter will wait until the function in the Lua script is completed and "returns" before it reacts to any of it in the skin.
User avatar
kyriakos876
Posts: 908
Joined: January 30th, 2017, 2:01 am
Location: Greece

Re: What happens in a lua cycle.

kyriakos876 » December 12th, 2018, 1:37 pm

jsmorley wrote:
December 12th, 2018, 1:19 pm
"World".

The Lua script is "blocking", so Rainmeter will wait until the function in the Lua script is completed and "returns" before it reacts to any of it in the skin.
So if the one called is blocking the skin, calling another lua inside the lua to apply the changes won't help either right?
User avatar
jsmorley
Developer
Posts: 18663
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: What happens in a lua cycle.

jsmorley » December 12th, 2018, 1:40 pm

kyriakos876 wrote:
December 12th, 2018, 1:37 pm
So if the one called is blocking the skin, calling another lua inside the lua to apply the changes won't help either right?
Nope. You simply cannot use for / next loops in Lua to "drive" the Rainmeter skin. It won't work. Put it out of your mind. Move on... ;-)
User avatar
kyriakos876
Posts: 908
Joined: January 30th, 2017, 2:01 am
Location: Greece

Re: What happens in a lua cycle.

kyriakos876 » December 12th, 2018, 1:41 pm

jsmorley wrote:
December 12th, 2018, 1:40 pm
Nope. You simply cannot use for / next loops in Lua to "drive" the Rainmeter skin. It won't work.
Ah poop.... I'll just call different luas then. Thanks!
User avatar
jsmorley
Developer
Posts: 18663
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: What happens in a lua cycle.

jsmorley » December 12th, 2018, 2:42 pm

Note that while you can't drive the skin from the Lua, you can drive the Lua from the skin:

https://docs.rainmeter.net/manual/lua-scripting/inline-lua/#CallingAFunction

Skin:

Code: Select all

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

[Variables]
MyVar=0

[Lua]
Measure=Script
ScriptFile=#CURRENTPATH#Test.lua
Disabled=1

[Counter]
Measure=Calc

[FireLua]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat FireIt, 5, 100
FireIt=[&Lua:MyForNextLoop()]

[MeterCount]
Meter=String
MeasureName=Counter
FontSize=12
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
DynamicVariables=1
Text=The count is: %1#CRLF#The variable MyVar is: #MyVar#
LeftMouseUpAction=[!CommandMeasure FireLua "Execute 1"]
Lua:

Code: Select all

function Initialize()

	myCount = 0
	
end

function MyForNextLoop()

	myCount = myCount + 1
	if myCount > 100 then myCount = 1 end
	
	SKIN:Bang('!SetVariable', 'MyVar', myCount)
	SKIN:Bang('!SetOption', 'Counter', 'Formula', myCount)
	SKIN:Bang('!UpdateMeasure', 'Counter')
	SKIN:Bang('!UpdateMeter', '*')
	SKIN:Bang('!Redraw')
	
end
Viola! A for / next loop that runs like a scalded cat, and is not "blocking". ActionTimer is a "threaded" plugin.

GIF.gif
You do not have the required permissions to view the files attached to this post.
User avatar
kyriakos876
Posts: 908
Joined: January 30th, 2017, 2:01 am
Location: Greece

Re: What happens in a lua cycle.

kyriakos876 » December 12th, 2018, 3:13 pm

Why isn't the "MyCount" variable in the Lua get reseted Everytime?
I'll explain how I think this works. Correct where I'm wrong.
1) Repeat calls Lua
2) Lua does MyCount+1
3) Lua closes (shouldn't the MyCount be forgotten since the next time it'll be 0 again?)
4) repeat calls Lua again.
User avatar
jsmorley
Developer
Posts: 18663
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: What happens in a lua cycle.

jsmorley » December 12th, 2018, 3:14 pm

kyriakos876 wrote:
December 12th, 2018, 3:13 pm
Why isn't the "MyCount" variable in the Lua get reseted Everytime?
I'll explain how I think this works. Correct where I'm wrong.
1) Repeat calls Lua
2) Lua does MyCount+1
3) Lua closes (shouldn't the MyCount be forgotten since the next time it'll be 0 again?)
4) repeat calls Lua again.
No, the value of myCount in the Lua is not "forgotten". The Lua is not "closed". A Lua Script measure is never "closed" unless the skin is refreshed or unloaded.
rxtd
Posts: 81
Joined: April 30th, 2017, 11:51 am

Re: What happens in a lua cycle.

rxtd » December 12th, 2018, 3:38 pm

jsmorley wrote:
December 12th, 2018, 1:19 pm
The Lua script is "blocking", so Rainmeter will wait until the function in the Lua script is completed and "returns" before it reacts to any of it in the skin.
I have read this so many time since I joined Rainmeter community, and I didn't check what happens if I mix bangs with lua code. And, after I did few tests, it looks like I don't understand what you mean by this "blocking".
What does this "blocking" apply to?

I see that after executing this code

Code: Select all

SKIN:Bang('!SetVariable', 'qwe', '123')
print(SKIN:ReplaceVariables('#qwe#'))
I get "123" in the log. So variables are changed immediately after SetVariable bang from lua.

Then what if I call some other lua script? Just in case !SetVariable make changes in some local script cache. Well, apparently CommandMeasure bang is performed immediately, and section variables are resolved immediately.
File script1.lua

Code: Select all

local a = 0

function fun()
	a = 1
	return 'fun'
end

function Initialize()
	SKIN:Bang('!CommandMeasure', 'script2', 'call()')
	print(a)
end
File script2.lua

Code: Select all

function call()
	SKIN:ReplaceVariables('[&script1:fun()]')
end
What happen if I change some option on some measure and update it? Apparently, SetOption and UpdateMeasure are also performed immediately.
Lets imagine that we have a Calc Measure named testCalc.
Script:

Code: Select all

a = false

function Update()
	if (a == true) then return end
	a = true
	SKIN:Bang('!SetOption', 'testCalc', 'formula', '2')
	SKIN:Bang('!UpdateMeasure', 'testCalc')
	print(SKIN:ReplaceVariables('[testCalc]'))
end
More! Lets try to change some meter and redraw the skin.
Aaaaaaand... It just works :confused:
"im" is an Image meter.

Code: Select all

a = false

function Update()
	if (a == true) then return end
	a = true
	SKIN:Bang('!SetOption', 'im', 'w', '200')
	SKIN:Bang('!SetOption', 'im', 'h', '200')
	SKIN:Bang('!UpdateMeter', 'im')
	SKIN:Bang('!Redraw')
	
	for i = 1 , 100000000 do
		SKIN:Bang('!UpdateMeasure testCalc')
	end
	
	print('end')
end
Rainmeter clearly does redraw the skin before the final statement in lua script as that loop blocks the main Rainmeter thread and it doesn't respond to user action and don't update skins.

So. Nothing of that what I have tested is showing this "blocking" effect. Even redrawing of a skin actually happens just in the place I call !Redraw bang from lua.
What exactly do you mean by "blocking"? Is it the sole fact that scripts are executed in the main Rainmeter thread, so any heavy loop will make Rainmeter unresponsive?
I also understand that if I call several bangs without !Redraw somewhere in-between, I won't see changes. But it isn't related to lua: bangs defined in the skin also work that way.
Last edited by rxtd on December 12th, 2018, 3:49 pm, edited 1 time in total.
User avatar
jsmorley
Developer
Posts: 18663
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: What happens in a lua cycle.

jsmorley » December 12th, 2018, 3:49 pm

Right, by "blocking" I mean that the entire Lua is executed in a single Rainmeter Update cycle.

If you have a Lua like this:

Code: Select all

function Update()

	for a = 1, 100 do
		SKIN:Bang('!SetOption', 'MeterCount', 'Text', 'Count is: '..a)
		SKIN:Bang('!UpdateMeter', '*')
		SKIN:Bang('!Redraw')
	end

end
You might see the meter "flicker" a bit, but basically it will always be "100" All of the bangs will be executed, but they will all happen in the same Update cycle of the skin, as fast as your computer can execute them, which is really, really, fast. So it will increment the value of "a", send the Text option to the meter, update the meter and redraw the skin. It will do that 100 times, as fast as your computer will go (again, very fast) and end up at "100", where it will wait for the next skin Update cycle to start and begin again.

While that loop is executing, nothing else in the skin will happen, and the skin will be unresponsive to the mouse.

If you were to change that 100 to 1000000, the skin would become entirely unresponsive to any mouse actions, because it is "blocked" by the Lua script. Windows will treat it as a threat and kill Rainmeter entirely.

It isn't that each and every bang you send to the skin doesn't happen when you do it in a for / next loop in Lua, they all do. It's just that they all happen "at once" in a sense, or more accurately, "one after the other, as fast as possible".

Now you might think that you can beat that by building in some kind of "sleep" in the Lua for / next loop, but that won't work. It will just make the skin even more "unresponsive" and cause Windows to hate it even more. The skin will be unresponsive for the entire duration of the Lua Update() function.

Think of it this way. The skin passes control to the Lua script when the Script measure is executed. The skin will then sit, entirely unresponsive, until the script is finished and "returns". Then the skin regains control, and everything that the script told Rainmeter to do will all be done at once, one after the other, as fast as your computer will go.