跳转到内容

Celestia/Celx 脚本/CELX Lua 方法

来自维基教科书,开放世界中的开放书籍

此摘要描述了对 Celestia 中 Lua/CELX 脚本的支持,主要包括 CELX API。本文档以及 Celestia 中的 CELX 支持可能包含一些错误或漏洞。请报告您发现的任何问题。

关于本文档

[编辑 | 编辑源代码]

它最初是为了记录 Celestia v1.3.1pre11 开发期间可用的功能,然后随着新功能的贡献而扩展。

CELX 使用 Lua 编程语言,所以您实际上是在编写程序。这与旧的 CEL Celestia 脚本完全不同,旧的 CEL Celestia 脚本只是一系列固定命令。因此,您可能需要具备一些编程经验,否则本文档对您帮助不大。

阅读 Lua 文档的前几节也是一个好主意,可以在以下位置找到:

CELX 在 Celestia 中的工作原理

[编辑 | 编辑源代码]

Celestia 大致(!) 通过重复以下步骤来工作:

  • 检查用户输入,相应地更改渲染设置(例如,启用轨道的渲染,更改观察者位置/方向)
  • 更新模拟时间
  • 如果启用了跳转,更新观察者的位置
  • 使用当前设置(渲染标志,时间,位置)渲染所有对象

如果 CELX 脚本已启动,它将在渲染开始前执行。然后 Celestia 将控制权交给 Lua 解释器,它将继续从上次停止的地方执行脚本。当 CELX 方法在脚本中被调用时,例如 celestia:print(),Lua 解释器会调用一个小的 C++ 函数,该函数会将参数从 Lua 类型转换为 C++ 类型,调用正确的 Celestia 方法来执行操作,并在必要时将 C++ 返回值转换回 Lua 值。请注意,Lua 解释器调用了此 C++ 函数,因此当该函数返回时,脚本将继续执行:永远不会有机会将控制权交回 Celestia 循环。为此,脚本必须调用 wait() 函数,该函数使 Lua 解释器返回控制权。

在 Celestia 1.3.1 中忘记调用 wait() 意味着 Celestia 永远不会再次获得控制权,因此无法处理停止或退出脚本的命令 - 它完全被阻塞了。从版本 1.3.2 开始,Celestia 定期检查脚本是否超过了最大允许的执行时间(5 秒),如果超过了,它将终止脚本。

应该很清楚的是,大多数操作实际上并没有立即更改任何内容。相反,脚本会更改一个设置,该设置稍后在渲染过程中使用,从脚本的角度来看,这发生在调用 wait() 的时候。因此,如果观察者的位置更改十次,而没有在中间调用 wait(),则不会有任何影响 - 只有最后一个位置才会实际用于渲染。

有关 Lua 语法的完整描述,请阅读 https://lua.ac.cn/manual/5.0/
Celestia 版本 1.5.0 使用 Lua 版本 5.1,它与早期 Celestia 版本中使用的 Lua 版本 5.0 略有不同。
Lua 5.1 手册可在 https://lua.ac.cn/manual/5.1/ 找到
有关 Lua 版本 5.0 和 5.1 之间更改的详细信息,请参见 https://lua.ac.cn/manual/5.1/manual.html#7

一些快速入门说明

  1. Lua 命令可以通过文本行终止符或分号来终止。要在文本的单行中包含多个 Lua 命令,请用分号 (;) 分隔它们,但如果行中只有一个 Lua 命令,则不需要分号。
  2. 使用诸如“记事本”、“记事本++”或“写字板”之类的行编辑器无需文本格式来编写您的 CELX 脚本;
  3. 短(单行)注释以两个连字符“--”开头;
  4. 长(多行)注释使用“--[[ comment ]]”。
  5. 当您在 CELX 脚本的第一行中使用注释“-- Title: string:text”时,string:text 标题将在 Celestia/文件/脚本下拉菜单中显示,而不是文件名。

示例

-- Title: Example script
-- This is a short comment line.
-- [[ This
      is
      a
      long
      comment
      line.]]
a = 5; b = 6 -- two Lua commands on a single line
c = 3        -- one Lua command on a line

变量和类型

[编辑 | 编辑源代码]

Lua 变量不需要声明,也没有类型,但是内容有类型。

