It is currently May 10th, 2024, 5:28 pm

Setting meter text with Lua?

Discuss the use of Lua in Script measures.
FatherCode
Posts: 21
Joined: October 8th, 2011, 4:01 pm

Setting meter text with Lua?

Post by FatherCode »

I was reading the documentation (and, also, learning Lua) here: http://rainmeter.net/cms/LuaScripting_beta
when I saw this line:
Directly set the value of a string meter.
But I never did find the method for setting the value of a string meter =/
Can anyone point me in the right direction?

[EDIT]
I'm making a flash card skin, which is why I want to know how to set the value of a string meter.
I don't need to update the skin at all until I press the 'next card', 'prev card' or 'flip card' buttons.

I tried something along the lines of:
Skin.ini

Code: Select all

[MeterNextCard]
	LeftMouseUpAction	=!Execute [!CommandMeasure "MeasureLua" "nextCard()"]
Skin.lua

Code: Select all

function nextCard ()
	temp_i = tonumber(SKIN:GetVariable("card.cur"))+1
	if (temp_i == tonumber(SKIN:GetVariable("card.amt"))) then
		SKIN:Bang("!SetVariable card.cur 0")
	else
		SKIN:Bang("!SetVariable card.cur "..temp_i)
	end
	SKIN:Bang("!Update")
end
But apparently, !Update doesn't update the skin =/
I also tried !Redraw, !UpdateMeeasure MeasureLua, !UpdateMeter MeterFlashCard and a bunch of other stuff but couldn't get it to update immediately after a button was clicked
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Setting meter text with Lua?

Post by jsmorley »

FatherCode wrote:I was reading the documentation (and, also, learning Lua) here: http://rainmeter.net/cms/LuaScripting_beta
when I saw this line: But I never did find the method for setting the value of a string meter =/
Can anyone point me in the right direction?

[EDIT]
I'm making a flash card skin, which is why I want to know how to set the value of a string meter.
I don't need to update the skin at all until I press the 'next card', 'prev card' or 'flip card' buttons.

I tried something along the lines of:
Skin.ini

Code: Select all

[MeterNextCard]
	LeftMouseUpAction	=!Execute [!CommandMeasure "MeasureLua" "nextCard()"]
Skin.lua

Code: Select all

function nextCard ()
	temp_i = tonumber(SKIN:GetVariable("card.cur"))+1
	if (temp_i == tonumber(SKIN:GetVariable("card.amt"))) then
		SKIN:Bang("!SetVariable card.cur 0")
	else
		SKIN:Bang("!SetVariable card.cur "..temp_i)
	end
	SKIN:Bang("!Update")
end
But apparently, !Update doesn't update the skin =/
I also tried !Redraw, !UpdateMeeasure MeasureLua, !UpdateMeter MeterFlashCard and a bunch of other stuff but couldn't get it to update immediately after a button was clicked
First, you can directly set the text of a string meter with

SKIN:Bang('!SetOption MeterName Text "StringYouWant"')

As to the second bit, you can update the skin with SKIN:Bang('!Update') just as you have it, but it doesn't make any sense to do that from Lua. EVERYTHING in the Lua script that talks to Rainmeter happens when the script is done and returns to Rainmeter, and thus on the next Update anyway... You might want to consider something like:

LeftMouseUpAction=!Execute [!CommandMeasure "MeasureLua" "nextCard()"][!Update]

Which should execute the Lua and immediately update.

I'd be interested to see the rest of the skin code, to see if there are any other tips we might offer.
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Setting meter text with Lua?

Post by jsmorley »

Just thinking about "flash cards" in it's most simple terms, I'd be tempted to do something like this:

Skin:

Code: Select all

[Rainmeter]
Update=1000

[Variables]
CurrCard=0

[MeasureLuaScript]
Measure=Script
ScriptFile=Test.lua
UpdateDivider=-1

