n00b perspective on LUA

n00b perspective on LUA

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

n00b perspective on LUA

Post by Zpock »

I'm trying to learn LUA, and rival this thread:
http://spring.clan-sy.com/phpbb/viewtopic.php?t=11695
The first thing I want to do is draw something, anything on the screen, and go from there.

The Files

1. So I start off with the first problem every n00b asks himself, what file is needed, where. Of course overlooked in all guides (not that there's any guides on LUA to begin with :cry: ) since it's so blatantly trivial and obvious to all who knows how. In notepad .lua files look a bit screwed up. So to probperly edit/make lua files you seem to need a LUA editor, this is the 1st step for the aspiring LUA n00b. With the editor setup and opening the scarce .lua files available can be opened to have a look. They seem to reside in 2 natural habitats. The spring/luaUI folder, and in the /LuaRules folder inside a specific mods own folder. The latter is the gadgetz, who are understood to be used for making up custom game mechanics. The ones in /LuaUi is for making universal UI mods. There's also a few other folders where LUA files can be found, like LuaCOB, for LUA thats integrated with cob scripts. Being Primarily interested in making my own game mechanics, the gadgetz are my primary interest. An important question still remains regarding what/where of files. Am I supposed to call the files in a certain way, or do I just put in whatever I want, like main.lua, myluafile.lua, etc and spring dosn't care at all? It seems so.

The Examples
2. Now that the where/what question of LUA files is getting a bit more clear it's time to review what example files there are to be scavanged for information. For gadgetz, the only source that I know of is CA. However, the stuff in there turns out to be a maddening experience. There are several separate CA .sdz files, with LUA files of interest spread around them. There seems to be a net of dependencies that is very hard to navigate being a total lua-n00b. The deployment stuff naturally seems interesting, it draws some stuff on the screen...

Unfortunately it also contains about 2k lines of code. Most of it seems like random stuff drawing things you would expect to find in the spring rendering code itself, for example:

Code: Select all

local function DrawReadyTeams(vsx, vsy)
  local teams = SYNCED.teams
  if (not teams) then
    return
  end

  local readys = {}
  for teamID, team in spairs(teams) do
    local id, leader, active, dead = Spring.GetTeamInfo(teamID)
...etc
...etc
Isolating what you need to draw just some basic text or whatever from this seems next to impossible. Moving on, there's a bunch of widgets in the mentioned LuaUI folder. Of course, I have a feeling that writing widgetz is different from writing gadgetz. However, the widgetz contains some little standalone things that supposedly just draw some little thing like a clock. The clock widget seems like a good place to look indeed! Opening it up, the first thing noticed is that it's a shocking 200 lines of code ! :shock: Most of it seems to be for making sure the clock is placed in the right place. There seems to be multiple functions in here just to do this, for example:

Code: Select all

local function UpdateGeometry()
  -- use the fractions if available
  xpos = (xposf and (xposf * vsx)) or xpos
  ypos = (yposf and (yposf * vsy)) or ypos
  size = (sizef and (sizef * vsy)) or size
  -- negative values reference the right/top edges
  xpos = (xpos < 0) and (vsx + xpos) or xpos
  ypos = (ypos < 0) and (vsy + ypos) or ypos
end
Obviously, while all this is probably needed for some reasons, is 100% reliable and well coded etc, but surely we don't really need to get into this just to put some random crap on the screen? What it all boils down to is this:

Code: Select all

    gl.Text(timestring, xpos, ypos, size, format)
Ok, so here is finally some interesting code. Apparantly, this is the line to print some stuff on the screen. The parameters seem simple enough to grasp. The first is what should be written, then where and what size. The format parameter is more mysterious of course, the wiki gives some hint here, but surely it should be fine to simply put it empty for our purposes?? Anyway what's the kind of unit for the positions and stuff? Simple enough, lets see what the clock says if we put like this instead:

Code: Select all

    gl.Text(xpos, 500, ypos, size, format)
Note that the clock should now write out the xpos variable, and put 500 in its place. It turns out that conveniently enough, the unit is screen pixels. Ok, so if we want to write some simple text, something like this should do it:

Code: Select all

gl.Text("AIHFOIAHDIOFHODIAHFOIHA", 500, 100, 15, "")

The Garbage

3. So now the real question is, how much random junk is needed around this line to make it actually work? We need a function I think, something like:

Code: Select all

function DrawScreen()
  gl.Text("AIHFOIAHDIOFHODIAHFOIHA", 1000, 100, 15, "")
end
The drawscreen function is what seems most commonly used for this kind of stuff, for example the clock uses exactly this function. It looks like this there tough:

Code: Select all

function widget:DrawScreen()
Looking in actual gadget files (from CA), it seems like the "widget:" part should simply be removed when making a gadget. Next, we consider it might be needed to have some color. This is confusing, the wiki mentions something about:
'n' = deactives colorCodes (so you can use gl.Color() to write transparent text etc.)
I have no idea what that means. The clock uses this format option, and it has some line:

Code: Select all

include("colors.h.lua")
Spring complains about this line when placed in a gadget tough, so I'm assuming this is best simply ignored for making a simple as possible gadget. To put some colour we need a line along these lines:

Code: Select all

function DrawScreen()
  gl.Color(1, 1, 1)
  gl.Text("AIHFOIAHDIOFHODIAHFOIHA", 1000, 100, 15, "")
end
Next, looking at the clock widget, theres some stuff above the drawing line like:

Code: Select all

  if (fh) then
    fh = fontHandler.UseFont(font)
    fontHandler.DisableCache()
    fontHandler.DrawRight(GetTimeString(), floor(xpos), floor(ypos))
    fontHandler.EnableCache()
  else
Something tells me this has to do with fonts, and possibly is needed for writing stuff? However in other widgets I didn't find anything similar so I assume it's just some random stuff trepan put in for the sake of it.

Knowing opengl, there is usually A LOT more of setup junk needed to get started. However, most of the stuff should be there alredy in spring I think, so I have no idea what more is needed. Usually you have to orient where stuff is put on the screen and stuff, with juicy matrix maths and stuff. However for writing some text on screen coordinates, this I think is not really what's missing.

The PHAIL
Still, there's no sign of any text on the screen, the only sign that my LuaRules/main.lua file is poked at by spring at all is the error message about the include line I tried putting in. This is as far as I got for today now running out of time.
User avatar
quantum
Posts: 590
Joined: 19 Sep 2006, 22:48

Post by quantum »

This a basic text display widget:

Code: Select all

function widget:GetInfo()
  return {
    name      = "a",
    desc      = "b",
    author    = "c",
    date      = "d",
    license   = "e",
    layer     = 0,
    enabled   = false  --  loaded by default?
  }
end

local text = "hi"
local x, y = 100, 100
  
function widget:DrawScreen()
  fontHandler.Draw(text, x, y)
end
To make a gadget instead, copy the LuaRules folder from CA-r*.sdz, go to the LuaRules/Gadgets folder, delete the existing gadgets, and save this:

Code: Select all

function gadget:GetInfo()
  return {
    name      = "1",
    desc      = "2",
    author    = "3",
    date      = "4",
    license   = "5",
    layer     = 0,
    enabled   = true  --  loaded by default?
  }
end

local text = "hi"
local x, y = 100, 100
local size = 20
local options = nil

function gadget:DrawScreen()
  gl.Text(text, x, y, size, options)
end
We are using gl.Text instead of the text handler, because the latter is not included in LuaRules (at least in CA).

Sorry if it's not much help, I'm a bit in a rush at the moment.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Post by jK »

Cos rendering is only possible in unsynced code, you should only run it there (but it wouldn't crash if you don't check it, because DrawScreen() isn't called in synced code)

so this is recommended:

Code: Select all

function gadget:GetInfo() 
  return { 
    name      = "1", 
    desc      = "2", 
    author    = "3", 
    date      = "4", 
    license   = "5", 
    layer     = 0, 
    enabled   = true  --  loaded by default? 
  } 
end 

if (not gadgetHandler:IsSyncedCode()) then
  local text = "hi" 
  local x, y = 100, 100 
  local size = 20 
  local options = nil 

  function gadget:DrawScreen() 
    gl.Text(text, x, y, size, options) 
  end
end
And yup there are 2 ways top draw text gl.Text and a fontHandler. Like Quantum said the second is only available in LuaUI, cause it is a lua header file (perhaps you can port it to LuaRules, duno).

The "n" parameter disables colorcodes. Those are specific charcodes in the given string, perhaps you already saw them in IRC or under linux (bash). Some of those codes are defined in the headerfile "colors.h.lua", so if you include this file into your widget/gadget, you can write things like

Code: Select all

gl.Text(RedStr .. "warning!",1,2,3,"");
The advantage of those colorcodes is that you can change the color of a single char/word/line/string in the drawn text.
But sometimes you want to deactivate those colorcodes with "n", because you don't generate the text yourself and don't want a colorized text (e.g. tooltip string contain colorcodes) or want to use gl.Color to colorize the whole text in one color or you only want to speed your code up (colorcodes are (much?) slower).

PS: The gl.Color(1,1,1,1) is used to avoid blending. Cause all gl primitves are blended with glColor, so if you use gl.Color(1,0,0,1) and then draw your text, it would be red (even without "n" param!). So if you set gl.Color to something else than 1,1,1,1 (full opac white), don't forget to reset it, else other widget/gadgets, which would be called after yours would be rendered in that color, too!
User avatar
quantum
Posts: 590
Joined: 19 Sep 2006, 22:48

Re: n00b perspective on LUA

Post by quantum »

Am I supposed to call the files in a certain way, or do I just put in whatever I want, like main.lua, myluafile.lua, etc and spring dosn't care at all? It seems so.
I think Spring only looks for "main.lua" and "draw.lua" in the LuaUI, LuaRules, LuaGaia and LuaCob folders. You could put your code there, but it's easier to use trepan's gadget/widget handler, which forwards the call-ins to widgets or gadgets, and sends the call-outs back.

Widgets and gadgets can have any name that ends in .lua, but need a global "widget:GetInfo" or "gadget:GetInfo" function.
Post Reply

Return to “Lua Scripts”