1415 lines
45 KiB
C++
1415 lines
45 KiB
C++
// celx_object.cpp
|
|
//
|
|
// Copyright (C) 2003-2009, the Celestia Development Team
|
|
//
|
|
// Lua script extensions for Celestia: object
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
#include "celx.h"
|
|
#include "celx_internal.h"
|
|
#include "celx_object.h"
|
|
#include <celengine/body.h>
|
|
#include <celengine/timelinephase.h>
|
|
#include <celengine/axisarrow.h>
|
|
#include <celengine/visibleregion.h>
|
|
#include <celengine/planetgrid.h>
|
|
#include "celestiacore.h"
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
static MarkerRepresentation::Symbol parseMarkerSymbol(const string& name)
|
|
{
|
|
if (compareIgnoringCase(name, "diamond") == 0)
|
|
return MarkerRepresentation::Diamond;
|
|
else if (compareIgnoringCase(name, "triangle") == 0)
|
|
return MarkerRepresentation::Triangle;
|
|
else if (compareIgnoringCase(name, "square") == 0)
|
|
return MarkerRepresentation::Square;
|
|
else if (compareIgnoringCase(name, "filledsquare") == 0)
|
|
return MarkerRepresentation::FilledSquare;
|
|
else if (compareIgnoringCase(name, "plus") == 0)
|
|
return MarkerRepresentation::Plus;
|
|
else if (compareIgnoringCase(name, "x") == 0)
|
|
return MarkerRepresentation::X;
|
|
else if (compareIgnoringCase(name, "leftarrow") == 0)
|
|
return MarkerRepresentation::LeftArrow;
|
|
else if (compareIgnoringCase(name, "rightarrow") == 0)
|
|
return MarkerRepresentation::RightArrow;
|
|
else if (compareIgnoringCase(name, "uparrow") == 0)
|
|
return MarkerRepresentation::UpArrow;
|
|
else if (compareIgnoringCase(name, "downarrow") == 0)
|
|
return MarkerRepresentation::DownArrow;
|
|
else if (compareIgnoringCase(name, "circle") == 0)
|
|
return MarkerRepresentation::Circle;
|
|
else if (compareIgnoringCase(name, "disk") == 0)
|
|
return MarkerRepresentation::Disk;
|
|
else
|
|
return MarkerRepresentation::Diamond;
|
|
}
|
|
|
|
|
|
// ==================== Object ====================
|
|
// star, planet, or deep-sky object
|
|
int object_new(lua_State* l, const Selection& sel)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
Selection* ud = reinterpret_cast<Selection*>(lua_newuserdata(l, sizeof(Selection)));
|
|
*ud = sel;
|
|
|
|
celx.setClass(Celx_Object);
|
|
|
|
return 1;
|
|
}
|
|
|
|
Selection* to_object(lua_State* l, int index)
|
|
{
|
|
CelxLua celx(l);
|
|
return static_cast<Selection*>(celx.checkUserData(index, Celx_Object));
|
|
}
|
|
|
|
static Selection* this_object(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
Selection* sel = to_object(l, 1);
|
|
if (sel == NULL)
|
|
{
|
|
celx.doError("Bad position object!");
|
|
}
|
|
|
|
return sel;
|
|
}
|
|
|
|
|
|
static int object_tostring(lua_State* l)
|
|
{
|
|
lua_pushstring(l, "[Object]");
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// Return true if the object is visible, false if not.
|
|
static int object_visible(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:visible");
|
|
|
|
Selection* sel = this_object(l);
|
|
lua_pushboolean(l, sel->isVisible());
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// Set the object visibility flag.
|
|
static int object_setvisible(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(2, 2, "One argument expected to object:setvisible()");
|
|
|
|
Selection* sel = this_object(l);
|
|
bool visible = celx.safeGetBoolean(2, AllErrors, "Argument to object:setvisible() must be a boolean");
|
|
if (sel->body() != NULL)
|
|
{
|
|
sel->body()->setVisible(visible);
|
|
}
|
|
else if (sel->deepsky() != NULL)
|
|
{
|
|
sel->deepsky()->setVisible(visible);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int object_setorbitcolor(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(4, 4, "Red, green, and blue color values exepected for object:setorbitcolor()");
|
|
|
|
Selection* sel = this_object(l);
|
|
float r = (float) celx.safeGetNumber(2, WrongType, "Argument 1 to object:setorbitcolor() must be a number", 0.0);
|
|
float g = (float) celx.safeGetNumber(3, WrongType, "Argument 2 to object:setorbitcolor() must be a number", 0.0);
|
|
float b = (float) celx.safeGetNumber(4, WrongType, "Argument 3 to object:setorbitcolor() must be a number", 0.0);
|
|
Color orbitColor(r, g, b);
|
|
|
|
if (sel->body() != NULL)
|
|
{
|
|
sel->body()->setOrbitColor(orbitColor);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int object_orbitcoloroverridden(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to object:orbitcoloroverridden");
|
|
|
|
bool isOverridden = false;
|
|
Selection* sel = this_object(l);
|
|
if (sel->body() != NULL)
|
|
{
|
|
isOverridden = sel->body()->isOrbitColorOverridden();
|
|
}
|
|
|
|
lua_pushboolean(l, isOverridden);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int object_setorbitcoloroverridden(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(2, 2, "One argument expected to object:setorbitcoloroverridden");
|
|
|
|
Selection* sel = this_object(l);
|
|
bool override = celx.safeGetBoolean(2, AllErrors, "Argument to object:setorbitcoloroverridden() must be a boolean");
|
|
|
|
if (sel->body() != NULL)
|
|
{
|
|
sel->body()->setOrbitColorOverridden(override);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int object_orbitvisibility(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to object:orbitvisibility");
|
|
|
|
Body::VisibilityPolicy visibility = Body::UseClassVisibility;
|
|
|
|
Selection* sel = this_object(l);
|
|
if (sel->body() != NULL)
|
|
{
|
|
visibility = sel->body()->getOrbitVisibility();
|
|
}
|
|
|
|
const char* s = "normal";
|
|
if (visibility == Body::AlwaysVisible)
|
|
s = "always";
|
|
else if (visibility == Body::NeverVisible)
|
|
s = "never";
|
|
|
|
lua_pushstring(l, s);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int object_setorbitvisibility(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(2, 2, "One argument expected to object:setorbitcoloroverridden");
|
|
|
|
if (!lua_isstring(l, 2))
|
|
{
|
|
celx.doError("First argument to object:setorbitvisibility() must be a string");
|
|
}
|
|
|
|
Selection* sel = this_object(l);
|
|
|
|
string key;
|
|
key = lua_tostring(l, 2);
|
|
|
|
if (CelxLua::OrbitVisibilityMap.count(key) == 0)
|
|
{
|
|
cerr << "Unknown visibility policy: " << key << endl;
|
|
}
|
|
else
|
|
{
|
|
Body::VisibilityPolicy visibility = static_cast<Body::VisibilityPolicy>(CelxLua::OrbitVisibilityMap[key]);
|
|
|
|
if (sel->body() != NULL)
|
|
{
|
|
sel->body()->setOrbitVisibility(visibility);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int object_addreferencemark(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(2, 2, "Expected one table as argument to object:addreferencemark()");
|
|
|
|
if (!lua_istable(l, 2))
|
|
{
|
|
celx.doError("Argument to object:addreferencemark() must be a table");
|
|
}
|
|
|
|
Selection* sel = this_object(l);
|
|
Body* body = sel->body();
|
|
|
|
lua_pushstring(l, "type");
|
|
lua_gettable(l, 2);
|
|
const char* rmtype = celx.safeGetString(3, NoErrors, "");
|
|
lua_settop(l, 2);
|
|
|
|
lua_pushstring(l, "size");
|
|
lua_gettable(l, 2);
|
|
float rmsize = (float) celx.safeGetNumber(3, NoErrors, "", body->getRadius()) + body->getRadius();
|
|
lua_settop(l, 2);
|
|
|
|
lua_pushstring(l, "opacity");
|
|
lua_gettable(l, 2);
|
|
// -1 indicates that the opacity wasn't set and the default value
|
|
// should be used.
|
|
float rmopacity = (float) celx.safeGetNumber(3, NoErrors, "", -1.0f);
|
|
lua_settop(l, 2);
|
|
|
|
lua_pushstring(l, "color");
|
|
lua_gettable(l, 2);
|
|
const char* rmcolorstring = celx.safeGetString(3, NoErrors, "");
|
|
Color rmcolor(0.0f, 1.0f, 0.0f);
|
|
if (rmcolorstring != NULL)
|
|
Color::parse(rmcolorstring, rmcolor);
|
|
lua_settop(l, 2);
|
|
|
|
lua_pushstring(l, "tag");
|
|
lua_gettable(l, 2);
|
|
const char* rmtag = celx.safeGetString(3, NoErrors, "");
|
|
if (rmtag == NULL)
|
|
rmtag = rmtype;
|
|
lua_settop(l, 2);
|
|
|
|
lua_pushstring(l, "target");
|
|
lua_gettable(l, 2);
|
|
Selection* rmtarget = to_object(l, 3);
|
|
lua_settop(l, 2);
|
|
|
|
if (rmtype != NULL)
|
|
{
|
|
body->removeReferenceMark(rmtype);
|
|
|
|
if (compareIgnoringCase(rmtype, "body axes") == 0)
|
|
{
|
|
BodyAxisArrows* arrow = new BodyAxisArrows(*body);
|
|
arrow->setTag(rmtag);
|
|
arrow->setSize(rmsize);
|
|
if (rmopacity >= 0.0f)
|
|
arrow->setOpacity(rmopacity);
|
|
body->addReferenceMark(arrow);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "frame axes") == 0)
|
|
{
|
|
FrameAxisArrows* arrow = new FrameAxisArrows(*body);
|
|
arrow->setTag(rmtag);
|
|
arrow->setSize(rmsize);
|
|
if (rmopacity >= 0.0f)
|
|
arrow->setOpacity(rmopacity);
|
|
body->addReferenceMark(arrow);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "sun direction") == 0)
|
|
{
|
|
SunDirectionArrow* arrow = new SunDirectionArrow(*body);
|
|
arrow->setTag(rmtag);
|
|
arrow->setSize(rmsize);
|
|
if (rmcolorstring != NULL)
|
|
arrow->setColor(rmcolor);
|
|
body->addReferenceMark(arrow);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "velocity vector") == 0)
|
|
{
|
|
VelocityVectorArrow* arrow = new VelocityVectorArrow(*body);
|
|
arrow->setTag(rmtag);
|
|
arrow->setSize(rmsize);
|
|
if (rmcolorstring != NULL)
|
|
arrow->setColor(rmcolor);
|
|
body->addReferenceMark(arrow);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "spin vector") == 0)
|
|
{
|
|
SpinVectorArrow* arrow = new SpinVectorArrow(*body);
|
|
arrow->setTag(rmtag);
|
|
arrow->setSize(rmsize);
|
|
if (rmcolorstring != NULL)
|
|
arrow->setColor(rmcolor);
|
|
body->addReferenceMark(arrow);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "body to body direction") == 0 && rmtarget != NULL)
|
|
{
|
|
BodyToBodyDirectionArrow* arrow = new BodyToBodyDirectionArrow(*body, *rmtarget);
|
|
arrow->setTag(rmtag);
|
|
arrow->setSize(rmsize);
|
|
if (rmcolorstring != NULL)
|
|
arrow->setColor(rmcolor);
|
|
body->addReferenceMark(arrow);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "visible region") == 0 && rmtarget != NULL)
|
|
{
|
|
VisibleRegion* region = new VisibleRegion(*body, *rmtarget);
|
|
region->setTag(rmtag);
|
|
if (rmopacity >= 0.0f)
|
|
region->setOpacity(rmopacity);
|
|
if (rmcolorstring != NULL)
|
|
region->setColor(rmcolor);
|
|
body->addReferenceMark(region);
|
|
}
|
|
else if (compareIgnoringCase(rmtype, "planetographic grid") == 0)
|
|
{
|
|
PlanetographicGrid* grid = new PlanetographicGrid(*body);
|
|
body->addReferenceMark(grid);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int object_removereferencemark(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1000, "Invalid number of arguments in object:removereferencemark");
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
Selection* sel = this_object(l);
|
|
Body* body = sel->body();
|
|
|
|
int argc = lua_gettop(l);
|
|
for (int i = 2; i <= argc; i++)
|
|
{
|
|
string refMark = celx.safeGetString(i, AllErrors, "Arguments to object:removereferencemark() must be strings");
|
|
|
|
if (body->findReferenceMark(refMark))
|
|
appCore->toggleReferenceMark(refMark, *sel);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int object_radius(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:radius");
|
|
|
|
Selection* sel = this_object(l);
|
|
lua_pushnumber(l, sel->radius());
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_setradius(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(2, 2, "One argument expected to object:setradius()");
|
|
|
|
Selection* sel = this_object(l);
|
|
if (sel->body() != NULL)
|
|
{
|
|
Body* body = sel->body();
|
|
float iradius = body->getRadius();
|
|
double radius = celx.safeGetNumber(2, AllErrors, "Argument to object:setradius() must be a number");
|
|
if ((radius > 0))
|
|
{
|
|
body->setSemiAxes(body->getSemiAxes() * ((float) radius / iradius));
|
|
}
|
|
|
|
if (body->getRings() != NULL)
|
|
{
|
|
RingSystem rings(0.0f, 0.0f);
|
|
rings = *body->getRings();
|
|
float inner = rings.innerRadius;
|
|
float outer = rings.outerRadius;
|
|
rings.innerRadius = inner * (float) radius / iradius;
|
|
rings.outerRadius = outer * (float) radius / iradius;
|
|
body->setRings(rings);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int object_type(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:type");
|
|
|
|
Selection* sel = this_object(l);
|
|
const char* tname = "unknown";
|
|
switch (sel->getType())
|
|
{
|
|
case Selection::Type_Body:
|
|
{
|
|
int cl = sel->body()->getClassification();
|
|
switch (cl)
|
|
{
|
|
case Body::Planet : tname = "planet"; break;
|
|
case Body::DwarfPlanet : tname = "dwarfplanet"; break;
|
|
case Body::Moon : tname = "moon"; break;
|
|
case Body::MinorMoon : tname = "minormoon"; break;
|
|
case Body::Asteroid : tname = "asteroid"; break;
|
|
case Body::Comet : tname = "comet"; break;
|
|
case Body::Spacecraft : tname = "spacecraft"; break;
|
|
case Body::Invisible : tname = "invisible"; break;
|
|
case Body::SurfaceFeature : tname = "surfacefeature"; break;
|
|
case Body::Component : tname = "component"; break;
|
|
case Body::Diffuse : tname = "diffuse"; break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Selection::Type_Star:
|
|
tname = "star";
|
|
break;
|
|
|
|
case Selection::Type_DeepSky:
|
|
tname = sel->deepsky()->getObjTypeName();
|
|
break;
|
|
|
|
case Selection::Type_Location:
|
|
tname = "location";
|
|
break;
|
|
|
|
case Selection::Type_Nil:
|
|
tname = "null";
|
|
break;
|
|
}
|
|
|
|
lua_pushstring(l, tname);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_name(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:name");
|
|
|
|
Selection* sel = this_object(l);
|
|
switch (sel->getType())
|
|
{
|
|
case Selection::Type_Body:
|
|
lua_pushstring(l, sel->body()->getName().c_str());
|
|
break;
|
|
case Selection::Type_DeepSky:
|
|
lua_pushstring(l, celx.appCore(AllErrors)->getSimulation()->getUniverse()
|
|
->getDSOCatalog()->getDSOName(sel->deepsky()).c_str());
|
|
break;
|
|
case Selection::Type_Star:
|
|
lua_pushstring(l, celx.appCore(AllErrors)->getSimulation()->getUniverse()
|
|
->getStarCatalog()->getStarName(*(sel->star())).c_str());
|
|
break;
|
|
case Selection::Type_Location:
|
|
lua_pushstring(l, sel->location()->getName().c_str());
|
|
break;
|
|
default:
|
|
lua_pushstring(l, "?");
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_localname(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:localname");
|
|
|
|
Selection* sel = this_object(l);
|
|
switch (sel->getType())
|
|
{
|
|
case Selection::Type_Body:
|
|
lua_pushstring(l, sel->body()->getName(true).c_str());
|
|
break;
|
|
case Selection::Type_DeepSky:
|
|
lua_pushstring(l, celx.appCore(AllErrors)->getSimulation()->getUniverse()
|
|
->getDSOCatalog()->getDSOName(sel->deepsky(), true).c_str());
|
|
break;
|
|
case Selection::Type_Star:
|
|
lua_pushstring(l, celx.appCore(AllErrors)->getSimulation()->getUniverse()
|
|
->getStarCatalog()->getStarName(*(sel->star()), true).c_str());
|
|
break;
|
|
default:
|
|
lua_pushstring(l, "?");
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_spectraltype(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:spectraltype");
|
|
|
|
Selection* sel = this_object(l);
|
|
if (sel->star() != NULL)
|
|
{
|
|
char buf[16];
|
|
strncpy(buf, sel->star()->getSpectralType(), sizeof buf);
|
|
buf[sizeof(buf) - 1] = '\0'; // make sure it's zero terminate
|
|
lua_pushstring(l, buf);
|
|
}
|
|
else
|
|
{
|
|
lua_pushnil(l);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_getinfo(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:getinfo");
|
|
|
|
lua_newtable(l);
|
|
|
|
Selection* sel = this_object(l);
|
|
if (sel->star() != NULL)
|
|
{
|
|
Star* star = sel->star();
|
|
celx.setTable("type", "star");
|
|
celx.setTable("name", celx.appCore(AllErrors)->getSimulation()->getUniverse()
|
|
->getStarCatalog()->getStarName(*(sel->star())).c_str());
|
|
celx.setTable("catalogNumber", star->getCatalogNumber());
|
|
celx.setTable("stellarClass", star->getSpectralType());
|
|
celx.setTable("absoluteMagnitude", (lua_Number)star->getAbsoluteMagnitude());
|
|
celx.setTable("luminosity", (lua_Number)star->getLuminosity());
|
|
celx.setTable("radius", (lua_Number)star->getRadius());
|
|
celx.setTable("temperature", (lua_Number)star->getTemperature());
|
|
celx.setTable("rotationPeriod", (lua_Number)star->getRotationModel()->getPeriod());
|
|
celx.setTable("bolometricMagnitude", (lua_Number)star->getBolometricMagnitude());
|
|
|
|
const Orbit* orbit = star->getOrbit();
|
|
if (orbit != NULL)
|
|
celx.setTable("orbitPeriod", orbit->getPeriod());
|
|
|
|
if (star->getOrbitBarycenter() != NULL)
|
|
{
|
|
Selection parent((Star*)(star->getOrbitBarycenter()));
|
|
lua_pushstring(l, "parent");
|
|
object_new(l, parent);
|
|
lua_settable(l, -3);
|
|
}
|
|
}
|
|
else if (sel->body() != NULL)
|
|
{
|
|
Body* body = sel->body();
|
|
const char* tname = "unknown";
|
|
switch (body->getClassification())
|
|
{
|
|
case Body::Planet : tname = "planet"; break;
|
|
case Body::DwarfPlanet : tname = "dwarfplanet"; break;
|
|
case Body::Moon : tname = "moon"; break;
|
|
case Body::MinorMoon : tname = "minormoon"; break;
|
|
case Body::Asteroid : tname = "asteroid"; break;
|
|
case Body::Comet : tname = "comet"; break;
|
|
case Body::Spacecraft : tname = "spacecraft"; break;
|
|
case Body::Invisible : tname = "invisible"; break;
|
|
case Body::SurfaceFeature : tname = "surfacefeature"; break;
|
|
case Body::Component : tname = "component"; break;
|
|
case Body::Diffuse : tname = "diffuse"; break;
|
|
}
|
|
|
|
celx.setTable("type", tname);
|
|
celx.setTable("name", body->getName().c_str());
|
|
celx.setTable("mass", (lua_Number)body->getMass());
|
|
celx.setTable("albedo", (lua_Number)body->getAlbedo());
|
|
celx.setTable("infoURL", body->getInfoURL().c_str());
|
|
celx.setTable("radius", (lua_Number)body->getRadius());
|
|
|
|
// TODO: add method to return semiaxes
|
|
Vec3f semiAxes = body->getSemiAxes();
|
|
// Note: oblateness is an obsolete field, replaced by semiaxes;
|
|
// it's only here for backward compatibility.
|
|
float polarRadius = semiAxes.y;
|
|
float eqRadius = max(semiAxes.x, semiAxes.z);
|
|
celx.setTable("oblateness", (eqRadius - polarRadius) / eqRadius);
|
|
|
|
double lifespanStart, lifespanEnd;
|
|
body->getLifespan(lifespanStart, lifespanEnd);
|
|
celx.setTable("lifespanStart", (lua_Number)lifespanStart);
|
|
celx.setTable("lifespanEnd", (lua_Number)lifespanEnd);
|
|
// TODO: atmosphere, surfaces ?
|
|
|
|
PlanetarySystem* system = body->getSystem();
|
|
if (system->getPrimaryBody() != NULL)
|
|
{
|
|
Selection parent(system->getPrimaryBody());
|
|
lua_pushstring(l, "parent");
|
|
object_new(l, parent);
|
|
lua_settable(l, -3);
|
|
}
|
|
else
|
|
{
|
|
Selection parent(system->getStar());
|
|
lua_pushstring(l, "parent");
|
|
object_new(l, parent);
|
|
lua_settable(l, -3);
|
|
}
|
|
|
|
lua_pushstring(l, "hasRings");
|
|
lua_pushboolean(l, body->getRings() != NULL);
|
|
lua_settable(l, -3);
|
|
|
|
// TIMELINE-TODO: The code to retrieve orbital and rotation periods only works
|
|
// if the object has a single timeline phase. This should hardly ever
|
|
// be a problem, but it still may be best to set the periods to zero
|
|
// for objects with multiple phases.
|
|
const RotationModel* rm = body->getRotationModel(0.0);
|
|
celx.setTable("rotationPeriod", (double) rm->getPeriod());
|
|
|
|
const Orbit* orbit = body->getOrbit(0.0);
|
|
celx.setTable("orbitPeriod", orbit->getPeriod());
|
|
Atmosphere* atmosphere = body->getAtmosphere();
|
|
if (atmosphere != NULL)
|
|
{
|
|
celx.setTable("atmosphereHeight", (double)atmosphere->height);
|
|
celx.setTable("atmosphereCloudHeight", (double)atmosphere->cloudHeight);
|
|
celx.setTable("atmosphereCloudSpeed", (double)atmosphere->cloudSpeed);
|
|
}
|
|
}
|
|
else if (sel->deepsky() != NULL)
|
|
{
|
|
DeepSkyObject* deepsky = sel->deepsky();
|
|
const char* objTypeName = deepsky->getObjTypeName();
|
|
celx.setTable("type", objTypeName);
|
|
|
|
celx.setTable("name", celx.appCore(AllErrors)->getSimulation()->getUniverse()
|
|
->getDSOCatalog()->getDSOName(deepsky).c_str());
|
|
celx.setTable("catalogNumber", deepsky->getCatalogNumber());
|
|
|
|
if (!strcmp(objTypeName, "galaxy"))
|
|
celx.setTable("hubbleType", deepsky->getType());
|
|
|
|
celx.setTable("absoluteMagnitude", (lua_Number)deepsky->getAbsoluteMagnitude());
|
|
celx.setTable("radius", (lua_Number)deepsky->getRadius());
|
|
}
|
|
else if (sel->location() != NULL)
|
|
{
|
|
celx.setTable("type", "location");
|
|
Location* location = sel->location();
|
|
celx.setTable("name", location->getName().c_str());
|
|
celx.setTable("size", (lua_Number)location->getSize());
|
|
celx.setTable("importance", (lua_Number)location->getImportance());
|
|
celx.setTable("infoURL", location->getInfoURL().c_str());
|
|
|
|
Location::FeatureType featureType = location->getFeatureType();
|
|
string featureName("Unknown");
|
|
for (CelxLua::FlagMap64::const_iterator it = CelxLua::LocationFlagMap.begin();
|
|
it != CelxLua::LocationFlagMap.end(); it++)
|
|
{
|
|
if (it->second == featureType)
|
|
{
|
|
featureName = it->first;
|
|
break;
|
|
}
|
|
}
|
|
celx.setTable("featureType", featureName.c_str());
|
|
|
|
Body* parent = location->getParentBody();
|
|
if (parent != NULL)
|
|
{
|
|
Selection selection(parent);
|
|
lua_pushstring(l, "parent");
|
|
object_new(l, selection);
|
|
lua_settable(l, -3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
celx.setTable("type", "null");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int object_absmag(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:absmag");
|
|
|
|
Selection* sel = this_object(l);
|
|
if (sel->star() != NULL)
|
|
lua_pushnumber(l, sel->star()->getAbsoluteMagnitude());
|
|
else
|
|
lua_pushnil(l);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_mark(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 7, "Need 0 to 6 arguments for object:mark");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
Color markColor(0.0f, 1.0f, 0.0f);
|
|
const char* colorString = celx.safeGetString(2, WrongType, "First argument to object:mark must be a string");
|
|
if (colorString != NULL)
|
|
Color::parse(colorString, markColor);
|
|
|
|
MarkerRepresentation::Symbol markSymbol = MarkerRepresentation::Diamond;
|
|
const char* markerString = celx.safeGetString(3, WrongType, "Second argument to object:mark must be a string");
|
|
if (markerString != NULL)
|
|
markSymbol = parseMarkerSymbol(markerString);
|
|
|
|
float markSize = (float)celx.safeGetNumber(4, WrongType, "Third arg to object:mark must be a number", 10.0);
|
|
if (markSize < 1.0f)
|
|
markSize = 1.0f;
|
|
else if (markSize > 10000.0f)
|
|
markSize = 10000.0f;
|
|
|
|
float markAlpha = (float)celx.safeGetNumber(5, WrongType, "Fourth arg to object:mark must be a number", 0.9);
|
|
if (markAlpha < 0.0f)
|
|
markAlpha = 0.0f;
|
|
else if (markAlpha > 1.0f)
|
|
markAlpha = 1.0f;
|
|
|
|
Color markColorAlpha(0.0f, 1.0f, 0.0f, 0.9f);
|
|
markColorAlpha = Color(markColor, markAlpha);
|
|
|
|
const char* markLabel = celx.safeGetString(6, WrongType, "Fifth argument to object:mark must be a string");
|
|
if (markLabel == NULL)
|
|
markLabel = "";
|
|
|
|
bool occludable = celx.safeGetBoolean(7, WrongType, "Sixth argument to object:mark must be a boolean", true);
|
|
|
|
Simulation* sim = appCore->getSimulation();
|
|
|
|
MarkerRepresentation markerRep(markSymbol);
|
|
markerRep.setSize(markSize);
|
|
markerRep.setColor(markColorAlpha);
|
|
markerRep.setLabel(markLabel);
|
|
sim->getUniverse()->markObject(*sel, markerRep, 1, occludable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int object_unmark(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected to function object:unmark");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
Simulation* sim = appCore->getSimulation();
|
|
sim->getUniverse()->unmarkObject(*sel, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Return the object's current position. A time argument is optional;
|
|
// if not provided, the current master simulation time is used.
|
|
static int object_getposition(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 2, "Expected no or one argument to object:getposition");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
double t = celx.safeGetNumber(2, WrongType, "Time expected as argument to object:getposition",
|
|
appCore->getSimulation()->getTime());
|
|
celx.newPosition(sel->getPosition(t));
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_getchildren(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments expected for object:getchildren()");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
Simulation* sim = appCore->getSimulation();
|
|
|
|
lua_newtable(l);
|
|
if (sel->star() != NULL)
|
|
{
|
|
SolarSystemCatalog* solarSystemCatalog = sim->getUniverse()->getSolarSystemCatalog();
|
|
SolarSystemCatalog::iterator iter = solarSystemCatalog->find(sel->star()->getCatalogNumber());
|
|
if (iter != solarSystemCatalog->end())
|
|
{
|
|
SolarSystem* solarSys = iter->second;
|
|
for (int i = 0; i < solarSys->getPlanets()->getSystemSize(); i++)
|
|
{
|
|
Body* body = solarSys->getPlanets()->getBody(i);
|
|
Selection satSel(body);
|
|
object_new(l, satSel);
|
|
lua_rawseti(l, -2, i + 1);
|
|
}
|
|
}
|
|
}
|
|
else if (sel->body() != NULL)
|
|
{
|
|
const PlanetarySystem* satellites = sel->body()->getSatellites();
|
|
if (satellites != NULL && satellites->getSystemSize() != 0)
|
|
{
|
|
for (int i = 0; i < satellites->getSystemSize(); i++)
|
|
{
|
|
Body* body = satellites->getBody(i);
|
|
Selection satSel(body);
|
|
object_new(l, satSel);
|
|
lua_rawseti(l, -2, i + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int object_preloadtexture(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No argument expected to object:preloadtexture");
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
Renderer* renderer = appCore->getRenderer();
|
|
Selection* sel = this_object(l);
|
|
|
|
if (sel->body() != NULL && renderer != NULL)
|
|
{
|
|
LuaState* luastate = celx.getLuaStateObject();
|
|
// make sure we don't timeout because of texture-loading:
|
|
double timeToTimeout = luastate->timeout - luastate->getTime();
|
|
|
|
renderer->loadTextures(sel->body());
|
|
|
|
// no matter how long it really took, make it look like 0.1s:
|
|
luastate->timeout = luastate->getTime() + timeToTimeout - 0.1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*! object:catalognumber(string: catalog_prefix)
|
|
*
|
|
* Look up the catalog number for a star in one of the supported catalogs,
|
|
* currently HIPPARCOS, HD, or SAO. The single argument is a string that
|
|
* specifies the catalog number, either "HD", "SAO", or "HIP".
|
|
* If the object is a star, the catalog string is valid, and the star
|
|
* is present in the catalog, the catalog number is returned on the stack.
|
|
* Otherwise, nil is returned.
|
|
*
|
|
* \verbatim
|
|
* -- Example: Get the SAO and HD catalog numbers for Rigel
|
|
* --
|
|
* rigel = celestia:find("Rigel")
|
|
* sao = rigel:catalognumber("SAO")
|
|
* hd = rigel:catalognumber("HD")
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_catalognumber(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(2, 2, "One argument expected to object:catalognumber");
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
Selection* sel = this_object(l);
|
|
const char* catalogName = celx.safeGetString(2, WrongType, "Argument to object:catalognumber must be a string");
|
|
|
|
// The argument is a string indicating the catalog.
|
|
bool validCatalog = false;
|
|
bool useHIPPARCOS = false;
|
|
StarDatabase::Catalog catalog = StarDatabase::HenryDraper;
|
|
if (catalogName != NULL)
|
|
{
|
|
if (compareIgnoringCase(catalogName, "HD") == 0)
|
|
{
|
|
catalog = StarDatabase::HenryDraper;
|
|
validCatalog = true;
|
|
}
|
|
else if (compareIgnoringCase(catalogName, "SAO") == 0)
|
|
{
|
|
catalog = StarDatabase::SAO;
|
|
validCatalog = true;
|
|
}
|
|
else if (compareIgnoringCase(catalogName, "HIP") == 0)
|
|
{
|
|
useHIPPARCOS = true;
|
|
validCatalog = true;
|
|
}
|
|
}
|
|
|
|
uint32 catalogNumber = Star::InvalidCatalogNumber;
|
|
if (sel->star() != NULL && validCatalog)
|
|
{
|
|
uint32 internalNumber = sel->star()->getCatalogNumber();
|
|
|
|
if (useHIPPARCOS)
|
|
{
|
|
// Celestia's internal catalog numbers /are/ HIPPARCOS numbers
|
|
if (internalNumber < StarDatabase::MAX_HIPPARCOS_NUMBER)
|
|
catalogNumber = internalNumber;
|
|
}
|
|
else
|
|
{
|
|
const StarDatabase* stardb = appCore->getSimulation()->getUniverse()->getStarCatalog();
|
|
catalogNumber = stardb->crossIndex(catalog, internalNumber);
|
|
}
|
|
}
|
|
|
|
if (catalogNumber != Star::InvalidCatalogNumber)
|
|
lua_pushnumber(l, catalogNumber);
|
|
else
|
|
lua_pushnil(l);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// Locations iterator function; two upvalues expected. Used by
|
|
// object:locations method.
|
|
static int object_locations_iter(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
Selection* sel = to_object(l, lua_upvalueindex(1));
|
|
if (sel == NULL)
|
|
{
|
|
celx.doError("Bad object!");
|
|
return 0;
|
|
}
|
|
|
|
// Get the current counter value
|
|
uint32 i = (uint32) lua_tonumber(l, lua_upvalueindex(2));
|
|
|
|
vector<Location*>* locations = NULL;
|
|
if (sel->body() != NULL)
|
|
{
|
|
locations = sel->body()->getLocations();
|
|
}
|
|
|
|
if (locations != NULL && i < locations->size())
|
|
{
|
|
// Increment the counter
|
|
lua_pushnumber(l, i + 1);
|
|
lua_replace(l, lua_upvalueindex(2));
|
|
|
|
Location* loc = locations->at(i);
|
|
if (loc == NULL)
|
|
lua_pushnil(l);
|
|
else
|
|
object_new(l, Selection(loc));
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// Return nil when we've enumerated all the locations (or if
|
|
// there were no locations associated with the object.)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*! object:locations()
|
|
*
|
|
* Return an iterator over all the locations associated with an object.
|
|
* Only solar system bodies have locations; for all other object types,
|
|
* this method will return an empty iterator.
|
|
*
|
|
* \verbatim
|
|
* -- Example: print locations of current selection
|
|
* --
|
|
* for loc in celestia:getselection():locations() do
|
|
* celestia:log(loc:name())
|
|
* end
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_locations(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
// Push a closure with two upvalues: the object and a counter
|
|
lua_pushvalue(l, 1); // object
|
|
lua_pushnumber(l, 0); // counter
|
|
lua_pushcclosure(l, object_locations_iter, 2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*! object:bodyfixedframe()
|
|
*
|
|
* Return the body-fixed frame for this object.
|
|
*
|
|
* \verbatim
|
|
* -- Example: get the body-fixed frame of the Earth
|
|
* --
|
|
* earth = celestia:find("Sol/Earth")
|
|
* ebf = earth:bodyfixedframe()
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_bodyfixedframe(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments allowed for object:bodyfixedframe");
|
|
|
|
Selection* sel = this_object(l);
|
|
celx.newFrame(ObserverFrame(ObserverFrame::BodyFixed, *sel));
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*! object:equatorialframe()
|
|
*
|
|
* Return the mean equatorial frame for this object.
|
|
*
|
|
* \verbatim
|
|
* -- Example: getthe equatorial frame of the Earth
|
|
* --
|
|
* earth = celestia:find("Sol/Earth")
|
|
* eme = earth:equatorialframe()
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_equatorialframe(lua_State* l)
|
|
{
|
|
// TODO: allow one argument specifying a freeze time
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 1, "No arguments allowed for to object:equatorialframe");
|
|
|
|
Selection* sel = this_object(l);
|
|
celx.newFrame(ObserverFrame(ObserverFrame::Equatorial, *sel));
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*! object:orbitframe(time: t)
|
|
*
|
|
* Return the frame in which the orbit for an object is defined at a particular
|
|
* time. If time isn't specified, the current simulation time is assumed. The
|
|
* positions of stars and deep sky objects are always defined in the universal
|
|
* frame.
|
|
*
|
|
* \verbatim
|
|
* -- Example: get the orbital frame for the Earth at the current time.
|
|
* --
|
|
* earth = celestia:find("Sol/Earth")
|
|
* eof = earth:orbitframe()
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_orbitframe(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 2, "One or no arguments allowed for to object:orbitframe");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
double t = celx.safeGetNumber(2, WrongType, "Time expected as argument to object:orbitframe",
|
|
appCore->getSimulation()->getTime());
|
|
|
|
if (sel->body() == NULL)
|
|
{
|
|
// The default universal frame
|
|
celx.newFrame(ObserverFrame());
|
|
}
|
|
else
|
|
{
|
|
const ReferenceFrame* f = sel->body()->getOrbitFrame(t);
|
|
celx.newFrame(ObserverFrame(*f));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*! object:bodyframe(time: t)
|
|
*
|
|
* Return the frame in which the orientation for an object is defined at a
|
|
* particular time. If time isn't specified, the current simulation time is
|
|
* assumed. The positions of stars and deep sky objects are always defined
|
|
* in the universal frame.
|
|
*
|
|
* \verbatim
|
|
* -- Example: get the curren body frame for the International Space Station.
|
|
* --
|
|
* iss = celestia:find("Sol/Earth/ISS")
|
|
* f = iss:bodyframe()
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_bodyframe(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 2, "One or no arguments allowed for to object:bodyframe");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
double t = celx.safeGetNumber(2, WrongType, "Time expected as argument to object:orbitframe",
|
|
appCore->getSimulation()->getTime());
|
|
|
|
if (sel->body() == NULL)
|
|
{
|
|
// The default universal frame
|
|
celx.newFrame(ObserverFrame());
|
|
}
|
|
else
|
|
{
|
|
const ReferenceFrame* f = sel->body()->getBodyFrame(t);
|
|
celx.newFrame(ObserverFrame(*f));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*! object:getphase(time: t)
|
|
*
|
|
* Get the active timeline phase at the specified time. If no time is
|
|
* specified, the current simulation time is used. This method returns
|
|
* nil if the object is not a solar system body, or if the time lies
|
|
* outside the range covered by the timeline.
|
|
*
|
|
* \verbatim
|
|
* -- Example: get the timeline phase for Cassini at midnight January 1, 2000 UTC.
|
|
* --
|
|
* cassini = celestia:find("Sol/Cassini")
|
|
* tdb = celestia:utctotdb(2000, 1, 1)
|
|
* phase = cassini:getphase(tdb)
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_getphase(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
celx.checkArgs(1, 2, "One or no arguments allowed for to object:getphase");
|
|
|
|
Selection* sel = this_object(l);
|
|
CelestiaCore* appCore = celx.appCore(AllErrors);
|
|
|
|
double t = celx.safeGetNumber(2, WrongType, "Time expected as argument to object:getphase",
|
|
appCore->getSimulation()->getTime());
|
|
|
|
if (sel->body() == NULL)
|
|
{
|
|
lua_pushnil(l);
|
|
}
|
|
else
|
|
{
|
|
const Timeline* timeline = sel->body()->getTimeline();
|
|
if (timeline->includes(t))
|
|
{
|
|
celx.newPhase(*timeline->findPhase(t));
|
|
}
|
|
else
|
|
{
|
|
lua_pushnil(l);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// Phases iterator function; two upvalues expected. Used by
|
|
// object:phases method.
|
|
static int object_phases_iter(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
Selection* sel = to_object(l, lua_upvalueindex(1));
|
|
if (sel == NULL)
|
|
{
|
|
celx.doError("Bad object!");
|
|
return 0;
|
|
}
|
|
|
|
// Get the current counter value
|
|
uint32 i = (uint32) lua_tonumber(l, lua_upvalueindex(2));
|
|
|
|
const Timeline* timeline = NULL;
|
|
if (sel->body() != NULL)
|
|
{
|
|
timeline = sel->body()->getTimeline();
|
|
}
|
|
|
|
if (timeline != NULL && i < timeline->phaseCount())
|
|
{
|
|
// Increment the counter
|
|
lua_pushnumber(l, i + 1);
|
|
lua_replace(l, lua_upvalueindex(2));
|
|
|
|
const TimelinePhase* phase = timeline->getPhase(i);
|
|
celx.newPhase(*phase);
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// Return nil when we've enumerated all the phases (or if
|
|
// if the object wasn't a solar system body.)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*! object:phases()
|
|
*
|
|
* Return an iterator over all the phases in an object's timeline.
|
|
* Only solar system bodies have timeline; for all other object types,
|
|
* this method will return an empty iterator. The phases in a timeline
|
|
* are always sorted from earliest to latest, and always coverage a
|
|
* continuous span of time.
|
|
*
|
|
* \verbatim
|
|
* -- Example: copy all of an objects phases into the array timeline
|
|
* --
|
|
* timeline = { }
|
|
* count = 0
|
|
* for phase in celestia:getselection():phases() do
|
|
* count = count + 1
|
|
* timeline[count] = phase
|
|
* end
|
|
*
|
|
* \endverbatim
|
|
*/
|
|
static int object_phases(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
// Push a closure with two upvalues: the object and a counter
|
|
lua_pushvalue(l, 1); // object
|
|
lua_pushnumber(l, 0); // counter
|
|
lua_pushcclosure(l, object_phases_iter, 2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
void CreateObjectMetaTable(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.createClassMetatable(Celx_Object);
|
|
|
|
celx.registerMethod("__tostring", object_tostring);
|
|
celx.registerMethod("visible", object_visible);
|
|
celx.registerMethod("setvisible", object_setvisible);
|
|
celx.registerMethod("orbitcoloroverridden", object_orbitcoloroverridden);
|
|
celx.registerMethod("setorbitcoloroverridden", object_setorbitcoloroverridden);
|
|
celx.registerMethod("setorbitcolor", object_setorbitcolor);
|
|
celx.registerMethod("orbitvisibility", object_orbitvisibility);
|
|
celx.registerMethod("setorbitvisibility", object_setorbitvisibility);
|
|
celx.registerMethod("addreferencemark", object_addreferencemark);
|
|
celx.registerMethod("removereferencemark", object_removereferencemark);
|
|
celx.registerMethod("radius", object_radius);
|
|
celx.registerMethod("setradius", object_setradius);
|
|
celx.registerMethod("type", object_type);
|
|
celx.registerMethod("spectraltype", object_spectraltype);
|
|
celx.registerMethod("getinfo", object_getinfo);
|
|
celx.registerMethod("catalognumber", object_catalognumber);
|
|
celx.registerMethod("absmag", object_absmag);
|
|
celx.registerMethod("name", object_name);
|
|
celx.registerMethod("localname", object_localname);
|
|
celx.registerMethod("mark", object_mark);
|
|
celx.registerMethod("unmark", object_unmark);
|
|
celx.registerMethod("getposition", object_getposition);
|
|
celx.registerMethod("getchildren", object_getchildren);
|
|
celx.registerMethod("locations", object_locations);
|
|
celx.registerMethod("bodyfixedframe", object_bodyfixedframe);
|
|
celx.registerMethod("equatorialframe", object_equatorialframe);
|
|
celx.registerMethod("orbitframe", object_orbitframe);
|
|
celx.registerMethod("bodyframe", object_bodyframe);
|
|
celx.registerMethod("getphase", object_getphase);
|
|
celx.registerMethod("phases", object_phases);
|
|
celx.registerMethod("preloadtexture", object_preloadtexture);
|
|
|
|
lua_pop(l, 1); // pop metatable off the stack
|
|
}
|
|
|
|
|
|
// ==================== object extensions ====================
|
|
|
|
// TODO: This should be replaced by an actual Atmosphere object
|
|
static int object_setatmosphere(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.checkArgs(23, 23, "22 arguments (!) expected to function object:setatmosphere");
|
|
|
|
Selection* sel = this_object(l);
|
|
//CelestiaCore* appCore = getAppCore(l, AllErrors);
|
|
|
|
if (sel->body() != NULL)
|
|
{
|
|
Body* body = sel->body();
|
|
Atmosphere* atmosphere = body->getAtmosphere();
|
|
if (atmosphere != NULL)
|
|
{
|
|
float r = (float) celx.safeGetNumber(2, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
float g = (float) celx.safeGetNumber(3, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
float b = (float) celx.safeGetNumber(4, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
// Color testColor(0.0f, 1.0f, 0.0f);
|
|
Color testColor(r, g, b);
|
|
atmosphere->lowerColor = testColor;
|
|
r = (float) celx.safeGetNumber(5, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
g = (float) celx.safeGetNumber(6, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
b = (float) celx.safeGetNumber(7, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->upperColor = Color(r, g, b);
|
|
r = (float) celx.safeGetNumber(8, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
g = (float) celx.safeGetNumber(9, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
b = (float) celx.safeGetNumber(10, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->skyColor = Color(r, g, b);
|
|
r = (float) celx.safeGetNumber(11, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
g = (float) celx.safeGetNumber(12, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
b = (float) celx.safeGetNumber(13, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->sunsetColor = Color(r, g, b);
|
|
r = (float) celx.safeGetNumber(14, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
g = (float) celx.safeGetNumber(15, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
b = (float) celx.safeGetNumber(16, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
//HWR atmosphere->rayleighCoeff = Vector3(r, g, b);
|
|
r = (float) celx.safeGetNumber(17, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
g = (float) celx.safeGetNumber(18, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
b = (float) celx.safeGetNumber(19, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
//HWR atmosphere->absorptionCoeff = Vector3(r, g, b);
|
|
b = (float) celx.safeGetNumber(20, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->mieCoeff = b;
|
|
b = (float) celx.safeGetNumber(21, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->mieScaleHeight = b;
|
|
b = (float) celx.safeGetNumber(22, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->miePhaseAsymmetry = b;
|
|
b = (float) celx.safeGetNumber(23, AllErrors, "Arguments to observer:setatmosphere() must be numbers");
|
|
atmosphere->rayleighScaleHeight = b;
|
|
|
|
body->setAtmosphere(*atmosphere);
|
|
cout << "set atmosphere\n";
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ExtendObjectMetaTable(lua_State* l)
|
|
{
|
|
CelxLua celx(l);
|
|
|
|
celx.pushClassName(Celx_Object);
|
|
lua_rawget(l, LUA_REGISTRYINDEX);
|
|
if (lua_type(l, -1) != LUA_TTABLE)
|
|
cout << "Metatable for " << CelxLua::ClassNames[Celx_Object] << " not found!\n";
|
|
celx.registerMethod("setatmosphere", object_setatmosphere);
|
|
lua_pop(l, 1);
|
|
}
|