Reading key events from irrlua
Reading key events from irrlua
Could someone explain how to read key presses with irrlua? The gui example is slightly different than the c++ example. It uses a OnGuiEvent and a strange iir.createIEventReceiver method that doesn't exist in the c++ version.
Edit: Ok i found some documentation on the net.
But this means that we can't use the OnEvent method anymore with an event handler?
And is it possible to do this?
myEventHandler = irr.createIEventReceiver(myEventHandler)
Edit: Ok i found some documentation on the net.
But this means that we can't use the OnEvent method anymore with an event handler?
And is it possible to do this?
myEventHandler = irr.createIEventReceiver(myEventHandler)
To read keypresses you should use OnKeyEvent (Key, PressedDown, Shift, Control)... OnGuiEvent deals with gui controls and windowsBut this means that we can't use the OnEvent method anymore with an event handler?
The file 04.Movement.lua has it explained
Not only possible, but what should be done!And is it possible to do this?
myEventHandler = irr.createIEventReceiver(myEventHandler)
OK thanks i have it working. But now im not reading mouse input. Whenever i move the mouse inside the window it should receive mouse motion events. Must i do something before that to read mouse events?
Heres the lua code:
Heres the lua code:
Code: Select all
require "IrrLua"
-- game global state
SFglobal = {}
-- global data path
SFglobal.dataPath = "../Data"
-- irrlicht related state
SFglobal.irr = {}
SFglobal.irr.device = {}
SFglobal.irr.eventHandler = {}
-- default IrrLua event handlers
function SFglobal.irr.eventHandler:OnKeyEvent(Key, PressedDown, Shift, Control)
print("keyboard event received ", Key, PressedDown)
SFglobal.gui.ship1.x = SFglobal.gui.ship1.x + 1
return true
end
function SFglobal.irr.eventHandler:OnMouseEvent(Event, X, Y, Wheel)
print("Mouse event received ", X, Y)
return false
end
function SFglobal.irr.eventHandler:OnGuiEvent(Event, Caller)
return false
end
function SFglobal.irr.eventHandler:OnLogTextEvent(Event, Text)
return false
end
function SFglobal.irr.eventHandler:OnUserEvent(UserData1, UserData2, UserData3)
return false
end
function SFinit(width, height, depth, fullscreen)
SFglobal.irr.device = irr.createDevice(irr.video.EDT_DIRECT3D8,
irr.core.dimension2d(width, height), depth,
fullscreen, false, false)
local device = SFglobal.irr.device
if device == nil then return 0 end
SFglobal.irr.eventHandler = irr.createIEventReceiver(SFglobal.irr.eventHandler)
device:setEventReceiver(SFglobal.irr.eventHandler)
return 1
end
function SFquit()
SFglobal.irr.device:drop()
return 0
end
function SFinitGUI()
local dataPath = SFglobal.dataPath
local device = SFglobal.irr.device
local driver = device:getVideoDriver();
local guienv = device:getGUIEnvironment();
-- load fonts
SFglobal.gui = {}
SFglobal.gui.default = {}
SFglobal.gui.default.fonts = {}
local fontPath = SFglobal.dataPath .. "/GUI/Style/Default/f"
local fonts = {}
fonts.builtin = guienv:getBuiltInFont()
fonts.fixedfont = guienv:getFont(fontPath .. "/SF_FixedFont-10px.png")
fonts.smallfont = guienv:getFont(fontPath .. "/SF_SmallFont-10px.png")
SFglobal.gui.default.fonts = fonts
-- load two space ships for testing purposes
SFglobal.gui.ship1 = {}
SFglobal.gui.ship1.i = driver:getTexture(SFglobal.dataPath .. "/Entity/Ship/Arth/i/challenger.png")
SFglobal.gui.ship1.r = irr.core.rect(0,0,64,64)
SFglobal.gui.ship1.x = 100
SFglobal.gui.ship1.y = 100
SFglobal.gui.ship2 = {}
SFglobal.gui.ship2.i = driver:getTexture(SFglobal.dataPath .. "/Entity/Ship/Arth/i/wyltakin.png")
SFglobal.gui.ship2.r = irr.core.rect(0,0,64,64)
SFglobal.gui.ship2.x = 150
SFglobal.gui.ship2.y = 100
end
function SFdrawSprite(sprite)
local device = SFglobal.irr.device
local driver = device:getVideoDriver();
driver:draw2DImage(sprite.i, irr.core.position2d(sprite.x,sprite.y), sprite.r, nil,
irr.video.SColor(255,255,255,255), true)
end
function SFdrawText(font,text,x,y,w,h)
local device = SFglobal.irr.device
local driver = device:getVideoDriver();
local guienv = device:getGUIEnvironment();
font:draw(text, irr.core.rect(x,y,x+w,y+h), irr.video.SColor(255,255,255,255))
end
function SFdisplay()
local dataPath = SFglobal.dataPath
local device = SFglobal.irr.device
local driver = device:getVideoDriver();
local guienv = device:getGUIEnvironment();
local scnmgr = device:getSceneManager();
local time = 0
while device:run() do
driver:beginScene(true, true, irr.video.SColor(0,0,0,0))
local fonts = SFglobal.gui.default.fonts
SFdrawText(fonts.fixedfont, "Hello World", 0, 0, 128, 16)
SFdrawSprite(SFglobal.gui.ship1)
SFdrawSprite(SFglobal.gui.ship2)
scnmgr:drawAll()
guienv:drawAll()
driver:endScene()
end
end
SFinit(800,600,32,false)
SFinitGUI()
SFdisplay()
SFquit()
return 0
It was me the guest up there, been wandering around this forum for a while before registering
I just tried OnMouseEvent, it does nothing. Looking at IrrLua sourcecode I've seen it uses instead OnMouseInputEvent, it worked I think I'll leave the author a message for him to fix it in the documentation.
I just tried OnMouseEvent, it does nothing. Looking at IrrLua sourcecode I've seen it uses instead OnMouseInputEvent, it worked I think I'll leave the author a message for him to fix it in the documentation.
Sorry about all that! I'll fix the docs...
The problem with using the event receiver the way Irrlicht does is that initially I simply could not get c++ unions to work with tolua++. SEvent is a union, and it wouldn't show up in the Lua side.
They do work now, but I haven't changed it to the way Irrlicht does event receivers for a couple reasons:
1. Lua does not have a switch statement. In C++ Irrlicht examples, how much do you see:
When you start to port nested switch statements from C++ to Lua, it gets really messy with if-then-else everywhere.
2. There would be a small performance hit due to the need to create a table for each event received. It's a small hit though and not really a good argument.
Should I change it back to the way irrlicht does it in the next release and avoid some confusion?
The problem with using the event receiver the way Irrlicht does is that initially I simply could not get c++ unions to work with tolua++. SEvent is a union, and it wouldn't show up in the Lua side.
They do work now, but I haven't changed it to the way Irrlicht does event receivers for a couple reasons:
1. Lua does not have a switch statement. In C++ Irrlicht examples, how much do you see:
Code: Select all
switch(Event.EventType)
{
case EET_GUI_EVENT:
s32 id = Event.GuiEvent.Caller->getID();
switch(id)
{
case 23:
case 24:
...
}
break;
case EET_MOUSE_INPUT_EVENT:
...
break;
}
When you start to port nested switch statements from C++ to Lua, it gets really messy with if-then-else everywhere.
2. There would be a small performance hit due to the need to create a table for each event received. It's a small hit though and not really a good argument.
Should I change it back to the way irrlicht does it in the next release and avoid some confusion?
zenaku wrote:They do work now, but I haven't changed it to the way Irrlicht does event receivers for a couple reasons:
I actually like the way it is done now, makes it a bit simpler to do something like this:zenaku wrote: Should I change it back to the way irrlicht does it in the next release and avoid some confusion?
Code: Select all
EventReceiver = {}
EventReceiver.ev = {}
EventReceiver.key = {}
-- Adds Events to the GUI event table
function EventReceiver:GUIAddEvent(id, event, func)
if EventReceiver.ev[id] == nil then EventReceiver.ev[id]={} end
EventReceiver.ev[id][event]=func
end
-- Calls the GUI event if it is in the ev table
function EventReceiver:OnGuiEvent(Event, Caller)
local id = Caller:getID()
if EventReceiver.ev[id] then
if EventReceiver.ev[id][Event] then
return EventReceiver.ev[id][Event](Caller)
end
end
return false
end
-- Adds functions to the key event tables
function EventReceiver:KeyAddEvent(Key, Down, Shift, Control, func)
local d = 0
local s = 0
local c = 0
if Down then d = 1 end
if Shift then s = 1 end
if Control then c = 1 end
if EventReceiver.key[Key] == nil then EventReceiver.key[Key]={} end
if EventReceiver.key[Key][d] == nil then EventReceiver.key[Key][d]={} end
if EventReceiver.key[Key][d][s] == nil then EventReceiver.key[Key][d][s]={} end
EventReceiver.key[Key][d][s][c]=func
end
-- Calls key events
function EventReceiver:OnKeyEvent(Key, Down, Shift, Control)
local d = 0
local s = 0
local c = 0
if Down then d = 1 end
if Shift then s = 1 end
if Control then c = 1 end
if EventReceiver.key[Key] then
if EventReceiver.key[Key][d] then
if EventReceiver.key[Key][d][s] then
if EventReceiver.key[Key][d][s][c] then return EventReceiver.key[Key][d][s][c]() end
end
end
end
return false
end
Code: Select all
EventReceiver:KeyAddEvent(irr.KEY_KEY_W, true, false, false, function() player.speed = player.speed+1 end)
gui:addButton(irr.core.rect(10,10,100,50), nil, 101, "Exit")
EventReceiver:GUIAddEvent(101,irr.gui.EGET_BUTTON_CLICKED, function() device:closeDevice() return true end )
Anyway, thanks for IrrLua, zenaku! It's been saving me a lot of work in my scholarship project at univ.!
Actually the docs were incorrect (although the irrlua sample source code is right).And is it possible to do this?
myEventHandler = irr.createIEventReceiver(myEventHandler)
---
Not only possible, but what should be done!
The docs had:
Code: Select all
local myNode = irr.scene.createISceneNode(smgr:getRootSceneNode(), smgr, -1, myNode)
It should have said:
Code: Select all
local myNode = irr.scene.createISceneNode(smgr:getRootSceneNode(), smgr, -1, CMySceneNode)
So in your case you would do:
Code: Select all
CMyEventReveiver = {}
function CMyEventReceiver:OnMouseInputEvent(Event, X, Y, Wheel)
if Event == irr.EMIE_LEFT_MOUSE_DOWN then
-- do some stuff
return true
end
return false
end
function main()
local receiver = irr.createIEventReceiver(CMyEventReceiver)
local device = irr.createDevice(irr.EDT_OPENGL, irr.core.dimension2d(640,480), 32, false, false, false, receiver)
-- or you could also do
-- local device = irr.createDevice(irr.EDT_OPENGL)
-- device:setEventReceiver(receiver)
end
I see... I haven't had any error using the same table in the arguments and at the assignment, but that might be because one doesn't usually use more than one event receiver at a timezenaku wrote: Actually the docs were incorrect (although the irrlua sample source code is right).
The docs had:
Code: Select all
local myNode = irr.scene.createISceneNode(smgr:getRootSceneNode(), smgr, -1, myNode)
You *could* do it either way, but you would have to assign the functions after you create the variable. Example:ElementoY wrote:I see... I haven't had any error using the same table in the arguments and at the assignment, but that might be because one doesn't usually use more than one event receiver at a timezenaku wrote: Actually the docs were incorrect (although the irrlua sample source code is right).
The docs had:
Code: Select all
local myNode = irr.scene.createISceneNode(smgr:getRootSceneNode(), smgr, -1, myNode)
Code: Select all
-- function to create new nodes
function createNode()
local myNode = irr.scene.createISceneNode(sgmr:getRootSceneNode(), smgr, -1, myNode)
--[[
you could even do:
local myNode = irr.scene.createISceneNode(sgmr:getRootSceneNode(), smgr, -1, {}) -- pass in empty table
--]]
myNode.Box = irr.core.aabbox3d(-1,-1,-1,1,1,1)
myNode.render = function()
local driver = SceneManager.getDriver()
driver:draw2DImage(...)
end
myNode.getBoundingBox = function()
return self.Box
end
return myNode
end
Oops... I misread that code, I thought you were talking about event receivers... in that case yes, it doesn't hold the table contents my bad!zenaku wrote:You *could* do it either way, but you would have to assign the functions after you create the variable.ElementoY wrote:I see... I haven't had any error using the same table in the arguments and at the assignment, but that might be because one doesn't usually use more than one event receiver at a timezenaku wrote: Actually the docs were incorrect (although the irrlua sample source code is right).
The docs had:
Code: Select all
local myNode = irr.scene.createISceneNode(smgr:getRootSceneNode(), smgr, -1, myNode)
I have another problem now. Im trying to use the xml classes and functions to read a game xml resource file. When i try to run the function:
irr.io.createIrrXMLReader
it says im atempting to call a nil field. This means that this function is not yet binded right?
If this is the case i can allways use lua scripts to take the place of xml resources but i would prefer to use Irrlicht xml api.
This is the code im using:
When i run this script i get the result:
irr.io.createIrrXMLReader
it says im atempting to call a nil field. This means that this function is not yet binded right?
If this is the case i can allways use lua scripts to take the place of xml resources but i would prefer to use Irrlicht xml api.
This is the code im using:
Code: Select all
require "IrrLua"
-- game global state
SFglobal = {}
-- global data path
SFglobal.dataPath = "../Data"
function SFgetXMLResource(filename)
print("--> start reading xml <--")
local dataPath = SFglobal.dataPath
print("Calling getXMLResource(", filename, ")")
------------- PROBLEM --------------------
local xmlr = irr.io.createIrrXMLReader(filename)
if (xmlr == nil) then return nil end
-- allowed states
-- START, STOP, SHIP, STAT, ANIM, SPRITE
local state = "START"
local resource = {}
while xmlr:read() do
local nt = xmlr:getNodeType()
if nt == irr.io.EXN_NONE then
print("None: ")
elseif nt == irr.io.EXN_ELEMENT then
print("Element: ", xmlr:getNodeName())
elseif nt == irr.io.EXN_ELEMENT_END then
print("ElementEnd: ", xmlr:getNodeName())
elseif nt == irr.io.EXN_TEXT then
print("Text: ", xmlr:getNodeData())
elseif nt == irr.io.EXN_COMMENT then
print("Comment: ")
elseif nt == irr.io.EXN_CDATA then
print("Cdata: ", xmlr:getNodeData())
elseif nt == irr.io.EXN_UNKNOWN then
else
end
end
xmlr:drop()
return resource
end
function SFgetResourceInstance(resource)
end
SFgetXMLResource(SFglobal.dataPath .. "/Entity/Ship/Numlox/NumloxScout.xml")
Code: Select all
Calling getXMLResource( ../Data/Entity/Ship/Numlox/NumloxScout.xml )
lua: sf3_irrlicht_plug.lua:63: attempt to call field `createIrrXMLReader' (a nil
value)
stack traceback:
sf3_irrlicht_plug.lua:63: in function `SFgetXMLResource'
sf3_irrlicht_plug.lua:178: in main chunk
[C]: ?
IrrXMLReader is currently unsupported.
IXMLReader works, however. See the example 09.MeshViewer.lua for details on how to use it.
Example:
These classes are currently not supported:
line2d
heapsort
IFileList
IReadFile
irrMath
irrString
IStringParameters
IWriteFile
irrList
irrXML
Irrlicht has IrrXMLReader, IrrXMLWriter, IXMLReader, and IXMLWriter. The 'I' versions should work. The 'Irr' versions use nested templates however. tolua++ supports templates, but I can't seem to get nested templates to work right.
IXMLReader works, however. See the example 09.MeshViewer.lua for details on how to use it.
Example:
Code: Select all
local xml = device:getFileSystem():createXMLReader(filename)
These classes are currently not supported:
line2d
heapsort
IFileList
IReadFile
irrMath
irrString
IStringParameters
IWriteFile
irrList
irrXML
Irrlicht has IrrXMLReader, IrrXMLWriter, IXMLReader, and IXMLWriter. The 'I' versions should work. The 'Irr' versions use nested templates however. tolua++ supports templates, but I can't seem to get nested templates to work right.