Thread Tools Display Modes
03-15-09, 09:16 AM   #1
PeterP
A Murloc Raider
Join Date: Mar 2009
Posts: 5
Smile lua beginner question

greetings

i am quite new to develop own addons and the few tutorials that are out there just let a few questions open. maybe you can help:

i am trying to create a simple tooltip when mouse hovers a frame. i already got:

Code:
function showtooltip()
	local testtip = CreateFrame("GameTooltip", "ToolTipName") -- Where do i need the ToolTipName for example? Is it even neccessary to declare?
	testtip:SetFrameStrata("TOOLTIP")
	testtip:SetClampedToScreen(true)
	testtip:SetOwner(f, "ANCHOR_CURSOR")
	testtip:SetText("tooltipText", 1, 1, 1)  -- Whats the difference between SetText and Addline?
	testtip:AddLine("tooltipText", 1, 1, 1) 
	testtip:Show()
end


f = CreateFrame("Frame",nil,UIParent)
f:SetFrameStrata("BACKGROUND")
f:SetWidth(500)
f:SetHeight(500)
f:SetScript("OnEnter", showtooltip)

t = f:CreateTexture(nil,"BACKGROUND")
t:SetTexture(1, 1, 1, 1)
t:SetAllPoints(f)
f.texture = t

f:SetPoint("CENTER",0,0)
f:Show()
the frame with the layer shows up ingame properly, but the tooltip hover isnt working. no error messages are shown.

thnx for your help,

peter
  Reply With Quote
03-15-09, 09:52 AM   #2
Maul
Ion Engines, Engage!
 
Maul's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2005
Posts: 401
You have a few issues

First -

testtip:SetOwner(f, "ANCHOR_CURSOR")

"f" is not within the scope of that function, since you declare it after that function. "f" is nil when that function is called.

However, this line -

f:SetScript("OnEnter", showtooltip)

intrinsically passes the "self" variable to the function. That line is the same for (your purposes) as -

f:SetScript("OnEnter", function(self) showtooltip(self) end)

Therefore, this is an easy fix-

Change-

function showtooltip()
-to
function showtooltip(self)

and

testtip:SetOwner(f, "ANCHOR_CURSOR")
-to
testtip:SetOwner(self, "ANCHOR_CURSOR")

As it is now, your code is trying to set the tooltip owner to a non-existent frame, as far as the showtooltip() function is concerned.

Also, each time your showtooltip() function is called, it is creating a new frame object, something you do not want to do. So you will want to create your tooltip frame outside of the function to show your tooltip. Also, your tooltip frame has no font objects since you did not inherit the game's tooltip template or create your own font objects.

Your main frame is also not set to receive mouse input.

And one small point which does not affect functionality right now is that you will want to make sure your variables are either local if they are simple (like "f") or unique if declared as globals (like: "MyAddons_F_Variable"). Your current code is declaring "f" as a global and that could easily run afoul of other addons. This goes the same for functions.

Here is your code in a working manner -

Code:
--moved out of the showtooltip function, so as not to create a new frame each time OnEnter fires
local testtip = CreateFrame("GameTooltip", "ToolTipName", UIParent, "GameTooltipTemplate")
testtip:SetFrameStrata("TOOLTIP")
testtip:SetClampedToScreen(true)

--declare functions locally since we most likely do not need them as globals
local function showtooltip(self)
	testtip:SetOwner(self, "ANCHOR_CURSOR") -- change to reference a reachable variable
	testtip:SetText("tooltipText", 1, 1, 1)
	testtip:AddLine("tooltipText", 1, 1, 1)
	testtip:Show()
end

local function hidetooltip(self)
	testtip:Hide()
end

-- declare simple variables as locals to avoid problems
local f = CreateFrame("Frame",nil,UIParent)
f:EnableMouse(true) --enable mouse input for the frame
f:SetFrameStrata("BACKGROUND")
f:SetWidth(500)
f:SetHeight(500)
f:SetScript("OnEnter", showtooltip)
f:SetScript("OnLeave", hidetooltip) --hide the tooltip on leaving the frame, or it will remain stuck to the cursor

local t = f:CreateTexture(nil,"BACKGROUND")
t:SetTexture(1, 1, 1, 1)
t:SetAllPoints(f)
f.texture = t

f:SetPoint("CENTER",0,0)
f:Show()
As for naming your tooltip, that is up to you if you think you will need to access it outside the scope of your code.

SetText is usually used to "initialize" a tooltip with text. AddLine implies that lines of text already exist in the tooltip
__________________

Twitter: @IonMaul | Windows Live: [email protected] | Google Talk: [email protected]

Last edited by Maul : 03-15-09 at 09:59 AM.
  Reply With Quote
03-15-09, 10:14 AM   #3
PeterP
A Murloc Raider
Join Date: Mar 2009
Posts: 5
Smile

