CELX in Celestia

(Document version 1.2d) - This summary describes the support for Lua/CELX-scripting in Celestia and consists mostly of the CELX API.
This documents as well as the CELX-support in Celestia probably contain a number of errors or bugs. Please report any problems you find.
  1. Introduction
    1. General
    2. Syntax
  2. Objects and Methods (The CELX API)
  3. Operators
  4. Callbacks
  5. Notes
    1. Typical Problems
If you have any comments, corrections or questions, write me a mail: Harald Schmidt.

Features specific to a version of celestia are marked by these colors:

1.3.1 Celestia 1.3.1

1.3.2 Celestia 1.3.2

1.4.0 Celestia 1.4.0

1. Introduction

1.1. About this document

It was started to document the available functionality during development celestia v1.3.1pre11, and was then extended as I contributed new functionality.
CELX uses the Lua Programming Language, so you are writing real programs. This is completely different than older CEL Celestia scripts, which are just sequences of fixed commands. So you probably should have a little experience in programming, otherwise this document won't help you much. And it's a good idea to read at least the first sections of the Lua-Documentation, available here: http://www.lua.org/manual/5.0/.

1.2. How CELX works in Celestia

Celestia works roughly(!) by repeating this:

If a CELX-script has been started, it is executed just before rendering begins. Then Celestia gives control to the Lua-interpreter, which continues to execute the script where he stopped the last time. When you call a CELX-method in a script, e.g. celestia:print(), the Lua-interpreter calls in fact a little C++ function which converts the arguments from Lua-types to C++-types, calls the right Celestia-methods to perform the action, and if necessary converts the C++ return value back to a Lua-value. Note that the Lua-interpreter called this C++ function, so when it returns the script continues, there is never a chance to return control back to the Celestia loop. To do this, the script has to call the "wait()" command, which makes the Lua-interpreter return control.

Forgetting to call wait() in Celestia 1.3.1 meant that Celestia never gained control again, and thus couldn't even handle the command to stop the script, or quit - it was completely blocked. 1.3.2 Celestia v1.3.2 periodically checks if the scripts has exceeded the maximum allowed time to execute (5s), and if it has it terminates the script.

It should have become obvious that most actions don't really change anything immediately, instead they change a setting which is used later on during rendering, which from the point of view of the script happens while calling wait(). So if you change the position of the observer ten times without calling wait() in between, this will have no effect - only the last position will actually be used in rendering.

1.3. Syntax

For a complete description of the syntax of Lua, please read http://www.lua.org/manual/5.0/

Some examples and quick notes:

You don't need anything like ";" to complete a line, simply write line after line. Blocks are enclosed by "begin ... end", short comments start with a "--", long (multiline) comments use "--[[ comment ]]".

1.3.1. Variables & Types

Lua-variables don't have to be declared, and don't have a type. But the content has a type, so you can do:
a = 1
a = a / 2 -- a is now 0.5
a = "Hello World"
a = a / 2 -- This is an error!
a = true
a = not a -- a is now false
Besides from numbers (which are doubles), booleans and strings there are tables, which can be used as arrays or hashes. A table is used like this:
t = {}
t["key1"] = "value1" -- long form
t.key2 = "value2" -- short form
u = { key1="value1", key2="value2" } -- u is now the same as t
v = { 1,2,3,4,5 } -- v[1] is now 1, v[2] is 2, ...
Then there is one special type called userdata, this is what the objects to control celestia are. To operate on this data you can call methods for these objects. To use Lua for celestia, you mostly need to know only about the available objects, the methods defined on them and how to call them - everybody who already knows Object-Oriented-Programming should feel right at home.
At the beginning of your script, the global variable celestia is defined, holding a reference to the core-functionality of celestia. To call methods on it, use this syntax:
obs = celestia:getobserver() -- get the current observer, store it in "obs"
earth = celestia:find("Earth") -- find the object representing Earth, store it in a variable "earth"
mars = earth -- do something to confuse the reader
These objects are mostly wrappers around objects which are really used in Celestia.
You then could use obs and earth like this:
obs:goto(earth)
This will start the goto-command: it moves the observer to earth, just as if you had pressed "g" in celestia after selecting earth.

1.3.2. Function definition and call:

function add_one(i)
  -- use 'local' to declare variables local to function:
  local j = i + 1
  return j
end
function divide(i, j)
  return i / j
end
-- and now call them:
a = add_one(1)
b = divide(a, 2)
Note: Lua can return multiple values at once, see the Lua-documentation for details.
The function "wait(number:n)" is predefined in celestia waits n seconds. It is special because it returns control to celestia, which you have to do to avoid blocking celestia. Many more functions are defined in Lua (see Lua-docs), such as mathematical functions or string operations. Note that not all Lua-libraries are loaded, you don't have access to io and debug-functions (which greatly reduces the danger of security-problems by "evil" scripts). But see the methode celestia:requestsystemaccess() for more information.

