XLua Best Practices

This section only puts forth recommendations based on our experiences. These are not rules which are required by XLua; however, adopting these practices is recommended, even for the simplest projects. A good deal of the naming practices described below evolved from the frequent need for you to find your symbol (variables, tables and functions) names throughout your project, and using standardized protocols in your naming will give you hooks to search/find that kind of data you need to find.

Constant Names


MAX_SPEED = 100

Global Var Names


g_seconds_from_last     =   0

Local Var Names


local   l_loop_counter = 1

XP Dataref Names


xdr_sim_paused  =   find_dataref("sim/time/paused")     --  xdr = "XplaneDataRef"

if xdr_bus_volts[0] > 14.0 then....                     --  XPlane's bus volt value

XP Command Names


--PREFIX/SUFFIX when AUGMENTING XP COMMAND-----------------
function    xccb_flaps_up_bhandler(phase, duration) --  use _bhandler suffix to mean "before xplane handler"
function    xccb_flaps_up_ahandler(phase, duration) --  use _ahandler suffix to mean "after xplane handler"
function    xccb_flaps_dn_fhandler()                --  use _fhandler suffix to mean "a filter handler"

xcmd_flaps_up   =   wrap_command("sim/flight_controls/flaps_up",   xccb_flaps_up_bhandler,  xccb_flaps_up_ahandler)

--PREFIX/SUFFIX when REPLACING XP COMMAND-----------------
function    xccb_flaps_dn_handler()     --  use _handler suffix, since only one callback handler is used with "replace_command"

xcmd_flaps_dn   =   replace_command("sim/flight_controls/flaps_down",   xccb_flaps_dn_handler)

Custom Dataref Names


cdr_window_animation_ratio  =   create_dataref("mycustom/window/animation_ratio",  "number")    --create custom dataref

--  The below var names illustrates how using 'cdr_' and 'xdr_' prefixes help you distinguish data sources from one 
--  another.  The more you customize, the higher likelihood you may override X-Plane's data and ***mimicking*** x-plane 
--  dataref names is quite common.  

cdr_bus_volts
xdr_bus_volts   

--  BELOW: custom DR write handler showing prefix/suffix use.  
--  The name of the function alone tells you this is a 
--  write callback handler for the "door_handle_ratio" custom dataref.

cdr_door_handle_ratio_handler   =   function()          

Custom Command Names


--  Custom Command Handler Function
ccb_toggle_avitab_position_handler      =   function()

--  Custom Command Declaration
ccmd_toggle_avitab_position =   create_command("laminar/misc/toggle_avitab_position",   ccb_toggle_avitab_position_handler)

Flight Loop Functions

For longer code blocks that need to run every flight loop, wrap that code into your own custom functions and add the suffix, "_FLCB" to the function name to remind you these are running every flight loop. THEN call these functions from one of XLua's physics callbacks, which of course runs every flight loop. This keeps the physics functions from becoming polluted with long blocks of code that can be difficult to interpret the longer it gets.


function    hydraulics_FLCB()
    --  do hydraulics stuff
end

function    electrical_FLCB()
    --  do electrical stuff
end

after_physics()
    hydraulics_FLCB()
    electrical_FLCB()
end 

Comments


g_some_table = {0, 1, 5.4, 12, 23.3}

--A divider comment line -------------------------------------

function    does_alot_of_stuff()
    for i, v in ipairs(g_some_table) do
        if      v == 0  then
            print("next number in line is 1")
        elseif  v == 1  then
            print("next number in line is 5.4")     
        else            
            for j = 1, 15, 1 do
                if j == v then
                    print("we matched the whole number " .. v)
                end
            end -- of iterator j=1, 15
        end --  of enumeration switch
    end  -- of g_some_table iterator
end -- of function 'does_alot_of_stuff'

Code Alignment

Code Alignment is a personal preference. Code that does similar things is easier to read when aligned in columns and grouped together. See XLua Example Template


--HARD TO READ (but works fine)--

g_myvar1=0
local l_myvariabl2="N234MA"
g_bobsvar3=3.23343
tomsfunction=function() end
local l_bus_state = false
xdr_running_time=find_dataref("sim/time/running_time")

--EASIER TO READ, and still works fine--

local   l_bus_state     =   false
local   l_myvariabl2    =   "N234MA"

g_myvar1                =   0
g_bobsvar3              =   3.23343

tomsfunction            =   function() end

xdr_running_time        =   find_dataref("sim/time/running_time")

Variable Names

Be VERY descriptive when naming your variables and name them according to what they actually do. Long names don't hurt, so don't get lazy! Prefixes and suffixes can go a long way to clarifying the symbols use.


cdr_large_knob_manip                        --  A custom dataref that is driven (written to) by a manipulator
cdr_large_knob_anim                         --  A custom dataref that drives an OBJ animation
cdr_pilot_alt_tens_digit_wheel_ratio_anim   --  A custom dataref that drives an animated altimeter scrollwheel  
ccb_avitab_stow_handler                     --  A Custom command CallBack that manages(handles) a tablet animation
ccmd_toggle_sunvisor_position               --  A Custom command handle to toggle a sunvisor position animation

Do Nothing Write Callbacks

Many required callbacks, for both commands and datarefs have no need to do anything. When this is the case, then use one single callback named "do_nothing_CB" and pass this callback name as a parameter whenever your callbacks do not need to do anything. This will save you the time of writing multiple callbacks for other commands and datarefs that all do nothing, as well as let you know in the declaration statement itself that the command/write dataref callbacks do nothing. =

Button Presses

Whenever you need to process a simple click in 3D, i.e. "push/press" a button or click on a handle, then prefer to use a COMMAND type manipulator and the XLua command callbacks, rather than the older button type manipulator, which uses a Dataref write Callback. You can animate such buttons by assigning them the "virtual dataref": CMND=your/command/string/name in Blender, or alternatively, you can create a dedicated animation dataref if you so desire.