Lua 中有八种基本类型

  1. nil
    • Nil 是值 nil 的类型,其主要属性是与任何其他值不同;它通常表示缺少有用的值。
  2. boolean
    • Boolean 是值 false 和 true 的类型。
      nil 和 false 都使条件为假;任何其他值都使它为真。
  3. number
    • Number 表示实数(双精度浮点数)。
  4. string
    • String 表示任何 8 位字符的数组。
  5. table
    • 表格可以用作数组,这些数组不仅可以用数字索引,还可以用任何值索引(除了 nil)。
      表格也可以包含所有类型的的值(除了 nil)。
  6. userdata
    • 用于控制 Celestia 的对象属于这种特殊的类型 userdata。
  7. function
    • 函数类型是一个可执行表达式,编译自 Lua 和 CELX 代码块。
  8. thread
    • 这里不作进一步解释。

示例
同一个变量“a”可以具有不同类型的內容。

a = 1                -- a is 1, an integer number
a = a / 2            -- a is now 0.5, changed into a floatingpoint number
a = "Hello World"    -- a contains a string now 
a = a / 3            -- ERROR, because a string is divided by a number! 
a = true             -- a is true, a boolean
a = not a            -- a is now false, a boolean

示例
表格可以像这样使用。

t = {}                                  -- define Table t
t["key1"] = "value1"                    -- long form to store a string
t.key2 = "value2"                       -- short form to store a string
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, etc.

要操作 userdata,您可以调用对象的方. 要将 Lua 用于 Celestia,您主要只需要了解可用的对象、定义在它们上的方法以及如何调用它们 - 任何已经了解面向对象编程的人都会感觉宾至如归。

在脚本的开头,celestia 对象会自动定义,它保存对 Celestia 的核心功能的引用!要操作此 celestia 对象,您可以调用定义在它上的方法,方法是使用“celestia:”前缀,如 celestia 方法 部分所示。

示例

-- Get observer instance of the active view and store it in "obs"
obs = celestia:getobserver()

-- Find the celestial object representing Earth and store it in "earth"
earth = celestia:find("Sol/Earth")

-- Do something to confuse the reader, but possible in CELX
-- The object with name mars is made equal to the object with name earth
mars = earth
-- You can also use obs and earth like this.
obs:goto(earth)
-- This will start the goto-command, which moves the observer to Earth,
-- just as if you had pressed the [G] key in Celestia, after selecting Earth.

函数是一个可执行表达式,编译自 Lua 和 CELX 代码块,其值具有函数类型。

函数可以有用于输入值的參數,并且函数也可以返回零个、一个或多个值(有关详细信息,请参阅 Lua 文档)。

您可以在 CELX 脚本的开头定义一个或多个函数,并且可以在 CELX 脚本的主体中调用它们一次或多次。

示例

-- Define function with name "add_one" and parameterlist "i" (a number).
function add_one(i) 
   -- use 'local' to declare variables local to function: 
   local j = i + 1 
   -- return the value of "j", a number.
   return j 
end
-- Define function with name "divide" and parameterlist "i, j" (two numbers).
function divide(i, j) 
   -- return the value of the division "i / j", a number.
   return i / j 
end
-- Start of the main body of your script
<... other script code ...>
-- and now call the functions: 
a = add_one(1) 
b = divide(a, 2)
<... other script code ...>

函数“wait(number:n)”在 Celestia 中预定义,等待 number:n 秒。它很特殊,因为它会将控制权交回 Celestia,您必须这样做以避免阻塞 Celestia。

Lua 中定义了许多其他函数(参见 Lua 文档),例如数学函数或字符串操作。

备注

  1. 并非所有 Lua 库都被加载,您无法访问 io 和调试功能(这极大地降低了来自“恶意”脚本的安全问题的风险)。有关更多信息,请参见方法 celestia:requestsystemaccess()

控制结构

[编辑 | 编辑源代码]

Lua 拥有典型的控制结构,例如 forwhilerepeatif

示例

-- Execute the block of codelines (...) 10 times after each other,
-- where "i" is incremented with 1 during each loop.
for i = 1, 10 do 
   ... 
end
-- Execute the block of codelines (...)
-- as long as "i" is smaller than or equal to 11.
i = 1 
while i <= 11 do 
   ... 
   i = i + 1 
end
-- Execute the block of codelines (...) 
-- until "i" is equal to "j".
i = 1
j = 22
repeat 
   ... 
   i = i + 1 