1.3.3. Control Structures

Lua has the typical control-structures, like while, if, for. They are used like this:
for i = 1, 10 do
  ...
end

i = 1
while i <= 11 do
  ...
i = i + 1
end

if i > j then
  ...
elsif i < j then
  ...
else
  ...
end
To loop over the contents of a table "tbl", you can use this:
for key, value in pairs(tbl) do
  -- tbl[key] == value
end

-- Use this for tabels used as arrays, i.e. indexed by numbers 1..n:
for i, value in ipairs(tbl) do
  -- tbl[i] == value
end

2. Objects and Methods (The CELX API)

This sections documents the classes (types of objects) available in Lua-scripting. You can't create an object (i.e. an userdata) yourself, you must call some method to create one. As you only have the celestia-object (ignoring methods which are not Celestia related) available when the script is starting, you must use it to create other objects. For example, to call the method getposition() of observer, you have to get an observer-instance from celestia first and then call getposition on it:
o = celestia:getobserver()
pos = o:getposition()
Note that while I am using names for the various classes in this documentation, these names have no real meaning in a script. Even "celestia" is just a variable holding an object of type celestia and not really special.
Each method is listed with it's signature:
return_value object:methodname(parameter, parameter[, optional parameter])
This is followed by a short description of what the method does, then a list of the parameters and what they are for, and possibly some notes about how to use this method, what it does exactly etc.

Object and method index:

celestia
observer
object
position
vector
rotation
frame
celscript

2.1. celestia

(back to index)
This object is predefined and gives access to all the celestia-related functionality available for Lua-scripts, either directly by methods of celestia, or indirectly by creating other objects which offer more functionality.
2.1.1.  celestia:print(string:text [, number:duration, number:horig, number:vorig, number:hoffset, number:voffset])
Print text on screen
text: A string containing the message to be printed. The string can contain newlines "\n" to break lines, or many special characters encoded in UTF-8.
duration [optional]: Number of seconds the text is shown. Default is 5.
horig [optional]: Horizontal origin of text, -1 is left, 0 center, 1 right
vorig [optional]: Vertical origin of text, -1 is bottom, 0 center, 1 top
hoffset [optional]: Offset relative to origin.
voffset [optional]: Offset relative to origin.
1.3.2 Celestia now supports UTF-8 strings as text.
2.1.2.  celestia:flash(string:text [, number:duration])
Print text on screen, similar to print.
text: A string containing the message to be printed. The string can contain newlines "\n" to break lines, or many special characters encoded in UTF-8.
duration [optional]: Number of seconds the text is shown. Default is 5.
1.3.2 Celestia now supports UTF-8 strings as text.
2.1.3.  celestia:show(string:renderflag)
Enable one or many rendering features.
renderflag: String describing the render-feature to be enabled. Must be one of orbits, cloudmaps, constellations, galaxies, planets, stars, nightmaps, eclipseshadows, ringshadows, comettails, boundaries, markers, automag, atmospheres, grid, smoothlines 1.3.2 , lightdelay 1.3.2 , partialtrajectories 1.3.2
Multiple features can be enabled at once by giving multiple arguments to this method.
2.1.4.  celestia:hide(string:renderflag)
Disable one or many rendering features.
renderflag: String describing the render-feature to be enabled. See celestia:show()
2.1.5. table celestia:getrenderflags() 1.3.2
Return a table with all known renderflags as keys, and a boolean as value indicating whether a specific renderflag is enabled.
2.1.6.  celestia:setrenderflags(table:renderflags) 1.3.2
Enable or disable renderflags, i.e. enable/disable rendering of specific features.
renderflags: A table which contains the renderflags (see celestia:show()) as keys, and booleans as values for each key.
You can use show() and hide() or setrenderflags(), both have equivalent functionality. The main reason for the existence of this method is as a counterpart of getrenderflags(), e.g. to reset all renderflags to values saved at the beginning of a script (for cleanup).
Example: enabling comet-tails and disabling nightmaps
t = {} -- create table
t.nightmaps = false
t.comettails = true
celestia:setrenderflags(t)
or shorter:
celestia:setrenderflags{nightmaps = false, comettails = true} -- note the curly braces
or old-style:
celestia:show("comettails")
celestia:hide("nightmaps")