thank you so much maul,

your answers are very detailed and i think i slowly begin to understand how lua is working it tried your code and it worked perfectly.

but nevertheless there is still something i dont understand

when we define the function
Code:
local function showtooltip(self)
	testtip:SetOwner(self, "ANCHOR_CURSOR") -- change to reference a reachable variable
	testtip:SetText("tooltipText", 1, 1, 1)
	testtip:AddLine("tooltipText", 1, 1, 1)
	testtip:Show()
end
we define a parameter called self. self should be the frame to which we will attach the gametooltip. but when we execute the f:SetScript("OnEnter", showtooltip) we dont tell whats the content of the parameter "self". i dont know, but in other languages i have to set the arguments, when the function is working with parameters. i am a bit confused about that. maybe you can explain

best greetings

peter

p.s. pls excuse my english - hope you got what i mean
  Reply With Quote
03-15-09, 10:16 AM   #4
spiel2001
nUI's Author
 
spiel2001's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2008
Posts: 7,724
Okay... a couple of things... unless declared otherwise, all variables are global... so declaring a variable "f" and doing something with it is begging for something to get broken somewhere. Be careful how you use variables.

That said, do you need a new separate tooltip frame, or just to display in the existing tooltip frame? The following should accomplish the latter...

Code:
local f = CreateFrame("Frame",nil,UIParent)

function showtooltip()
    GameTooltip:SetOwner(f, "ANCHOR_CURSOR")
    GameTooltip:SetText("tooltipText", 1, 1, 1)  -- SetText "empties" the current tooltip frame and adds this text as the first line in the tooltip
    GameTooltip:AddLine("tooltipText", 1, 1, 1)  -- add line appends a line to the end of whatever is already in the tooltip
    GameTooltip:Show()
end

f:SetFrameStrata("BACKGROUND")
f:SetWidth(500)
f:SetHeight(500)
f:SetScript("OnEnter", showtooltip)

local t = f:CreateTexture(nil,"BACKGROUND")
t:SetTexture(1, 1, 1, 1)
t:SetAllPoints(f)
f.texture = t

f:SetPoint("CENTER",0,0)
f:Show()
Two invaluable resources to look at...

http://www.wowwiki.com/Portal:Interface_customization
http://www.lua.org/manual/5.1/
__________________

What people don't get is that I am, ultimately, an artist at heart.
My brush has two colors, 1 and 0, and my canvas is made of silicon.



Official nUI Web Site: http://www.nUIaddon.com
Official nUI Support Forum: http://forums.nUIaddon.com
My day job: http://www.presidio.com/
  Reply With Quote
03-15-09, 11:47 AM   #5
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
spiel2001's way is the way that it is usually done, unless you have a specific reason for needing to create your own tooltip.

Also, keep in mind that the way you had it set up originally, you were creating a new tooltip frame every single time you moused over your frame. This creates tons of garbage.

edit: I see you posted the same question in another (incorrect) forum. I have merged them into this thread.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh


Last edited by Seerah : 03-15-09 at 11:56 AM.
  Reply With Quote
03-15-09, 12:03 PM   #6
Maul
Ion Engines, Engage!
 
Maul's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2005
Posts: 401
Script handlers are implicitly wrapped in a function declaration. Certain local variables are automatically created and are passed to a called function within the script handler.

If you look at this from the XML perspective -

<OnEnter>
MyAddonFunc(self, motion)
</OnEnter>

"self" and "motion" are automatically declared and values assigned when the script handler executes.

It is the same for :SetScript() in that the only valid value for the second argument is a function, the script handler passes the function the implicit variables belonging to the handler.

And as I mentioned, if you really wanted to, you can define the function yourself -

f:SetScript("OnEnter", function(self, motion) showtooltip(self, motion) end)

The above method should only be used if you wanted to add variables that are passed. Otherwise, it is the same as -

f:SetScript("OnEnter", showtooltip)

The script handler "OnEnter" will "behind the scenes" pass the function its local variables it declares and assigns values to.

Here is a list of what variables are declared and assigned for each script handler upon execution -

* OnAttributeChanged: function(self,name,value)
* OnChar: function(self,text)
* OnCharComposition: function(self,text)
* OnClick: function(self,button,down)
* OnColorSelect: function(self,r,g,b)
* OnCursorChanged: function(self,x,y,w,h)
* OnDoubleClick: function(self,button)
* OnDragStart: function(self,button)
* OnEnter: function(self, motion)
* OnEvent: function(self,event,...)
* OnHorizontalScroll: function(self,offset)
* OnHyperlinkClick: function(self,link,text,button)
* OnHyperlinkEnter: function(self,link,text)
* OnHyperlinkLeave: function(self,link,text)
* OnInputLanguageChanged: function(self,language)
* OnKeyDown: function(self,key)
* OnKeyUp: function(self,key)
* OnLeave: function(self, motion)
* OnMouseDown: function(self,button)
* OnMouseUp: function(self,button)
* OnMouseWheel: function(self,delta)
* OnMovieShowSubtitle: function(self,text)
* OnScrollRangeChanged: function(self,xrange,yrange)
* OnSizeChanged: function(self,w,h)
* OnTooltipAddMoney: function(self,cost)
* OnUpdate: function(self,elapsed)
* OnValueChanged: function(self,value)
* OnVerticalScroll: function(self,offset)
* PostClick: function(self,button,down)
* PreClick: function(self,button,down)

