[Lua] Best Way To Register Mouse Selection?

daviiadams

Prince
Joined
Jul 7, 2011
Messages
369
Location
London
I'm trying to allow for civ specific icons to be selectable (to bring up the diplomacy/deal/discuss with leader screen) but so far my attempts result in the screen coming up without any action performed by the player.

The icons are controlled within a loop, with no instance info involved and I'm trying using seperate functions similar to the way ToolTips are done, but haven't come good yet.

Is their a preferred way to go about this?
 
... but so far my attempts result in the screen coming up without any action performed by the player.

This usually means you've called the function when registering, and not passed a reference to the function, eg

Code:
Controls.Register(MyFunction()) -- WRONG, the () call the function

vs

Code:
Controls.Register(MyFunction) -- RIGHT, just pass the (pointer to the) function
 
This usually means you've called the function when registering, and not passed a reference to the function, eg

Code:
Controls.Register(MyFunction()) -- WRONG, the () call the function

vs

Code:
Controls.Register(MyFunction) -- RIGHT, just pass the (pointer to the) function

Is "Register" in those examples the method involved? I'd been trying to use RegisterCallback in this sort of way:

Code:
function CivSelection()

     for ePlayer = 1, GameDefines.MAX_MAJOR_CIVS-1, 1 do
          civSelected = string.format("CivIcon%i", ePlayer);
          Controls[civSelected]:RegisterCallback(Mouse.eLClick, OnCivSelected(ePlayer));
     end
end
 
I'd been trying to use RegisterCallback in this sort of way:

Code:
function CivSelection()
  for ePlayer = 1, GameDefines.MAX_MAJOR_CIVS-1, 1 do
    civSelected = string.format("CivIcon%i", ePlayer);
    Controls[civSelected]:RegisterCallback(Mouse.eLClick, OnCivSelected(ePlayer));
  end
end

The issue with that code is that RegisterCallback() requires a "pointer to a function" as its second parameter, eg

Code:
Controls[civSelected]:RegisterCallback(Mouse.eLClick, OnCivSelected);

Note the lack of brackets after the function name.

What you are passing is whatever invoking OnCivSelected(ePlayer) returns (probably nil), and the side effect of that is that the UI displays.

But you need to pass ePlayer as a parameter, so you need a way to "wrap up" OnCivSelected(ePlayer) into a function, and pass that into RegisterCallback.

Welcome to the world of closurers (see http://en.wikipedia.org/wiki/Closure_(computer_science) and http://www.lua.org/pil/6.1.html)

What you need is

Code:
function CivSelection()
  for ePlayer = 1, GameDefines.MAX_MAJOR_CIVS-1, 1 do
    civSelected = string.format("CivIcon%i", ePlayer);
    Controls[civSelected]:RegisterCallback(Mouse.eLClick, [B][COLOR="Red"]function() OnCivSelected(ePlayer) end[/COLOR][/B]);
  end
end
 
Code:
function CivSelection()
  for ePlayer = 1, GameDefines.MAX_MAJOR_CIVS-1, 1 do
    civSelected = string.format("CivIcon%i", ePlayer);
    Controls[civSelected]:RegisterCallback(Mouse.eLClick, [B][COLOR="Red"]function() OnCivSelected(ePlayer) end[/COLOR][/B]);
  end
end

That was the first thing I tried, as you'd advised on this at other times for similar situations, but get "attempt to call method 'RegisterCallback' (a nil value)" :confused:
 
but get "attempt to call method 'RegisterCallback' (a nil value)" :confused:

That means that the object "Controls[civSelected]" has no method "RegisterCallback()" so check what the CivIcon1 thru CivIcon21 controls are, and that you actually have them all present
 
That means that the object "Controls[civSelected]" has no method "RegisterCallback()" so check what the CivIcon1 thru CivIcon21 controls are, and that you actually have them all present

I'd assumed that the rest of the loop prior to that point would fail if the xml referrences were wrong?

The icons are contained within boxes, would that obscure them from RegisterCallback?
 
I'd assumed that the rest of the loop prior to that point would fail if the xml referrences were wrong?
If the control is missing, misnamed or not named as the string format, Controls[civSelected] will return nil and nil:RegisterCallback() will generate the error message you're seeing

The icons are contained within boxes, would that obscure them from RegisterCallback?
Depends if you have given the ID to the box (which then won't have a RegisterCallback() method, or the icon (which will)

Rather than keep second guessing what may or may not be in the xml and lua files, probably just easiest to attach the files
 
Depends if you have given the ID to the box (which then won't have a RegisterCallback() method, or the icon (which will)

Which will ... always assuming the icon is in a text string ... which it isn't!

Code:
<Box Anchor="C,C" Offset="C,C" Size="32,32" Padding="4" Color="0.0.0.200" ID="IconBox0">
  <Image Anchor="C,C" Size="32.32" Texture="CivSymbolsColor256.dds" ID="CivIcon0" ToolTipType="TooltipTypeEOT"/>
</Box>

Images arn't clickable, you'll need to wrap the image tag with a button tag and then register the callback to the button ID
 
Which will ... always assuming the icon is in a text string ... which it isn't!

Code:
<Box Anchor="C,C" Offset="C,C" Size="32,32" Padding="4" Color="0.0.0.200" ID="IconBox0">
  <Image Anchor="C,C" Size="32.32" Texture="CivSymbolsColor256.dds" ID="CivIcon0" ToolTipType="TooltipTypeEOT"/>
</Box>

Images arn't clickable, you'll need to wrap the image tag with a button tag and then register the callback to the button ID

Something like this?

Code:
<Button ID="CivIconButton0"........> 
     <Box Anchor="C,C" Offset="C,C" Size="32,32" Padding="4" Color="0.0.0.200" ID="IconBox0">
          <Image Anchor="C,C" Size="32.32" Texture="CivSymbolsColor256.dds" ID="CivIcon0" ToolTipType="TooltipTypeEOT"/>
     </Box>
</Button>
 
Code:
<Box Anchor="C,C" Offset="C,C" Size="32,32" Padding="4" Color="0.0.0.200" ID="IconBox0">
  <Button ID="CivIconButton0"........> 
    <Image Anchor="C,C" Size="32.32" Texture="CivSymbolsColor256.dds" ID="CivIcon0" ToolTipType="TooltipTypeEOT"/>
  </Button>
</Box>
 
Ah ok, I had thought that first when I replied, only to change it in case the containing box needed to be included.

I shall give this a whirl once I'm home later :)
 
There is a hierarchy to the controls

Box, Container and Grid are all layout elements - think of them as the scaffold
Button (and sub-versions) are the things we interact with
Labels and Images are the decoration

Obviously there are exceptions, but I find that's a good staring point!

[It also doesn't help that some items can be used for more than one purpose (eg TextButton)]
 
It worked like a charm and makes EOT very handy indeed, thanks for the help :)

I feel i'm gradually getting to grips with Lua/xml, though have to admit that I tend to need to re learn things more often than I expect to. Though, no doubt that goes hand in hand with working on mods in fits and starts!
 
Back
Top Bottom