2.1.7.  celestia:showlabel(string:labelflag)
Enables labeling.
labelflag: String describing the type of labels to enable, must be one of: planets, moons, spacecraft, asteroids, comets, constellations, stars, galaxies, locations1.3.2
Multiple features can be enabled at once by giving multiple arguments to this method.
2.1.8.  celestia:hidelabel(string:labelflag)
Disable labeling.
labelflag: String describing the type of labels to disable. See celestia:showlabel().
2.1.9. table celestia:getlabelflags() 1.3.2
Return a table with all known labelflags as keys, and a boolean as value indicating whether a specific labelflag is enabled. C.f. getrenderflags().
2.1.10.  celestia:setlabelflags(table:labelflags) 1.3.2
Enable or disable the rendering of labels.
labelflags: A table which contains the labelflags (see celestia:showlabels()) as keys, and booleans as values for each key.
See setrenderflags() for how to use this method.
2.1.11. table celestia:getorbitflags() 1.3.2
Return a table with all known orbitflags as keys, and a boolean as value indicating whether a specific orbit is enabled. C.f. getrenderflags().
2.1.12.  celestia:setorbitflags(table:orbitflags) 1.3.2
Enable or disable the rendering of specific orbits.
orbitflags: A table which contains the orbitflags as keys, and booleans as values for each key.
Each orbitflag must be one of: Planet, Moon, Asteroid, Comet, Spacecraft, Invisible, Unknown. See setrenderflags() for how to use this method.
2.1.13. number celestia:getambient() 1.3.2
Return the current level of ambient light.
2.1.14.  celestia:setambient(number:ambient) 1.3.2
Set the level of ambient light.
ambient: The new level of ambient light, must be between 0 and 1.
2.1.15. number celestia:getfaintestvisible() 1.3.2
Return the current faintest visible magnitude. If AutoMag has been enabled, this method returns the faintest maginute at 45° instead.
2.1.16.  celestia:setfaintestvisible(number:faintest) 1.3.2
Sets the current faintest visible magnitude. If AutoMag has been enabled, sets the faintest maginute at 45° instead.
faintest: The new faintest magnitude
2.1.17. number celestia:getminorbitsize() 1.3.2
Returns the minimum size in pixel for an orbit to be rendered.
2.1.18.  celestia:setminorbitsize(number:orbitsize) 1.3.2
Set the minimum size of an orbit to be rendered.
orbitsize: The minimum size of an orbit in pixel.
2.1.19. number celestia:getstardistancelimit() 1.3.2
Returns the maximum distance of stars which are still rendered.
2.1.20.  celestia:setstardistancelimit(number:distance) 1.3.2
Sets the maximum distance of stars to be rendered.
distance: The maximum distance.
2.1.21. number celestia:getminfeaturesize() 1.3.2
Returns the minimum size for locations.
2.1.22.  celestia:setminfeaturesize(number:size) 1.3.2
Sets the minimum size for locations.
size: The minimum feature size for location-labels.
2.1.23. string celestia:getstarstyle() 1.3.2
Returns the current rendering style for stars, one of fuzzy, point, disc.
2.1.24.  celestia:setstarstyle(string:starstyle) 1.3.2
Sets the rendering style for stars.
starstyle: The new rendering style, must be one of fuzzy, point, disc.
2.1.25. object celestia:find(string:name)
Return object by name.
name: String describing the wanted object, like "Earth" (or "Sol/Earth"), "Jupiter" etc.
2.1.26. object celestia:getselection()
Return the current selection.
2.1.27.  celestia:select(object:o)
Sets the current selection.
o: The object which will be the new selection.
2.1.28.  celestia:mark(object:o)
Marks object.
o: The object to be marked.
You may want to use object:mark() instead.
2.1.29.  celestia:unmark(object:o)
Remove marker.
o: The object whose marker should be removed.
You may want to use object:unmark() instead.
2.1.30.  celestia:unmarkall()
Remove all markers.
2.1.31. number celestia:gettime()
Get current simulation-time as julian days.
2.1.32.  celestia:settime(number:time)
Set time for this simulation in julian days.
time: Number giving the time in julian days.
See celestia:tojulianday() to convert between normal dates and julian days.
2.1.33. number celestia:gettimescale()
Get current timescale, i.e. how many seconds of simulation time equal one second of real time.
2.1.34.  celestia:settimescale(number:timescale)
Set the timescale.
timescale: The new timescale.
2.1.35. number celestia:getscripttime()
Returns the real number of seconds (with fractions) since the script has been started, useful for timing purposes.
2.1.36. number celestia:getstarcount()
Return number of stars in the used star catalogue.
2.1.37. object celestia:getstar(number:index_number)
Return a star identified by its index number.
index_number: Number of star in star-database.
2.1.38. observer celestia:getobserver()
Return the current active observer. Note: this method returns the observer of the active view, which can be changed by the user.
2.1.39. table celestia:getobservers() 1.3.2
Return a list of all used observers, i.e. one observer for each view.
2.1.40. number celestia:tojulianday(number:year, number:month, number:day, number:hour, number:minute, number:seconds)
Convert calendar dates to the number of julian days (see settime/gettime).
year: integer values for this date
month: integer values for this date
day: integer values for this date
hour: integer values for this date
minute: integer values for this date
seconds: float value for seconds.
2.1.41. table celestia:fromjulianday(number:jd) 1.3.2
Convert julian days to calendar dates. The returned table contains the keys year, month, day, hour, minute, second and the respective values.
jd: the date as julian days
2.1.42. x, y celestia:getscreendimension() 1.3.2
Returns width and height of Celestia-window.
2.1.43. vector celestia:newvector(number:x, number:y, number:z)
Create new vector.
x: The components of the new vector. Unit is microlightyears.
y: The components of the new vector. Unit is microlightyears.
z: The components of the new vector. Unit is microlightyears.
2.1.44. position celestia:newposition(number:x, number:y, number:z) 1.3.2
Create new position object from numbers.
x: The x-component of the new vector as a number (unit is microlightyears).
y: The y-component of the new vector a number (unit is microlightyears).
z: The y-component of the new vector a number (unit is microlightyears).
2.1.45. position celestia:newposition(string:x, string:y, string:z) 1.3.2
Create new position object from URL-style Base64-encoded values.
x: The x-component of the new vector, as a string-values taken from a cel-style URL.
y: The y-component of the new vector, as a string-values taken from a cel-style URL.
z: The z-component of the new vector, as a string-values taken from a cel-style URL.
2.1.46. rotation celestia:newrotation(vector:axis, angle:w)
Create new rotation (i.e. a quaternion).
axis: Vector describing the axis of this rotation.
w: The angle of this rotation (for details check out quaternions).
2.1.47. rotation celestia:newrotation(number:w, number:x, number:y, number:z)
Create new rotation (i.e. a quaternion).
w: The values for this quaternion.
x: The values for this quaternion.
y: The values for this quaternion.
z: The values for this quaternion.
Note: passing the components of a vector as x,y,z-values is not the same as passing the vector. If you pass a vector, a quaternion will be created by the use of "setAxisAngle", which (I hope) is more useful in practice. If you want to create a rotation from the values used in a cel:-URL, use the seperate values.
Note: the (vector, w) variant of this method is deprecated to avoid this confusion. Don't use it - use rotation:setaxisangle() instead.
2.1.48. frame celestia:newframe(string:coordsysname [, object:ref, object:target])
Create new frame of reference.
coordsysname: String describing type of frame. Must be one of: universal, ecliptic, equatorial, planetographic, observer, lock, chase.
ref [optional]: The reference-object for the new frame. Not needed for type "universal".
target [optional]: The target-object for this frame. Only needed for frames of type "lock".
2.1.49.  celestia:requestkeyboard(boolean:enable) 1.3.2
Enable or disable callback for keyboard input.
enable: true if keyboard-input should be enabled, false to let celestia handle the keyboard.
If keyboard-input has been enabled, celestia will execute the function with the name "celestia_keyboard_callback" for each keypress. This function must exist when calling requestkeyboard.
The pressed key is given the function as a string-argument, containing the UTF-8 encoding of this key (which for ASCII-chars will simply be the string containing the normal char).
The callback-function can return a boolean indicating whether the keypress has been handled (true) or if the normal processing should continue (false), no return value is taken as true.
These callbacks can only happen while the script is executing wait().
2.1.50.  celestia:requestsystemaccess() 1.3.2
Request permission to access the io and os libraries of Lua, which provide file-writing and program-execution. See the Lua-docs for details.If the ScriptSystemAccessPolicy in celestia.cfg is "ask" (default), the user will be asked whether (s)he wants to allow this.
This question will appear with the next wait(), so you must call wait before the request can have an effect. If you need access to os & io, then use something like this at the beginning of your script.
celestia:requestsystemaccess()
wait(0)