[CardMeter]
Meter=String
FontSize=13
FontColor=255,255,255,255
SolidColor=0,0,0,1
Text=Click me to start practicing...
LeftMouseUpAction=!Execute [!CommandMeasure "MeasureLuaScript" "NextCard()"][!Update]
So I have the Script measure, which is set to UpdateDivider=-1 so it only runs once, to Initialize() it. Then the !CommandMeasure that just calls the NexCard() function. Then it insta-updates the skin so you get really quick response to the clicks.

Lua:

Code: Select all

PROPERTIES =
{

}

function Initialize()

	tCards = {}
	tCards[1] = "2 X 1"
	tCards[2] = "2 X 2"
	tCards[3] = "2 X 3"
	tCards[4] = "2 X 4"
	tCards[5] = "2 X 5"

end -->Initialize

function Update()

	return 1

end -->Update

function NextCard()

	iCurrCard = tonumber(SKIN:GetVariable('CurrCard'))
	iNewCard = iCurrCard + 1
	if iNewCard == 6 then iNewCard = 1 end
	SKIN:Bang('!SetOption CardMeter Text \"'..tCards[iNewCard]..'\"')
	SKIN:Bang('!SetVariable CurrCard '..iNewCard)

end -->NextCard
So I initialize a table with the text of the cards (the worlds simplest multiplication flash cards) indexed from 1 to 5. Then I have a variable set in the skin (CurrCard) that is used so the Lua can keep track of where we are. It reads it, uses it, then sets it after adding +1.

So I have added +1 to the "current card number", then use that to look up the text from that table and smack it on the meter with !SetOption. Then update the variable in the skin so it is +1 for the next time I click. When we get to 6, we have gone too far, and set it back to 1.

... Might be even more fun with actual images of cards named 1.png ... 5.png and an Image Meter that you set the "ImageName=" with !SetOption from the Lua.
FatherCode
Posts: 21
Joined: October 8th, 2011, 4:01 pm

Re: Setting meter text with Lua?

Post by FatherCode »

My current lua file:

Code: Select all

flashCard = {front=""; back="";}