I have the above list saved in a text file for my own personal reference.
__________________

Twitter: @IonMaul | Windows Live: [email protected] | Google Talk: [email protected]

Last edited by Maul : 03-15-09 at 12:08 PM.
  Reply With Quote
03-15-09, 12:35 PM   #7
PeterP
A Murloc Raider
Join Date: Mar 2009
Posts: 5
thnx

thanks,

spiel2001: i found your solution very often in various addons, but did not understand them before. now i can image that each frame already has its standard gametooltip object, so i dont need to create an own object. hope i got it right.

maul: ""self" and "motion" are automatically declared and values assigned when the script handler executes." - thats what i needed to know. also thank you for your helpful list. i already saved it


the last hours i read a bit about tables and one little question came up:

Code:
local table = {}
table[1] = "combat"
table[2] = "health"

local function combat()
-- ...
end

local function health()
--...
end

-- now i would like to execute all functions , that are listet in my tables database. i tried:

for i, v in pairs(table) do
	v()  -- i thought he would replace "v" with its content end then open the apropriate function...
end
when i execute this script i just got this error: "attemp to call local "v" (a string value)" i suppose i am lacking an important information about variables or expressions, but didnt found anything useful in the official lua manual (or didnt understand it correctly )

maybe s.o. can help

greetings,
peter
  Reply With Quote
03-15-09, 12:46 PM   #8
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Table rows in lua can be functions itself.
  Reply With Quote
03-15-09, 12:53 PM   #9
spiel2001
nUI's Author
 
spiel2001's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2008
Posts: 7,724
Strings and methods are not interchangeable like that.

Code:
 
-- declare your methods first...

local function combat()
-- ...
end

local function health()
--...
end

-- then build the table that references the methods... 
-- note the lack of quotes, 
-- you also need a comma to separate each row in the table.

local table = 
{
    [1] = combat,
    [2] = health,
 }

-- now i would like to execute all functions , that are listet in my tables database. i tried:

for i in pairs(table) do
    table[i]()
end
__________________

What people don't get is that I am, ultimately, an artist at heart.
My brush has two colors, 1 and 0, and my canvas is made of silicon.



Official nUI Web Site: http://www.nUIaddon.com
Official nUI Support Forum: http://forums.nUIaddon.com
My day job: http://www.presidio.com/
  Reply With Quote
03-15-09, 01:01 PM   #10
Maul
Ion Engines, Engage!
 
Maul's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2005
Posts: 401
As mentioned, table values can be any valid value type.

To assign a table value a function, the function has to first exist. Again this has to do with the scope of a variable.

Imagine your lua file as a time line. The beginning of the file is the start of time, and the end of the file is the end of time. At the end of time, you know all that has transpired previously. Near the beginning of time, you only know of what has happened so far.

To modify your code -
Code:
local table = {}

local function combat()
-- ...
end

table[1] = combat

local function health()
--...
end

table[2] = health

for i, v in pairs(table) do
	v()
end
Notice the values are not strings, but direct references to the functions themselves. This is what mrruben5 means.

To simplify your code, and perhaps make it more useful, you could do -

Code:
local table

local function combat()
-- ...
end

local function health()
--...
end

table = {
	[1] = combat,
	[2] = health,
}

for i, v in pairs(table) do
	v()
end
Since "table" is declared at the start of the code block, the rest of the code is "aware" of table. So when you assign values to table at a later time, the code at the beginning can still reach those values.
__________________

Twitter: @IonMaul | Windows Live: [email protected] | Google Talk: [email protected]
  Reply With Quote
03-15-09, 01:26 PM   #11
PeterP
A Murloc Raider
Join Date: Mar 2009
Posts: 5
Thumbs up

okay, it all works perfectly now. i really have to keep in mind the "timeline" thing - thank you guys

wish you a nice evening

peter
  Reply With Quote
03-15-09, 02:36 PM   #12
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Originally Posted by PeterP View Post
thanks,

spiel2001: i found your solution very often in various addons, but did not understand them before. now i can image that each frame already has its standard gametooltip object, so i dont need to create an own object. hope i got it right.
Not quite. The GameTooltip referenced in spiel2001's code *is* the game's tooltip. You would just be borrowing it for a moment.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » lua beginner question


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off