If the request was successfull, the io and os libraries will simply appear and can be used.
Note: Keyboard handling is disabled after calling requestsystemaccess(), so if you need it you must reenable it via celestia:requestkeyboard(true). This behaviour may change in future versions (but reenabling it won't hurt then either).
2.1.51. string celestia:getscriptpath() 1.3.2
Returns the path to this script, possibly relative to the current working dir.
2.1.52. boolean celestia:takescreenshot(string:filetype, string:name) 1.3.2
Take (if allowed) a screenshot and save it to disk, returns true if successful.
filetype: either "png" or "jpg", default is png
name: a string which will be used in the filename for this screenshot.
The limitations which were put in place for security reasons in 1.3.2 have been somewhat lifted in 1.4.0 because CEL-scripting now offers less secure screenshot taking, so this security can be circumvented by using a CEL script anyway :-(
However screenshots still are written to the directory set by the config option "ScriptScreenshotDirectory" in celestia.cfg, defaulting to the main celestia directory (typically something like C:\Program Files\Celestia\). Depending on your system, celestia may not be allowed to write files there.
To avoid overwriting other files (i.e. non-screenshots), the filename is always something like "screenshot-000001.png" or "screenshot-name-000001.png", where the number is counting from 1 on for each time you start a script, and name can be chosen by the script - see above. The name-part is restricted to A-z, 0-9 and _ (underscore) with a maximum length of eigth chars.
Note that taking screenshots takes some time, but any flash, print, goto or center command in progress won't wait. This may change in future, but OTOH nobody has complained yet.
2.1.53. celscript celestia:createcelscript(string:CELsource) 1.3.2
Create a CEL-script object from a string. If the string doesn't contain a valid CEL-script, this method will cause an error.
CELsource: a string containing the sourcecode of a valid CEL-script
A CEL-script object can be used to execute a CEL-script embedded in a CELX-script. This is done by passing the CEL-script in a string to this method and creating a celscript-object. Then the tick() method for the celscript object is called repeatedly until it returns false, indicating that the CEL-script has terminated.
Note: Lua supports a syntax for long strings using double brackets which is useful here: [[ long string ]]. Using this you can in nearly all cases simply copy&paste complete CEL-scripts without modification into the CELX-script.

2.2. observer

(back to index)
observer-objects are used to access properties specific to a view, such as the point of view, the frame of reference, tracking, or to perform goto-commands in a view. Note: As views (and thus observers) can be created and destroyed by the user, observer-objects in Lua can become invalid.
Accessing an invalid observer-object will result in an error.
To ease handling of observer-objects, you can compare them with other observer-objects using "==", which is not reliably possible with other userdata.
2.2.1.  observer:goto(object/position:target [, number:duration, number:start_inter, number:end_inter])
Go to a position, just as if pressing "g" on the keyboard.
target: an object or a position to go to.
duration [optional]: number of seconds the goto should take. Default: 5s
start_inter [optional]: ?
end_inter [optional]: ?
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
Note: Going to the position returned by object:getposition() is not the same as going to the object, as you will go to the center of that object.
2.2.2.  observer:goto(table:gotoparams) 1.3.2
Go to a position, similar to pressing "g" on the keyboard.
gotoparams: a table containing the parameters used for the goto.
Using this method, many different types of gotos can be performed.
The parameters for the goto must be given in the table (watch for typos, unrecognized keys or values with wrong type will simply be ignored).
gotoparams.duration: duration (number)
gotoparams.from: source position
gotoparams.to: target position
gotoparams.initialOrientation: source orientation
gotoparams.finalOrientation: target orientation
gotoparams.startInterpolation: ?
gotoparams.endInterpolation: ?
gotoparams.accelTime: ?
Note: the given positions are expected to be relative to the universal frame-of-reference, while the non table-based goto uses positions relative to the current frame-of-reference. Sorry for the confusion.
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
2.2.3.  observer:gotolonglat(object:target [, number:longitude, number:latitude, number:distance, number:duration]) 1.3.2
Goto a position above longitude/latitude with given distance of object.
target: object where to go
longitude [optional]: The longitude where to go. Default: 0
latitude [optional]: The latitude where to go. Default: 0
distance [optional]: The distance from the objects center. Default: 5 times the objects radius.
duration [optional]: number of seconds the goto should take. Default: 5s
Note: longitude and latitude are in radians (0 to 2*pi), not degree (0 to 360). If necessary, use math.rad(...) to convert.
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
2.2.4.  observer:gotolocation(position:target [, number:duration])
Goto position target in duration seconds.
target: position to go to, in the observer's current frame of reference.
duration [optional]: number of seconds the goto should take. Default: 5s
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
Note: the position is relative to the current frame of reference for this observer.
Note: the name of this method is wrong (it goes to a position, not a location), and it expects the position relative to the current frame of reference while most methods use the universal frame of reference. Sorry.
2.2.5.  observer:gotodistance(object:target [, number:distance, number:duration]) 1.3.2
Goto given distance of target object in duration seconds.
target: object where to go to.
distance [optional]: the distance from target where to stop in km. Default: 20000
duration [optional]: number of seconds the goto should take. Default: 5s
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
2.2.6.  observer:gotosurface(object:target [, number:duration]) 1.3.2
Goto surface of given object.
target: object on which to land.
duration [optional]: number of seconds the goto should take. Default: 5s
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
2.2.7.  observer:center(object:target [, number:duration])
Rotate view so that target is centered, like pressing "c" on the keyboard.
target: The object to be centered.
duration [optional]: number of seconds the centering should take. Default: 5s
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
2.2.8.  observer:centerorbit(object:target [, number:duration]) 1.3.2
Orbit the object used as the reference in the current frame such that the target becomes centered. This is like pressing "C" on the keyboard.
target: The object to be centered.
duration [optional]: number of seconds the centering should take. Default: 5s
Note: This command returns immediately, so you probably want to wait duration seconds before continuing in your script.
2.2.9. boolean observer:travelling()
Return true if there is a goto or center currently in progress.
2.2.10.  observer:cancelgoto() 1.3.2
Stops any goto or center command currently in progress.
2.2.11.  observer:follow(object:target)
Activate follow-mode on object.
target: the object to be followed.
Follow is the same as setting the frame of reference to ecliptical with target as ref-object.
2.2.12.  observer:synchronous(object:target)
Activate synchronous-mode on object.
target: the object to be synchronize with.
Sync-mode is the same as setting the frame of reference to planetographic (a.k.a. geographic) with target as ref-object.
2.2.13.  observer:chase(object:target)
Activate chase-mode on object.
target: the object to chase.
Chase-mode is the same as setting the frame of reference to chase with target as ref-object.
2.2.14.  observer:lock(object:target)
Activate lock-mode on the axis from the target to the currently selected object.
target: the object to chase.
Lock-mode is the same as setting the frame of reference to lock with target as target-object and the selection as ref (or the other way round?).
2.2.15.  observer:track(object:target)
Set tracking on object, i.e. always keep object centered.
target: the object to track.
To stop tracking an object, use observer:track(nil).
2.2.16.  observer:setposition(position:pos)
Set position of observer.
pos: the new position of this observer (in universal coordinates).
2.2.17. position observer:getposition()
Return current position of this observer in universal coordinates.
2.2.18. rotation observer:getorientation()
Return the current orientation of this observer.
2.2.19.  observer:setorientation(rotation:rot)
Set orientation of observer.
rot: the new orientation of this observer (in universal coordinates).
2.2.20.  observer:rotate(rotation:rot)
Rotate observer.
rot: The rotation to be used on the current orientation.
2.2.21.  observer:lookat(position:from, position:to, vector:up)
Set orientation of observer.
from: The point from which to look to "to". If not given, the current position is used instead.
to: The point to look at from "from".
up: A vector pointing to where "up" should be in the current view. Must not be parallel to the axis from->to.
2.2.22. number observer:gettime()
Return this observers time as julian days.
This is currently the same as celestia:gettime() (?).
2.2.23. number observer:getspeed() 1.3.2
Return the current speed of this observer. Unit is microlightyears/s.
2.2.24.  observer:setspeed(number:speed) 1.3.2
Set the speed of this observer.
speed: speed of this observer in microlightyears/s
2.2.25. string observer:getsurface()
Returns string describing current surface (??) This can be "limit of knowledge" or possibly a AlternateSurface.
TODO: Check if this works as documented.
2.2.26.  observer:setsurface(string:name)
Set the currently used surface.
name: The name of the surface to be used.
See getsurface()
2.2.27. table observer:getlocationflags() 1.3.2
Return a table indicating the setting of all location-flags. C.f. celestia:setrenderflags().Possible location-flags are city, observatory, landingsite, crater, vallis, mons, planum, chasma, patera, mare, rupes, tessera, regio, chaos, terra, astrum, corona, dorsum, fossa, catena, mensa, rima, undae, reticulum, planitia, linea, fluctus, farrum, other.
Not all of these values are currently used.
2.2.28.  observer:setlocationflags(table:locationflags) 1.3.2
Set the currently used locationflags. C.f. celestia:setrenderflags() and observer:getlocationflags().
locationflags: a table holding the to be changed locationflags as keys, and corresponding values indicating if to set or clear this flag.
2.2.29. number observer:getfov()
Return the current FOV for this observer in radians.
2.2.30.  observer:setfov(number:fov)
Set the FOV for this observer.
fov: the new FOV in radians (use math.rad(...) to convert from degrees).
2.2.31. frame observer:getframe()
Return frame of reference for this observer.
2.2.32.  observer:setframe(frame:f)
Set frame of reference.
f: the new frame for this observer.
2.2.33.  observer:splitview(string:splitdirection [, number:splitpos]) 1.3.2
Split the view for this observer.
splitdirection: "h" for a horizontal split, "v" for a vertical split
splitpos [optional]: where to split this view, default is 0.5 (in the middle).
2.2.34.  observer:deleteview() 1.3.2
Delete the view of this observer (if there is at least one view left).Note: you must no use this observer-object after this command.
2.2.35.  observer:singleview() 1.3.2
Make the view of this observer the only view.
2.2.36. boolean observer:isvalid() 1.3.2
Returns true if this observer is still valid.
Note: this can change only if you are calling deleteView/singleView, or during wait() by user-interaction.

2.3. object

(back to index)
Confusingly, object is not a general object (like Object in Java), but a celestial object like a planet or a star.
2.3.1. number object:radius()
Return radius of object in kilometers.
2.3.2. string object:type()
Return type of object as string, where string is one of:planet, moon, asteroid, comet, spacecraft, star, invisible, unknown, deepsky, location, null
2.3.3. string object:spectraltype()
If object is a star, return string containing the spectral type. Otherwise return nil.
2.3.4. number object:absmag()
If object is a star, return the absolute magnitude. Otherwise return nil.
2.3.5. string object:name()
Return name of object.
2.3.6. table object:getinfo() 1.3.2
Returns a table with the available information on this object. The exact contents of the table depend on the type of object.The information returned includes the informaton available via other methods of objectNote: some keys may not be available because they don't apply to the body in question (e.g. it doesn't have an atmosphere etc.), or contain no useful data.
For a star the table may include these keys:
- type
- catalogNumber
- stellarClass
- absoluteMagnitude
- luminosity
- radius
- temperature
- rotationPeriod
- bolometricMagnitude
For a body (e.g. a planet) the table may include these keys
- type
- name
- mass
- oblateness
- albedo
- infoURL
- radius
- lifespanStart
- lifespanEnd
- parent (may be a body or a star)
- hasRings
- rotationPeriod
- rotationOffset
- rotationEpoch
- rotationObliquity
- rotationAscendingNode
- rotationPrecessionRate
- orbitPeriod
- atmosphereHeight
- atmosphereCloudHeight
- atmosphereCloudSpeed
For a deepsky object, the table may include these keys:
- type
- name
- radius
For a location object, the table may include these keys:
- type
- name
- size
- importance
- infoURL
- featureType
- parent
2.3.7.  object:mark(string:color, string:symbolname [, number:size])
Mark this object.
color: The color to be used for the marker. Either use HTML-style "#00ff00" (green), or some predefined color-names. Default is green.
symbolname: symbol to be used as marker. Use one of: diamond, triangle, square, plus, x. Default is diamond.
size [optional]: The size of the marker. Default is 10.
2.3.8.  object:unmark()
Remove marker.
2.3.9. position object:getposition(number:time)
Return position of this object-
time: The time to be used to determine the position of this object. Defaults to current simulation time.
2.3.10. table object:getchildren()
Return a table containing all children of this object.
2.3.11.  object:preloadtexture() 1.3.2
Loads texture for object from disk. Useful to reduce delays when approaching object.

2.4. position

(back to index)
A position-object contains the exact coordinates of a point in space. Internally position-objects use 128bit per component and therefore have higher precision than available directly in Lua (which typically uses 64-bit double-precision). A position is relative to a coordinate system (i.e. a frame of reference, see frame) and may need to be converted to or from universal coordinates before further use.
2.4.1. position position:addvector(vector:v)
Add vector to the position and return the result.
v: the vector to be added.
You can use "position + vector" instead.
2.4.2. vector position:vectorto(position:target)
Return vector pointing from this position to target.
target: The position the vector should be pointing to.
Precision of vector may be insufficient to express this distance exactly.
1.3.2 Instead of "source:vectorto(target)" you can also use "target - source"
2.4.3. number position:distanceto(position:target)
Returns distance in kilometers.
target: the target to which the distance is to be measured.
2.4.4. rotation position:orientationto(position:target, vector:up) 1.3.2
Returns a rotation object which points to target.
target: the target to which the orientation should point to.
up: the up-vector for the rotation.
2.4.5. number position:getx()
Return x-coordinate of this position.Note: the precision of the returned number may be insufficient to express the exact position.
1.3.2 You can access the x-component directly by using position.x (this works for assignment too: position.x = 1)
2.4.6. number position:gety()
See getx().
2.4.7. number position:getz()
See getx().

2.5. vector

(back to index)
A vector points from one position to another one. Coordinates are 64-bit double-precision. The used unit is microlightyears (1 microly = 9466411.842 km).
2.5.1. number vector:getx()
Return x-coordinate of this vector.1.3.2 You can also access the components directly using vector.x .
2.5.2. number vector:gety()
Return y-coordinate of this vector, see getx().
2.5.3. number vector:getz()
Return z-coordinate of this vector, see getx().
2.5.4. vector vector:normalize()
Returns a vector pointing in the same direction but with length 1. Be careful not to use this on extremely short vectors or even the vector (0,0,0), because the result is undefined (a vector of NaNs).
2.5.5. number vector:length() 1.3.2
Returns the length of this vector.

2.6. rotation

(back to index)
Rotation-objects are in fact quaternions and represent a rotation or the orientation in space. They can be created via celestia:newrotation() and used to control the observer via observer:rotate() or observer:setorientation(). A quaternion consists of the four values w, x, y, z and you can access these components directly using something like "rotation.x = 1".
(Note: I would appreciate any useful description of quaternions, or comments about useful methods etc. in CELX-scripting...)
2.6.1. vector rotation:imag()
Returns the x,y,z values of a rotation as a vector.
2.6.2. number rotation:real()
Returns the w value of a rotation.
2.6.3. vector rotation:transform(vector:v) 1.3.2
Applies this rotation to a vector and returns the result.
v: vector to be transformed
2.6.4.  rotation:setaxisangle(vector:v, number:w) 1.3.2
Sets axis and angle for this rotation.
v: the rotation axis
w: the rotation angle
2.6.5. rotation rotation:slerp(rotation:rot, number:t) 1.3.2
Return an interpolation of this rotation and rot, using t to indicate how much of each rotation should be used.
rot: The other rotation object
t: A number between 0 and 1. If 0, this methods returns this rotation. If 1, returns rot.

2.7. frame

(back to index)
A frame-object represents the frame of reference of an observer. See celestia:newframe() for possible types of frame of reference.
2.7.1. position frame:to(position:pos [, number:time])
pos: The position to be transformed.
time [optional]: The time to be used for the conversion (frames are relatives to celestial bodies, which move). Default is current simulation time.
2.7.2. rotation frame:to(rotation:rot [, number:time])
Convert position or rotation from universal coordinates to this frames coordinates.
rot: The orientation to be transformed.
time [optional]: The time to be used for the conversion (frames are relatives to celestial bodies, which move). Default is current simulation time.
2.7.3. position frame:from(position:pos [, number:time])
pos: The position to be transformed.
time [optional]: The time to be used for the conversion (frames are relatives to celestial bodies, which move). Default is current simulation time.
2.7.4. rotation frame:from(rotation:rot [, number:time])
Convert position or rotation from this frames coordinates to universal coordinates.
rot: The orientation to be transformed.
time [optional]: The time to be used for the conversion (frames are relatives to celestial bodies, which move). Default is current simulation time.
2.7.5. string frame:getcoordinatesystem() 1.3.2
Return the type of this frame, i.e. the used coordinate system. See celestia:newframe() for possible return values.
2.7.6. object frame:getrefobject() 1.3.2
Return the reference-object for this frame, or nil if this frame has no reference object.
2.7.7. object frame:gettargetobject() 1.3.2
Return the reference-object for this frame, or nil if this frame has no target object.

2.8. celscript

(back to index)
1.3.2 celscript-objects are needed to execute a CEL-script within a CELX-script. To do this you have to create a celscript-object by calling celestia:createcelscript(), and then repeatedly call tick() on the obtainted celscript-object until the CEL-script has finished.
2.8.1. bool celscript:tick(number:dt) 1.3.2
Execute the CEL-script as if dt seconds had passed.
dt: The amount of time the CEL-script should advance.
Returns true if the script is still running.

3. Operators

You can manipulate vectors, positions and rotations using normal operators like "+" or "-". Following operations are defined (s is a number):

Most operations are obvious, except for maybe vector = vector ^ vector, which computes the cross-product of two vectors. This matches the internal use in C++ within celestia. I am not quite sure myself about the operations on rotations.

4. Callbacks

Right now there are two callbacks, i.e. functions which are executed as a result of external events. Callbacks are limited in what you can do: the callback must complete within 1 second, or it will be terminated, and you can't use wait() in a callback.

4.1. Keyboard

The callback for keyboard input must have the name "celestia_keyboard_callback". After a script activates the handling keyboard-input by calling celestia:requestkeyboard(true), any keypress will result in a call to a method with this name.

The method should accept one parameter, a string, which holds the char of the key which has been pressed. Accented characters like ä or é will be passed as UTF-8 sequences, i.e. as a multibyte sequence - if you only want to handle ASCII you can safely ignore this. Keys like CTRL-A are passed as strings containing a char with ASCII-codes < 32, as are Enter (13) or Backspace (8). Some special keys like cursor-keys or ESC won't activate the callback.

The callback can return either true or false, indicating that it either has handled the keypress or that celestia should continue normal processing for this key. Not returning any value is the same as returning true. If an error occurs while processing the callback, the error message will be written to the console (visible with "~") and an implicit false is returned, i.e. celestia will continue processing for this key.

4.2. Cleanup

Whenever a Lua script terminates (because it ended, the user terminated it or an error occured), Celestia will try to execute a function with the name "celestia_cleanup_callback". This function can be used to perform any cleanup actions, notably restoring settings to the values in use before the script started. Errors will only be reported in the console.

5. Notes

5.1. Typical Problems