function flashCard:new (o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

function flashCard:getValue (side)
	if (side==0) then
		return self.front
	else
		return self.back
	end
end

FLASHCARDS = {cur=0, amt=0, state=0}
PROPERTIES = {
}
function Initialize ()
	for i=0, 10 do
		FLASHCARDS[i] = flashCard:new()
	end
	
	FLASHCARDS[0].front="I AM A FRONT #1"
	FLASHCARDS[0].back ="I AM A BACK #1"

	FLASHCARDS[1].front="I AM A FRONT #2"
	FLASHCARDS[1].back ="I AM A BACK #2"

	FLASHCARDS[2].front="I AM A FRONT #2"
	FLASHCARDS[2].back ="I AM A BACK #2"

	FLASHCARDS[3].front="I AM A FRONT #3"
	FLASHCARDS[3].back ="I AM A BACK #3"

	FLASHCARDS[4].front="I AM A FRONT #4"
	FLASHCARDS[4].back ="I AM A BACK #4"

	FLASHCARDS[5].front="I AM A FRONT #5"
	FLASHCARDS[5].back ="I AM A BACK #5"

	FLASHCARDS.amt = 6
	updateCard()
end

function Update ()
	return 1
end

function nextCard ()
	if (FLASHCARDS.cur+1==FLASHCARDS.amt) then
		FLASHCARDS.cur = 0
	else
		FLASHCARDS.cur = FLASHCARDS.cur+1
	end
	updateCard()
end

function prevCard ()
	if (FLASHCARDS.cur-1<0) then
		FLASHCARDS.cur = FLASHCARDS.amt-1
	else
		FLASHCARDS.cur = FLASHCARDS.cur-1
	end
	updateCard()
end

function flipCard ()
	FLASHCARDS.state = 1 - FLASHCARDS.state
	updateCard()
end

function updateCard ()
	SKIN:Bang("!SetOption MeterFlashCard Text \""..FLASHCARDS[FLASHCARDS.cur]:getValue(FLASHCARDS.state).."\"")
	SKIN:Bang("!Update")
end
Skin file (a little basic ><)

Code: Select all

[Rainmeter]
	Update			=1000
	Author			=JustinAnyhowStep
	BackgroundMode		=2
	SolidColor		=00000066

[Metadata]
	Name			=FlashCards
	Config			=
	Description		=A simple flash card skin to help you memorize things
	Instructions		=
	Version			=1.0
	Tags			=
	License			=
	Variant			=
	Preview			=

[Variables]
	@include		=#CURRENTPATH#\variables.inc

[ButtonStyle]
	W			=#btn.width#
	H			=#btn.height#
	Y			=(#skin.height#-#btn.height#-#skin.padding#)
	
[TextStyle]
	W			=(#skin.width#-(#skin.padding#*2))
	H			=(#skin.height#-(#skin.padding#*2)-#btn.height#)
	X			=#skin.padding#
	Y			=#skin.padding#
	FontColor		=FFFFFFFF
	
[InvisiblePaddingStyle]
	W			=#skin.padding#
	X			=(#skin.width#-#skin.padding#)
	Y			=0


[MeasureLua]
	Measure			=Script
	ScriptFile		=#CURRENTPATH#\FlashCards.lua
	
[MeterFlashCard]
	Meter			=String
	MeterStyle		=TextStyle
	MeasureName		=MeasureLua
	Text			=%1

[MeterFlipCard]
	Meter			=String
	MeterStyle		=TextStyle
	Text			=Flip Card
	DynamicVariables	=1
	LeftMouseUpAction	=!Execute [!CommandMeasure "MeasureLua" "flipCard()"]
	StringAlign		=CENTER
	W			=(#skin.width#/4)
	H			=#btn.height#
	X			=(#skin.width#/2)
	Y			=(#skin.height#-#btn.height#)

[MeterNextCard]
	Meter			=Image
	MeterStyle		=ButtonStyle
	ImageName		=#btn.nxt#
	X			=(#skin.width#-#skin.padding#-#btn.width#)
	DyanamicVariables	=1
	LeftMouseUpAction	=!Execute [!CommandMeasure "MeasureLua" "nextCard()"]

[MeterPrevCard]
	Meter			=Image
	MeterStyle		=ButtonStyle
	ImageName		=#btn.prv#
	X			=#skin.padding#
	DyanamicVariables	=1
	LeftMouseUpAction	=!Execute [!CommandMeasure "MeasureLua" "prevCard()"]
And the variables.inc

Code: Select all

[Variables]
	btnnxt		=#CURRENTPATH#\Active.png
	btnprv		=#CURRENTPATH#\Active.png
	btnwidth	=14
	btnheight	=14
	
	skinwidth	=200
	skinheight	=200
	skinpadding	=3
@jsmorley
Oh, wow. =x
I totally forgot that "Text" was an option ><

Anyways, I got it working fine now.
Thanks for the help :)

Oh, do you have any idea how I'd add more cards through the skin?
Or would I have to manually edit the .lua file every time I want to add a new card? =/
Last edited by FatherCode on October 11th, 2011, 2:00 am, edited 1 time in total.
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Setting meter text with Lua?

Post by jsmorley »

My pleasure.. I was just thinking about "answers" as well... ;-)

Code: Select all

PROPERTIES =
{

}

function Initialize()

	tCards = {}
	tAnswers = {}
	tCards[1] = "2 X 1"
	tAnswers[1] = "2"
	tCards[2] = "2 X 2"
	tAnswers[2] = "4"
	tCards[3] = "2 X 3"
	tAnswers[3] = "6"
	tCards[4] = "2 X 4"
	tAnswers[4] = "8"
	tCards[5] = "2 X 5"
	tAnswers[5] = "10"	

end -->Initialize

function Update()

	return 1

end -->Update

function NextCard()

	iCurrCard = tonumber(SKIN:GetVariable('CurrCard'))
	iAnswer = tonumber(SKIN:GetVariable('Answer'))

	if iAnswer == 0 then
		SKIN:Bang('!SetOption CardMeter Text \"'..tCards[iCurrCard]..'\"')
		SKIN:Bang('!SetVariable Answer 1')
	else
		SKIN:Bang('!SetOption CardMeter Text \"'..tAnswers[iCurrCard]..'\"')
		SKIN:Bang('!SetVariable Answer 0')
		iCurrCard = iCurrCard + 1
	end
	
	if iCurrCard == 6 then iCurrCard = 1 end
	SKIN:Bang('!SetVariable CurrCard '..iCurrCard)	
	
end
FatherCode
Posts: 21
Joined: October 8th, 2011, 4:01 pm

Re: Setting meter text with Lua?

Post by FatherCode »

Woah..
You're fast O_O

You might have missed my edit on the previous post asking about adding cards to the 'deck' =x

[EDIT]
I just decided to do away with variables in the .ini file for the deck and stuck it in the .lua file xD
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Setting meter text with Lua?

Post by jsmorley »

FatherCode wrote:Woah..
You're fast O_O

You might have missed my edit on the previous post asking about adding cards to the 'deck' =x

[EDIT]
I just decided to do away with variables in the .ini file for the deck and stuck it in the .lua file xD
I did miss that. I'm not sure, but I think I would create a text file with the cards, and read it in with the .lua and add it to the cards table or whatever... Then you can just edit the text file and refresh the skin. Not sure if that is robust enough for what you mean.

You could get a lot more clever and create the text file as a .ini formatted file, but named .inc as in "Cards.inc" or something (just so Rainmeter doesn't confuse it with a skin)

[Cards]
Card1="2 X 1"
Answer1="2"

Then use the InputText plugin in Rainmeter to send the bang !WriteKeyValue to add cards to that .inc text file from the skin, and have the .lua read the file on each "click". Tricky to then keep track of where you are and what the "end" is, but doable.
FatherCode
Posts: 21
Joined: October 8th, 2011, 4:01 pm

Re: Setting meter text with Lua?

Post by FatherCode »

All right, I tried it and it works except for a few things..
+ I use !WriteKeyValue, so I have to use !Refresh for the changes to take effect, right?

The thing is, !Refresh is called immediately after the first InputText command and this messes things up =/
Here's the code in question:

Code: Select all

	LeftMouseUpAction	=!Execute [!CommandMeasure "MeasureInputText" "ExecuteBatch 1-2"][!WriteKeyValue Variables card.amt (1+#card.amt#) "#CURRENTPATH#\variables.inc"][!Refresh]
The thing is, I thought this would happen:
01) Command1 is run
02) Command2 is run
03) card.amt is updated
04) Skin is refreshed

Instead, this happens
01) Command1 is run
02) card.amt is updated
03) Skin is refreshed

Command2 disappears =/

[EDIT]
Removing the part "[!Refresh]" fixes it, as in:
01) Command1 is run
02) Command2 is run
03) card.amt is updated

