# Class: UtilFunctions

### LuxModule: luxinialuacore

The UtilFunctions class is a collection of miscellanous useful lua functions.

## Methods:

### Method overview:

- addWindowResizeListener
- checkargtable
- color3byte
- color3hsv
- color3rgb2hsv
- color4byte
- dofile
- fileexists
- freelook
- getModelColMesh
- loadCollisionDataFile
- loadFontFile
- loadfile
- luaDoFile
- luaLoadFile
- luafilename
- luafilepath
- pairsByKeys
- picktest
- printf
- removeWindowResizeListener
- serialize
- setTableValue
- simplerenderqueue
- smallLogoPos
- tabletotalcount

addWindowResizeListener (function)
  returns: ()
  will call function after window was resized (directly after window.update or with a few milliseconds delay if thru window.resizemode > 0.
checkargtable (table)
  returns: (table)

  This function provides a system to check table keys for values. This is useful if a functions is taking a table containing various "named" function arguments. The return value of this function is a table which provides sophisticated functionalities. If the table is called with a string as argument, it expects that a key in the table is to be checked and returns a table with possible value checking functions:

  1. type: checks if the value of this key is of a certain type
  2. optional: if the value is nil, the passed optional value is returned (may be nil)
  3. translate: expects an table to be passed. That table contains values that substitue the value of the key. A 2nd optional value is used if no value was found
  4. oneofthis: like translate, but doesn't substitute the original value

  If the field "finish" is called, the collected arguments will be returned in the order they've been checked

        local x,y,vx,vy,type = UtilFunctions.checkargtable(info)
          "x":type "number"
          "y":type "number"
          "vx":optional(0)
          "vy":optional(0)
          "type":oneofthis{["player"]=true, ["AI"]=true}
          :finish()

color3byte (float r,g,b)
  returns: (float r,g,b)
  converts the incoming color values 0-255, to 0-1 floats
color3hsv (float h,s,v)
  returns: (float r,g,b)
  converts the incoming hsv to color to 0-1 rgb floats
color3rgb2hsv (float r,g,b)
  returns: (float h,s,v)
  converts the rgb color to a hsv color value
color4byte (float r,g,b,a)
  returns: (float r,g,b,a)
  converts the incoming color values 0-255, to 0-1 floats
dofile (string path,...)
  returns: ()
  similiar to original dofile except that this function trys to find the file in different locations relative to all loaded luafiles. This function replaces the original dofile function.
fileexists (string path)
  returns: (boolean exists)

  tries out if the given file exists. This is not very clean since it only trys to open and close the file and if it doesn't throw an error it is assumed that the file exists.

freelook (boolean)
  returns: (boolean)
  enables/disables freelook of current default l3dcamera. Useful for debugging, FreeLook.invert .movemulti .shiftmulti let you modify behavior. Controls are WASD,C,SPACE + Mouse.
getModelColMesh (model,[boolean needrawtable],[matrix4x4],[boolean visibleonly],[boolean neednotrimeshdata])
  returns: (tableBase,tableHit,[tableRaw])

  Creates a geom trimeshdata from the given model. Optionally transforms vertices.
  tableBase : {data = dgeomtrimeshdata, aabox = {min{x,y,z},max{x,y,z}, center = {x,y,z}}
  tableHit : {table similar to base, but for every "hitmesh" = meshes that contain "hitzone" in the material name
  tableRaw : { inds = indices{}, verts = vertices{}, tris = tridata{{mesh=meshid,orig=original index}...} }, table with all indices/vertices and a table with the tridata for every face in the model

loadCollisionDataFile ([string path,table],[boolean needoriginaltable],[boolean createl3ds])
  returns: (dgeom table,[extratable])

  loads dgeoms from the collision data lua file. extratable can contain the tables: "original" and/or "visual".Currently exported by 3dsmax.

loadFontFile (string fontname)
  returns: (fontset,texture)
  loads a font generated by the Font Bitmap Generator. The fontname must not contain a suffix (.lua). The function trys to load a fontfile that must reside in a 'fonts' directory. You must not delete the fontset yourself. All characters in the fontset that are not set by the font itself are mapped to the glyphid 0 (lefttopmost glyph)
loadfile (string path,...)
  returns: ()
  similiar to original loadfile except that this function trys to find the file in different locations relative to all loaded luafiles. This function replaces the original loadfile function.
luaDoFile
  original lua dofile function
luaLoadFile
  original lua loadfile function
luafilename (int level)
  returns: (string filename)

  retrieves the filename of a luafunction, if possible. The level is the functioncallerstack and should be >=1 returns filename and level of the found path.

luafilepath (int level)
  returns: (string filepath)
  like luafilename, but removes the filename itself
pairsByKeys (table,[comperator])
  returns: (function)
  returns an iterator function to traverse the table in sorted order. The comperator function can be used to use another ordering for traversion. The returned function returns three values if it is called: the key, the value, a number that tells the current index and another number that tells how many indeces are left to be be iterated. The comperator should take care about both values it gets - these could either be numbers, functions, strings, tables, etc.

  #### Example:

       for key,value in UtilFunctions.pairsByKeys({cde=1, abc=2})
       	do print(key,value) end

  #### Output:

       abc  2
       cde  3

picktest (dspace space,[x=mousex],[y=mousey],[maxlength=1000000],[l3dcamera camera = l3dcamera.default])
  returns: ([geom,{x,y,z},{nx,ny,nz}])

  This function will test the given space with a ray and returns, if a hit was generated, the geom, the coordinate of the nearest hit and the hitnormal. The ray is in line with the x,y pair (or the mouse coordinates if not given) on the camera projection plane and through the last known camera worldposition (this worldposition can be one frame behind, so you might have to call camera:forceupdate() to update to the currently set position if this is important, which is not in most cases). The maxlength can be optionally set and is per default set to 1000000. If no camera is specified, the default camera is used.

  This function handles also orthogonal camera fovs, which requires a different raysetting code.

  ## Example:

       UtilFunctions.simplerenderqueue() input.showmouse(true) -- so we can see the mouse
       space = dspacehash.new() -- our space with our objects
       box = actornode.new("box")  -- our box location
       box.geom = dgeombox.new(1,1,1,space) -- the geom, placed in 0,0,0
       box.geom.l3d = l3dprimitive.newbox("box",1,1,1) -- the l3d for our box
       box.geom.l3d:linkinterface(box) -- link it
       cam = actornode.new("cam",5,4,3) -- our cameranode so we can view
       l3dcamera.default():linkinterface(cam) -- link it with defaultcamera
       cam:lookat(0,0,0,0,0,1) -- and look at 0,0,0 (the box location) highlight = actornode.new("highlight") -- a simple highlighter
       highlight.l3d = l3dprimitive.newsphere("hightlight",0.05)
       highlight.l3d:color(1,0,0,1) -- make sphere red
       highlight.l3d:linkinterface(highlight) -- link it local function test () -- our testing function
       	 local g,pos = UtilFunctions.picktest(space)  -- test it
       	 highlight.l3d:rfNodraw(not pos) -- don't highlight if no hit 	 if pos then  -- if we have a hit
           highlight:pos(pos[1],pos[2],pos[3]) -- move the highlighter
           g.l3d:color(1,math.sin(os.clock()*5)/2+.5,1,1)
           	-- ^^ make the hit object do something
       	 end
       end
       Timer.set("picker", test,20) -- run the test every 20ms

printf (string format, ...)
  returns: ()

  prints out a formated string as the rules of string.format describe. This function is also stored in the global variable named printf

removeWindowResizeListener (function)
  returns: ()
  removes the given function from being called on window resize events
serialize (table input)
  returns: (string serialized)

  Serializes a given table into a string that allows the reconstruction of the given table. It returns a string that describes the table's content with lua code. To deserialize the string, it must only be executed:

       mytable = {1,2,3}
       serial = UtilFunctions.serialize(mytable)

       mytable = nil
       reconstructed = loadstring(serial)()

       for i,v in ipairs(reconstructed) do print(v) end
        -- prints out 1,2,3 - converted first to string and then
        -- to a table again successfully

  The table may contain self cycles:

       mytable = {1,2,3}
       mytable.self = mytable
       mytable[mytable] = "self index"
       serial = UtilFunctions.serialize(mytable)

       mytable = nil
       reconstructed = loadstring(serial)()

       print(reconstructed[reconstructed])
       for i,v in ipairs(reconstructed.self) do print(v) end
         -- prints out "self index" \n 1,2,3

  If the table contains function, the serilizing function will try to compile the function in its binary representation using string.dump - which may fail if the function is using local values from outside.

  If the table has a metatable function entry named __serialize, this function is being called and the return value is further serialized if it is a table value. However, if the function returns a string, the string is directly written in the place where the serialisation takes place! You can inject lua code this way:

       mytable = {}
       setmetatable(mytable, {__serialize =
         function (self, idx)
           return "function () return true end"
         end
       end
       })

       print (UtilFunctions.serialize({ mytable }))

  Output result:

       local refs = {}
       local fns = {}
       for i=1,1 do refs[i] = {} end

       refs[1][1] = function () return true end

       return refs[1]

  Important: don't serialize tables with __serialize metatables directly! Include them in a table instead, like in the example above.

  The serialisation function receives two arguments: the own table as argument 1 and an index value as argument 2. The indexvalue represents the id where the table data is stored (the refs table includes all required values and other values must reference them as well, building the cyclic tables and so on). The serialize function can return a second value which tells the serializer how many reference table you require - i.e. if you return 1 as second argument, an additional table is stored in refs.

  You could also return a table, which is then serialized too, or a string of a serialisation included in a function that is executed:

       (function () UtilFunctions.serialize({1,2,3}) end)()
        -- creates a table {1,2,3}

  Since you can modify the output result, you can write inject any code you want to save, meaning loops, functions and so on.

  The way the serialisation is stored is given in the output result above: A list of tables stored in refs is used to fill the data of the tables one after another without breaking the consistence due to cyclic references. The fns table contains functions that are created with the string.dump functions. The loop creates all required tables so we can easily use them later. After this initialisation, the tables in refs are filled with all values. At last, the first table value (which was passed to the serialize function) is returned. You can either write this string in a file or make a lua function of it by prepending "function serializedstuff () " and adding "end" to the string returned by the serializing function.

setTableValue (table,value,[newvalue])
  returns: ([index,oldvalue])

  searches a val in the given table. The first hit is replaced by newvalue, which removes the tableentry if it is nil. You can use it therefore to remove a value from a table. The index of the removed element and the value is then returned.

  If no match was found, nothing is returned.

simplerenderqueue ([l3dview],[boolean noempty],[tab ignorelayers])
  returns: (l3dview)

  sets up a standard renderqueue for the view (which is also returned). The l3dview has equivalent rcmds in its table. The order is: rClear,rDepth,rDrawbg,rLayers[1..16]. Each rLayer contains: stencil,drawlayer,drawprt for the equivalent l3dlayerids-1. Sorting is enabled and material-based.
  ignorelayers should contain 'true' at layer+1 field. Ie {true,true} will disable layer 0 & 1.

smallLogoPos (int n)
  returns: ()

  Sets the position of the small Luxinia Logo at one of the four corners (whatever you like more). Topright = 1, rightbottom = 2, bottomleft = 3, topleft = 4.

tabletotalcount (table)
  returns: (n)

  returns the number of elements in that table and all of its childs it also traverses into the metatables, but ignores tables that are weak typed. It also counts metatables as element.

  This function should help to find memory leaks, which can occure if table references are not removed.