until i == j
-- Compare "i" and "j" with each other and execute a
-- certain block of codelines (...1, ...2 or ...3),
-- depending on the result of this comparison.
if i > j then 
   ...1
elseif i < j then 
   ...2 
else 
   ...3
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 tables used as arrays, i.e. indexed by numbers 1..n: 
for i, value in ipairs(tbl) do	
   -- tbl[i] == value
   ... 
end

对象和方法 (CELX API)

[编辑 | 编辑源代码]

本节介绍 CELX Lua 脚本中可用的 userdata 类(对象类型)。

除了预定义的 celestia 对象,还有其他与 celestia 相关的对象来控制 Celestia。您无法自己创建对象(即 userdata),必须调用某个方法来创建对象。由于脚本启动时只有 celestia 对象(忽略与 Celestia 无关的方法)可用,因此您必须使用它来创建其他对象。

以下与 celestia 相关的对象可在 CELX 脚本中使用

  1. 观察者对象:
    观察者对象用于访问特定于视图的属性,例如查看者位置、查看者方向、参考系和跟踪状态。要操作观察者对象,您可以调用在其上定义的观察者方法,如 观察者方法 一节所示。
  2. 对象对象:
    CELX 中的“对象”对象是指像行星或恒星这样的天体。要操作“对象”对象,您可以调用在其上定义的“对象”方法,如 对象方法 一节所示。
  3. 位置对象:
    位置对象包含空间中某个点的精确坐标。要操作位置对象,您可以调用在其上定义的位置方法,如 位置方法 一节所示。
  4. 向量对象:
    向量对象是几何对象,在三维坐标系中具有长度和方向 [X,Y,Z]。要操作向量对象,您可以调用在其上定义的向量方法,如 向量方法 一节所示。
  5. 旋转对象:
    旋转对象在内部是四元数,这是在数学上描述三维旋转的一种方法(即它可以转换为旋转矩阵)。旋转也可以用于描述对象或观察者的方向(即观察者所看方向和“向上”方向)。要操作旋转对象,您可以调用在其上定义的旋转方法,如 旋转方法 一节所示。
  6. 帧对象:
    帧对象描述了 celestia 坐标系,并说明了每个三维坐标系的 X、Y 和 Z 轴是如何对齐的。坐标系在 Don Goyette 编写的可用 Celestia .Cel Scripting Guide v1-0g 中的“坐标系”一章中有详细介绍。要操作帧对象,您可以调用在其上定义的帧方法,如 帧方法 一节所示。
  7. 相位对象:
    对象的时序可以细分为一个或多个相位。每个相位对象都有自己的轨迹、旋转模型、轨道系和主体系。要操作相位对象,您可以调用在其上定义的相位方法,如 相位方法 一节所示。
  8. CELscript 对象:
    CELscript 对象包含一个包含有效 CEL 脚本的字符串,该字符串可以通过使用“celestia:createcelscript()”方法嵌入 CELX 脚本。要操作 CELscript 对象,您可以调用在其上定义的 CELscript 方法,如 CELscript 方法 一节所示。

示例
要调用 observer 的方法 getposition(),您首先必须从 celestia 获取一个观察者实例,然后对其调用 getposition()。

obs = celestia:getobserver() 
pos = obs:getposition()

备注

  1. 在使用本文档中的各种类的名称时,这些名称在脚本中没有任何实际意义。即使“celestia”也只是一个变量,它保存着类型为 celestia 的对象,实际上并没有什么特殊之处。

在下一节中,将列出每个方法及其签名

return_value_type object:methodname(type:parameter, type:parameter [, type:optional parameter])

之后是

  • 简短的描述,说明方法的作用;
  • 参数/参数列表及其用途;
  • 可能还有一些关于如何使用此方法、它究竟做了什么、一些注意事项等的说明
  • 最后给出了关于使用方法的示例

对象和方法索引

[编辑 | 编辑源代码]

1.6.0 仅在 Celestia 1.6.0 及更高版本中可用

对象和方法索引 (字母顺序)

[edit | edit source]

1.6.0 仅在 Celestia 1.6.0 及更高版本中可用

Callbacks

[edit | edit source]

回调函数是在外部事件发生时执行的函数。

目前Celestia中有两种回调函数可用

注意: 回调函数的功能有限

  • 回调函数必须在1秒内完成,否则将被终止;
  • 您不能在回调函数中使用wait()函数!

CEL 到 CELX 迁移