But then, the meters and measures don't know that the values have been updated =/

[EDIT=2]
The InputText in question:

Code: Select all

	Command1		=!Execute [!WriteKeyValue Variables fCard#card.amt# "$UserInput$" "#CURRENTPATH#\variables.inc"]
	Command2		=!Execute [!WriteKeyValue Variables bCard#card.amt# "$UserInput$" "#CURRENTPATH#\variables.inc"]
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Setting meter text with Lua?

Post by jsmorley »

Yeah, assuming that you are using Variables.inc in the skin as @Include=Variables.inc then the skin won't see any changes to that without a refresh. Unless we are talking at cross purposes, I was suggesting writing with !WriteKeyValue to a .inc file (or .cards or .zelda, it doesn't really matter) in a .ini "format" and then just reading it with the .lua, not the skin... Then you don't need a refresh.
User avatar
jsmorley
Developer
Posts: 22632
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Setting meter text with Lua?

Post by jsmorley »

Note that MyCards.cards or whatever you call it will already need to exist, and have the [Section] you want to write to when you use !WriteKeyValue. You can seed it with a file with simply:

[Cards]

then:

LeftMouseUpAction=!WriteKeyValue Cards Card1 AceOfSpades #CURRENTPATH#MyCards.cards

The file will now have:

[Cards]
Card1=AceOfSpades

then you can open that in Lua and parse the bejeesus out of it and use the values as you need.