Celestia/Celx Scripting/Q&A/Assigning Custom Key Functions with CELX

With CELX it's easy to create custom key functions, and assign them to different keys on your keyboard. Here's how:

First, you create a Lua function using CELX to implement your custom function. In this example, we'll create a new key function which zooms the active view so that the currently selected object fills the view:

 zoomToFit= function()
    obs = celestia:getobserver()
    obsPos = obs:getposition()
    sel = celestia:getselection()
    if sel == nil or sel:name() == "?" then return end
    selPos = sel:getposition()
    dist = obsPos:distanceto(selPos)
    rad = sel:radius()
    appDia = 2*math.atan(rad/dist)
    obs:setfov(appDia*1.20)
    celestia:flash("Zoom to fit "..sel:name(), 2) 
   end

Next, you create a table which maps a selected key to your new function. In this example, we'll use the "z" key:

 keymap = {
    z = zoomToFit
 }

Then, you create a key handling function to call your new Lua function when the desired key is pressed, and assign it as the Celestia keyboard callback:

   celestia_keyboard_callback = function(key) 
       f = keymap[key]
       if f then 
          f() 
          return true
       end
          return false
   end

Note that when there's a custom key definition for the input key, the callback returns true to indicate to Celestia that no further processing of the key is needed. Otherwise it returns false, and Celesta will handle the key according to the built-in key function assignments.

Finally, you tell Celestia that you want the callback to be called when a key is pressed, and then you wait for input:

   celestia:requestkeyboard(true)
   repeat
       wait(10)
   until false

Note that the script has an infinite loop, so you'll need to use the escape key to terminate it.

Once you've got the basic script, you can assign other new key functions simply by defining the Lua functions to implement them, and adding them to the key map.

Give it a try!


Download the script edit

Below you can find the whole script (without comments) in a single text block. Copy everything in the grey box and paste it into a text file in your favourite text editor, and save that file in your scripts directory as zoomtofit.celx. Then open it (File/Open Script) from within Celestia to see the script in action.

-- Zoom To Fit function script
syntaxhighlight lang="text"
zoomToFit= function()
  obs = celestia:getobserver()
  obsPos = obs:getposition()
  sel = celestia:getselection()
  if sel == nil or sel:name() == "?" then return end
  selPos = sel:getposition()
  dist = obsPos:distanceto(selPos)
  rad = sel:radius()
  appDia = 2*math.atan(rad/dist)
  obs:setfov(appDia*1.20)
  celestia:flash("Zoom to fit "..sel:name(), 2) 
 end

keymap = { z = zoomToFit }

celestia_keyboard_callback = function(key) 
     f = keymap[key]
     if f then 
        f() 
        return true
     end
        return false
 end

celestia:requestkeyboard(true)
repeat
     wait(10)
until false

</syntaxhighlight>


Distinguishing upper from lower case edit

Unfortunately, the example above does not distinguish between the typing of upper case (capital) letters and lower case letters.

When Celestia calls the function celestia_keyboard_callback, the function's argument ("key" in this example) contains the letter that was typed. A simple string of IF statements can distinguish among them:

 celestia_keyboard_callback = function(key) 
      if key == "F" then 
         zoomToFit() 
         return true
      end
         return false
  end

This form of the callback calls the function zoomToFit if an upper-case F is typed, but lets Celestia handle all other letters, including lower-case f.