[edit | edit source]

以下部分包含可用 CEL 命令的索引。单击特定命令,您将被引导至有关其功能以及如何将该 CEL 命令迁移到等效的 CELX 对象和方法的说明。

CEL 命令索引

[edit | edit source]

以下 CEL 命令按照 Don Goyette 在 Celestia .Cel Scripting Guide v1-0g 中对 CEL 脚本命令的顺序和解释进行组织。这些解释还包含许多 Don 的示例和语法描述,以帮助从 CEL 迁移到 CELX。

在本节中,CEL 命令和 CELX 方法的参数值以 <type> 或 <name> 的形式打印。在实际使用这些命令或方法时,需要替换这些参数值。

示例

<string>    "Sol/Earth"
<duration>  1.5
<distance>  20000

从 Celestia 1.6.0 和 1.6.1 版本开始,最初仅包含 35 个 Cel 命令的列表已扩展到 52 个 Cel 命令。新增命令用 1.6.01.6.1 表示。

  1. cancel
  2. 1.6.0 capture
  3. center
  4. changedistance
  5. chase
  6. cls
  7. 1.6.0 constellationcolor
  8. 1.6.0 constellations
  9. 1.6.0 deleteview
  10. 1.6.0 exit
  11. follow
  12. goto
  13. gotoloc
  14. gotolonglat
  15. labels
  16. lock
  17. lookback
  18. mark
  19. move
  20. orbit
  21. 1.6.0 orbitflags
  22. preloadtex
  23. print
  24. renderflags
  25. 1.6.0 renderpath
  26. rotate
  27. select
  28. set
  29. 1.6.0 setactiveview
  30. 1.6.0 setambientlight
  31. setfaintestautomag45deg
  32. setframe
  33. 1.6.0 setgalaxylightgain
  34. 1.6.0 setlabelcolor
  35. 1.6.0 setlinecolor
  36. setorientation
  37. setposition
  38. 1.6.0 setradius
  39. setsurface
  40. 1.6.1 settextcolor
  41. 1.6.0 settextureresolution
  42. seturl
  43. setvisibilitylimit
  44. 1.6.0 singleview
  45. 1.6.0 splitview
  46. synchronous
  47. time
  48. timerate
  49. track
  50. unmark
  51. unmarkall
  52. wait

备注

[edit | edit source]

常见问题

[edit | edit source]
  • Lua 脚本在 Celestia 的渲染阶段之间执行。因此,如果您进行一些冗长的计算(或无休止的循环),Celestia 将无法更新屏幕,甚至无法检查按键(即,您无法通过按下 [Esc] 键来停止脚本)。从脚本的角度来看,渲染和 UI 处理仅在调用 wait() 时发生。如果脚本超过 5 秒未将控制权返回给 Celestia,则该脚本将被终止。
  • 如果您想平滑地移动观察者,请通过设置其位置来执行此操作,然后调用 wait()。但请注意:如果在某个天体上激活了“跟踪”,这会覆盖脚本中的任何 observer:setorientation()。高时间速率会在渲染行星之前显着改变行星的位置,这会导致运动不流畅。如有必要,请在脚本中检查并重置时间和时间速率。
  • 在 Windows 上,wait() 可以非常快地返回而不会执行任何渲染,而在 Linux 上,它可靠地强制执行渲染传递。
  • 用户可以在脚本运行时更改设置,包括选定天体、位置、方向、速度、时间速率、渲染标志等。不要依赖于这些设置保持不变,如有必要,您必须不断重置它们。
  • 参考系一开始可能很难掌握。如果您尝试将观察者设置为太阳系内的某个位置,但得到的日心距离约为 206 个天文单位,那么您可能设置了错误的参考系。在 1.5.0 版本之前,206 个天文单位是宇宙坐标中原点 [0,0,0] 与太阳位置之间的距离。从 1.5.0 版本开始,Celestia 将太阳系的质心放置在 [0,0,0] 处。
  • 如果您的脚本使屏幕完全变黑或出现其他奇怪的效果,请检查是否有任何使用 observer:setorientation()observer:lookat() 的情况。您可能将方向设置为“无效”四元数(例如全为零),可能是通过使用 observer:lookat() 使向上向量平行于视点方向。如果发生这种情况,您可以通过运行一个将方向设置为合理值的脚本(或简单地重新启动 Celestia)使 Celestia 恢复可用。
华夏公益教科书