celx_observer.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:26k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // celx_observer.cpp
  2. //
  3. // Copyright (C) 2003-2008, the Celestia Development Team
  4. //
  5. // Lua script extensions for Celestia: observer object
  6. //
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the GNU General Public License
  9. // as published by the Free Software Foundation; either version 2
  10. // of the License, or (at your option) any later version.
  11. #include "celx.h"
  12. #include "celx_internal.h"
  13. #include "celx_observer.h"
  14. //#include <celengine/body.h>
  15. //#include <celengine/timelinephase.h>
  16. #include "celestiacore.h"
  17. // ==================== Observer ====================
  18. int observer_new(lua_State* l, Observer* o)
  19. {
  20.     CelxLua celx(l);
  21.     
  22.     Observer** ud = static_cast<Observer**>(lua_newuserdata(l, sizeof(Observer*)));
  23.     *ud = o;
  24.     
  25.     celx.setClass(Celx_Observer);
  26.     
  27.     return 1;
  28. }
  29. Observer* to_observer(lua_State* l, int index)
  30. {
  31.     CelxLua celx(l);
  32.     Observer** o = static_cast<Observer**>(lua_touserdata(l, index));
  33.     CelestiaCore* appCore = celx.appCore(AllErrors);
  34.     
  35.     // Check if pointer is still valid, i.e. is used by a view:
  36.     if (o != NULL && getViewByObserver(appCore, *o) != NULL)
  37.     {
  38.         return *o;
  39.     }
  40.     return NULL;
  41. }
  42. static Observer* this_observer(lua_State* l)
  43. {
  44.     CelxLua celx(l);
  45.     Observer* obs = to_observer(l, 1);
  46.     if (obs == NULL)
  47.     {
  48.         celx.doError("Bad observer object (maybe tried to access a deleted view?)!");
  49.     }
  50.     
  51.     return obs;
  52. }
  53. static int observer_isvalid(lua_State* l)
  54. {
  55.     CelxLua celx(l);
  56.     celx.checkArgs(1, 1, "No arguments expected for observer:isvalid()");
  57.     lua_pushboolean(l, to_observer(l, 1) != NULL);
  58.     return 1;
  59. }
  60. static int observer_tostring(lua_State* l)
  61. {
  62.     lua_pushstring(l, "[Observer]");
  63.     
  64.     return 1;
  65. }
  66. static int observer_setposition(lua_State* l)
  67. {
  68.     CelxLua celx(l);
  69.     celx.checkArgs(2, 2, "One argument required for setpos");
  70.     
  71.     Observer* o = this_observer(l);
  72.     
  73.     UniversalCoord* uc = celx.toPosition(2);
  74.     if (uc == NULL)
  75.     {
  76.         celx.doError("Argument to observer:setposition must be a position");
  77.     }
  78.     o->setPosition(*uc);
  79.     return 0;
  80. }
  81. static int observer_setorientation(lua_State* l)
  82. {
  83.     CelxLua celx(l);
  84.     celx.checkArgs(2, 2, "One argument required for setorientation");
  85.     
  86.     Observer* o = this_observer(l);
  87.     
  88.     Quatd* q = celx.toRotation(2);
  89.     if (q == NULL)
  90.     {
  91.         celx.doError("Argument to observer:setorientation must be a rotation");
  92.     }
  93.     o->setOrientation(*q);
  94.     return 0;
  95. }
  96. static int observer_getorientation(lua_State* l)
  97. {
  98.     CelxLua celx(l);
  99.     celx.checkArgs(1, 1, "No arguments expected to observer:getorientation()");
  100.     
  101.     Observer* o = this_observer(l);
  102.     celx.newRotation(o->getOrientation());
  103.     
  104.     return 1;
  105. }
  106. static int observer_rotate(lua_State* l)
  107. {
  108.     CelxLua celx(l);
  109.     celx.checkArgs(2, 2, "One argument required for rotate");
  110.     
  111.     Observer* o = this_observer(l);
  112.     
  113.     Quatd* q = celx.toRotation(2);
  114.     if (q == NULL)
  115.     {
  116.         celx.doError("Argument to observer:setpos must be a rotation");
  117.     }
  118.     Quatf qf((float) q->w, (float) q->x, (float) q->y, (float) q->z);
  119.     o->rotate(qf);
  120.     return 0;
  121. }
  122. static int observer_lookat(lua_State* l)
  123. {
  124.     CelxLua celx(l);
  125.     celx.checkArgs(3, 4, "Two or three arguments required for lookat");
  126.     int argc = lua_gettop(l);
  127.     
  128.     Observer* o = this_observer(l);
  129.     
  130.     UniversalCoord* from = NULL;
  131.     UniversalCoord* to = NULL;
  132.     Vec3d* upd = NULL;
  133.     if (argc == 3)
  134.     {
  135.         to = celx.toPosition(2);
  136.         upd = celx.toVector(3);
  137.         if (to == NULL)
  138.         {
  139.             celx.doError("Argument 1 (of 2) to observer:lookat must be of type position");
  140.         }
  141.     }
  142.     else
  143.     {
  144.         if (argc == 4)
  145.         {
  146.             from = celx.toPosition(2);
  147.             to = celx.toPosition(3);
  148.             upd = celx.toVector(4);
  149.             
  150.             if (to == NULL || from == NULL)
  151.             {
  152.                 celx.doError("Argument 1 and 2 (of 3) to observer:lookat must be of type position");
  153.             }
  154.         }
  155.     }
  156.     
  157.     if (upd == NULL)
  158.     {
  159.         celx.doError("Last argument to observer:lookat must be of type vector");
  160.     }
  161.     Vec3d nd;
  162.     if (from == NULL)
  163.     {
  164.         nd = (*to) - o->getPosition();
  165.     }
  166.     else
  167.     {
  168.         nd = (*to) - (*from);
  169.     }
  170.     // need Vec3f instead:
  171.     Vec3f up = Vec3f((float) upd->x, (float) upd->y, (float) upd->z);
  172.     Vec3f n = Vec3f((float) nd.x, (float) nd.y, (float) nd.z);
  173.     
  174.     n.normalize();
  175.     Vec3f v = n ^ up;
  176.     v.normalize();
  177.     Vec3f u = v ^ n;
  178.     Quatf qf = Quatf(Mat3f(v, u, -n));
  179.     o->setOrientation(qf);
  180.     return 0;
  181. }
  182. static int observer_gototable(lua_State* l)
  183. {
  184.     CelxLua celx(l);
  185.     celx.checkArgs(2, 2, "Expected one table as argument to goto");
  186.     
  187.     Observer* o = this_observer(l);
  188.     if (!lua_istable(l, 2))
  189.     {
  190.         lua_pushstring(l, "Argument to goto must be a table");
  191.     }
  192.     
  193.     Observer::JourneyParams jparams;
  194.     jparams.duration = 5.0;
  195.     jparams.from = o->getPosition();
  196.     jparams.to = o->getPosition();
  197.     jparams.initialOrientation = o->getOrientation();
  198.     jparams.finalOrientation = o->getOrientation();
  199.     jparams.startInterpolation = 0.25;
  200.     jparams.endInterpolation = 0.75;
  201.     jparams.accelTime = 0.5;
  202.     jparams.traj = Observer::Linear;
  203.     
  204.     lua_pushstring(l, "duration");
  205.     lua_gettable(l, 2);
  206.     jparams.duration = celx.safeGetNumber(3, NoErrors, "", 5.0);
  207.     lua_settop(l, 2);
  208.     
  209.     lua_pushstring(l, "from");
  210.     lua_gettable(l, 2);
  211.     UniversalCoord* from = celx.toPosition(3);
  212.     if (from != NULL)
  213.         jparams.from = *from;
  214.     lua_settop(l, 2);
  215.     
  216.     lua_pushstring(l, "to");
  217.     lua_gettable(l, 2);
  218.     UniversalCoord* to = celx.toPosition(3);
  219.     if (to != NULL)
  220.         jparams.to = *to;
  221.     lua_settop(l, 2);
  222.     
  223.     lua_pushstring(l, "initialOrientation");
  224.     lua_gettable(l, 2);
  225.     Quatd* rot1 = celx.toRotation(3);
  226.     if (rot1 != NULL)
  227.         jparams.initialOrientation = *rot1;
  228.     lua_settop(l, 2);
  229.     
  230.     lua_pushstring(l, "finalOrientation");
  231.     lua_gettable(l, 2);
  232.     Quatd* rot2 = celx.toRotation(3);
  233.     if (rot2 != NULL)
  234.         jparams.finalOrientation = *rot2;
  235.     lua_settop(l, 2);
  236.     
  237.     lua_pushstring(l, "startInterpolation");
  238.     lua_gettable(l, 2);
  239.     jparams.startInterpolation = celx.safeGetNumber(3, NoErrors, "", 0.25);
  240.     lua_settop(l, 2);
  241.     
  242.     lua_pushstring(l, "endInterpolation");
  243.     lua_gettable(l, 2);
  244.     jparams.endInterpolation = celx.safeGetNumber(3, NoErrors, "", 0.75);
  245.     lua_settop(l, 2);
  246.     
  247.     lua_pushstring(l, "accelTime");
  248.     lua_gettable(l, 2);
  249.     jparams.accelTime = celx.safeGetNumber(3, NoErrors, "", 0.5);
  250.     lua_settop(l, 2);
  251.     
  252.     jparams.duration = max(0.0, jparams.duration);
  253.     jparams.accelTime = min(1.0, max(0.1, jparams.accelTime));
  254.     jparams.startInterpolation = min(1.0, max(0.0, jparams.startInterpolation));
  255.     jparams.endInterpolation = min(1.0, max(0.0, jparams.endInterpolation));
  256.     
  257.     // args are in universal coords, let setFrame handle conversion:
  258.     ObserverFrame tmp = *(o->getFrame());
  259.     o->setFrame(ObserverFrame::Universal, Selection());
  260.     o->gotoJourney(jparams);
  261.     o->setFrame(tmp);
  262.     
  263.     return 0;
  264. }
  265. // First argument is the target object or position; optional second argument
  266. // is the travel time
  267. static int observer_goto(lua_State* l)
  268. {
  269.     CelxLua celx(l);
  270.     if (lua_gettop(l) == 2 && lua_istable(l, 2))
  271.     {
  272.         // handle this in own function
  273.         return observer_gototable(l);
  274.     }
  275.     celx.checkArgs(1, 5, "One to four arguments expected to observer:goto");
  276.     
  277.     Observer* o = this_observer(l);
  278.     
  279.     Selection* sel = celx.toObject(2);
  280.     UniversalCoord* uc = celx.toPosition(2);
  281.     if (sel == NULL && uc == NULL)
  282.     {
  283.         celx.doError("First arg to observer:goto must be object or position");
  284.     }
  285.     
  286.     double travelTime = celx.safeGetNumber(3, WrongType, "Second arg to observer:goto must be a number", 5.0);
  287.     double startInter = celx.safeGetNumber(4, WrongType, "Third arg to observer:goto must be a number", 0.25);
  288.     double endInter = celx.safeGetNumber(5, WrongType, "Fourth arg to observer:goto must be a number", 0.75);
  289.     if (startInter < 0 || startInter > 1) startInter = 0.25;
  290.     if (endInter < 0 || endInter > 1) startInter = 0.75;
  291.     
  292.     // The first argument may be either an object or a position
  293.     if (sel != NULL)
  294.     {
  295.         o->gotoSelection(*sel, travelTime, startInter, endInter, Vec3f(0, 1, 0), ObserverFrame::ObserverLocal);
  296.     }
  297.     else
  298.     {
  299.         o->gotoLocation(*uc, o->getOrientation(), travelTime);
  300.     }
  301.     
  302.     return 0;
  303. }
  304. static int observer_gotolonglat(lua_State* l)
  305. {
  306.     CelxLua celx(l);
  307.     celx.checkArgs(2, 7, "One to five arguments expected to observer:gotolonglat");
  308.     
  309.     Observer* o = this_observer(l);
  310.     
  311.     Selection* sel = celx.toObject(2);
  312.     if (sel == NULL)
  313.     {
  314.         celx.doError("First arg to observer:gotolonglat must be an object");
  315.     }
  316.     double defaultDistance = sel->radius() * 5.0;
  317.     
  318.     double longitude  = celx.safeGetNumber(3, WrongType, "Second arg to observer:gotolonglat must be a number", 0.0);
  319.     double latitude   = celx.safeGetNumber(4, WrongType, "Third arg to observer:gotolonglat must be a number", 0.0);
  320.     double distance   = celx.safeGetNumber(5, WrongType, "Fourth arg to observer:gotolonglat must be a number", defaultDistance);
  321.     double travelTime = celx.safeGetNumber(6, WrongType, "Fifth arg to observer:gotolonglat must be a number", 5.0);
  322.     
  323.     distance = distance / KM_PER_LY;
  324.     
  325.     Vec3f up(0.0f, 1.0f, 0.0f);
  326.     if (lua_gettop(l) >= 7)
  327.     {
  328.         Vec3d* uparg = celx.toVector(7);
  329.         if (uparg == NULL)
  330.         {
  331.             celx.doError("Sixth argument to observer:gotolonglat must be a vector");
  332.         }
  333.         up = Vec3f((float)uparg->x, (float)uparg->y, (float)uparg->z);
  334.     }
  335.     o->gotoSelectionLongLat(*sel, travelTime, distance, (float)longitude, (float)latitude, up);
  336.     
  337.     return 0;
  338. }
  339. // deprecated: wrong name, bad interface.
  340. static int observer_gotolocation(lua_State* l)
  341. {
  342.     CelxLua celx(l);
  343.     celx.checkArgs(2, 3,"Expected one or two arguments to observer:gotolocation");
  344.     
  345.     Observer* o = this_observer(l);
  346.     
  347.     double travelTime = celx.safeGetNumber(3, WrongType, "Second arg to observer:gotolocation must be a number", 5.0);
  348.     if (travelTime < 0)
  349.         travelTime = 0.0;
  350.     
  351.     UniversalCoord* uc = celx.toPosition(2);
  352.     if (uc != NULL)
  353.     {
  354.         o->gotoLocation(*uc, o->getOrientation(), travelTime);
  355.     }
  356.     else
  357.     {
  358.         celx.doError("First arg to observer:gotolocation must be a position");
  359.     }
  360.     
  361.     return 0;
  362. }
  363. static int observer_gotodistance(lua_State* l)
  364. {
  365.     CelxLua celx(l);
  366.     celx.checkArgs(2, 5, "One to four arguments expected to observer:gotodistance");
  367.     
  368.     Observer* o = this_observer(l);
  369.     Selection* sel = celx.toObject(2);
  370.     if (sel == NULL)
  371.     {
  372.         celx.doError("First arg to observer:gotodistance must be object");
  373.     }
  374.     
  375.     double distance = celx.safeGetNumber(3, WrongType, "Second arg to observer:gotodistance must be a number", 20000);
  376.     double travelTime = celx.safeGetNumber(4, WrongType, "Third arg to observer:gotodistance must be a number", 5.0);
  377.     
  378.     Vec3f up(0,1,0);
  379.     if (lua_gettop(l) > 4)
  380.     {
  381.         Vec3d* up_arg = celx.toVector(5);
  382.         if (up_arg == NULL)
  383.         {
  384.             celx.doError("Fourth arg to observer:gotodistance must be a vector");
  385.         }
  386.         up.x = (float)up_arg->x;
  387.         up.y = (float)up_arg->y;
  388.         up.z = (float)up_arg->z;
  389.     }
  390.     
  391.     o->gotoSelection(*sel, travelTime, astro::kilometersToLightYears(distance), up, ObserverFrame::Universal);
  392.     
  393.     return 0;
  394. }
  395. static int observer_gotosurface(lua_State* l)
  396. {
  397.     CelxLua celx(l);
  398.     celx.checkArgs(2, 3, "One to two arguments expected to observer:gotosurface");
  399.     
  400.     Observer* o = this_observer(l);
  401.     Selection* sel = celx.toObject(2);
  402.     if (sel == NULL)
  403.     {
  404.         celx.doError("First arg to observer:gotosurface must be object");
  405.     }
  406.     
  407.     double travelTime = celx.safeGetNumber(3, WrongType, "Second arg to observer:gotosurface must be a number", 5.0);
  408.     
  409.     // This is needed because gotoSurface expects frame to be geosync:
  410.     o->geosynchronousFollow(*sel);
  411.     o->gotoSurface(*sel, travelTime);
  412.     
  413.     return 0;
  414. }
  415. static int observer_center(lua_State* l)
  416. {
  417.     CelxLua celx(l);
  418.     celx.checkArgs(2, 3, "Expected one or two arguments for to observer:center");
  419.     
  420.     Observer* o = this_observer(l);
  421.     Selection* sel = celx.toObject(2);
  422.     if (sel == NULL)
  423.     {
  424.         celx.doError("First argument to observer:center must be an object");
  425.     }
  426.     double travelTime = celx.safeGetNumber(3, WrongType, "Second arg to observer:center must be a number", 5.0);
  427.     
  428.     o->centerSelection(*sel, travelTime);
  429.     
  430.     return 0;
  431. }
  432. static int observer_centerorbit(lua_State* l)
  433. {
  434.     CelxLua celx(l);
  435.     celx.checkArgs(2, 3, "Expected one or two arguments for to observer:center");
  436.     
  437.     Observer* o = this_observer(l);
  438.     Selection* sel = celx.toObject(2);
  439.     if (sel == NULL)
  440.     {
  441.         celx.doError("First argument to observer:centerorbit must be an object");
  442.     }
  443.     double travelTime = celx.safeGetNumber(3, WrongType, "Second arg to observer:centerorbit must be a number", 5.0);
  444.     
  445.     o->centerSelectionCO(*sel, travelTime);
  446.     
  447.     return 0;
  448. }
  449. static int observer_cancelgoto(lua_State* l)
  450. {
  451.     CelxLua celx(l);
  452.     celx.checkArgs(1, 1, "Expected no arguments to observer:cancelgoto");
  453.     
  454.     Observer* o = this_observer(l);
  455.     o->cancelMotion();
  456.     
  457.     return 0;
  458. }
  459. static int observer_follow(lua_State* l)
  460. {
  461.     CelxLua celx(l);
  462.     celx.checkArgs(2, 2, "One argument expected for observer:follow");
  463.     
  464.     Observer* o = this_observer(l);
  465.     Selection* sel = celx.toObject(2);
  466.     if (sel == NULL)
  467.     {
  468.         celx.doError("First argument to observer:follow must be an object");
  469.     }
  470.     o->follow(*sel);
  471.     
  472.     return 0;
  473. }
  474. static int observer_synchronous(lua_State* l)
  475. {
  476.     CelxLua celx(l);
  477.     celx.checkArgs(2, 2, "One argument expected for observer:synchronous");
  478.     
  479.     Observer* o = this_observer(l);
  480.     Selection* sel = celx.toObject(2);
  481.     if (sel == NULL)
  482.     {
  483.         celx.doError("First argument to observer:synchronous must be an object");
  484.     }
  485.     o->geosynchronousFollow(*sel);
  486.     
  487.     return 0;
  488. }
  489. static int observer_lock(lua_State* l)
  490. {
  491.     CelxLua celx(l);
  492.     celx.checkArgs(2, 2, "One argument expected for observer:lock");
  493.     
  494.     Observer* o = this_observer(l);
  495.     Selection* sel = celx.toObject(2);
  496.     if (sel == NULL)
  497.     {
  498.         celx.doError("First argument to observer:phaseLock must be an object");
  499.     }
  500.     o->phaseLock(*sel);
  501.     
  502.     return 0;
  503. }
  504. static int observer_chase(lua_State* l)
  505. {
  506.     CelxLua celx(l);
  507.     celx.checkArgs(2, 2, "One argument expected for observer:chase");
  508.     
  509.     Observer* o = this_observer(l);
  510.     Selection* sel = celx.toObject(2);
  511.     if (sel == NULL)
  512.     {
  513.         celx.doError("First argument to observer:chase must be an object");
  514.     }
  515.     o->chase(*sel);
  516.     
  517.     return 0;
  518. }
  519. static int observer_track(lua_State* l)
  520. {
  521.     CelxLua celx(l);
  522.     celx.checkArgs(2, 2, "One argument expected for observer:track");
  523.     
  524.     Observer* o = this_observer(l);
  525.     
  526.     // If the argument is nil, clear the tracked object
  527.     if (lua_isnil(l, 2))
  528.     {
  529.         o->setTrackedObject(Selection());
  530.     }
  531.     else
  532.     {
  533.         // Otherwise, turn on tracking and set the tracked object
  534.         Selection* sel = celx.toObject(2);
  535.         if (sel == NULL)
  536.         {
  537.             celx.doError("First argument to observer:center must be an object");
  538.         }
  539.         o->setTrackedObject(*sel);
  540.     }
  541.     
  542.     return 0;
  543. }
  544. static int observer_gettrackedobject(lua_State* l)
  545. {
  546.     CelxLua celx(l);
  547.     celx.checkArgs(1, 1, "No arguments expected to observer:gettrackedobject");
  548.     
  549.     Observer* o = this_observer(l);
  550.     celx.newObject(o->getTrackedObject());
  551.     
  552.     return 1;
  553. }
  554. // Return true if the observer is still moving as a result of a goto, center,
  555. // or similar command.
  556. static int observer_travelling(lua_State* l)
  557. {
  558.     CelxLua celx(l);
  559.     celx.checkArgs(1, 1, "No arguments expected to observer:travelling");
  560.     
  561.     Observer* o = this_observer(l);
  562.     if (o->getMode() == Observer::Travelling)
  563.         lua_pushboolean(l, 1);
  564.     else
  565.         lua_pushboolean(l, 0);
  566.     
  567.     return 1;
  568. }
  569. // Return the observer's current time as a Julian day number
  570. static int observer_gettime(lua_State* l)
  571. {
  572.     CelxLua celx(l);
  573.     celx.checkArgs(1, 1, "No arguments expected to observer:gettime");
  574.     
  575.     Observer* o = this_observer(l);
  576.     lua_pushnumber(l, o->getTime());
  577.     
  578.     return 1;
  579. }
  580. // Return the observer's current position
  581. static int observer_getposition(lua_State* l)
  582. {
  583.     CelxLua celx(l);
  584.     celx.checkArgs(1, 1, "No arguments expected to observer:getposition");
  585.     
  586.     Observer* o = this_observer(l);
  587.     celx.newPosition(o->getPosition());
  588.     
  589.     return 1;
  590. }
  591. static int observer_getsurface(lua_State* l)
  592. {
  593.     CelxLua celx(l);
  594.     celx.checkArgs(1, 1, "One argument expected to observer:getsurface()");
  595.     
  596.     Observer* obs = this_observer(l);
  597.     lua_pushstring(l, obs->getDisplayedSurface().c_str());
  598.     
  599.     return 1;
  600. }
  601. static int observer_setsurface(lua_State* l)
  602. {
  603.     CelxLua celx(l);
  604.     celx.checkArgs(2, 2, "One argument expected to observer:setsurface()");
  605.     
  606.     Observer* obs = this_observer(l);
  607.     const char* s = lua_tostring(l, 2);
  608.     
  609.     if (s == NULL)
  610.         obs->setDisplayedSurface("");
  611.     else
  612.         obs->setDisplayedSurface(s);
  613.     
  614.     return 0;
  615. }
  616. static int observer_getframe(lua_State* l)
  617. {
  618.     CelxLua celx(l);
  619.     celx.checkArgs(1, 1, "No arguments expected for observer:getframe()");
  620.     
  621.     Observer* obs = this_observer(l);
  622.     
  623.     const ObserverFrame* frame = obs->getFrame();
  624.     celx.newFrame(*frame);
  625.     return 1;
  626. }
  627. static int observer_setframe(lua_State* l)
  628. {
  629.     CelxLua celx(l);
  630.     celx.checkArgs(2, 2, "One argument required for observer:setframe()");
  631.     
  632.     Observer* obs = this_observer(l);
  633.     
  634.     ObserverFrame* frame;
  635.     frame = celx.toFrame(2);
  636.     if (frame != NULL)
  637.     {
  638.         obs->setFrame(*frame);
  639.     }
  640.     else
  641.     {
  642.         celx.doError("Argument to observer:setframe must be a frame");
  643.     }
  644.     return 0;
  645. }
  646. static int observer_setspeed(lua_State* l)
  647. {
  648.     CelxLua celx(l);
  649.     celx.checkArgs(2, 2, "One argument required for observer:setspeed()");
  650.     
  651.     Observer* obs = this_observer(l);
  652.     
  653.     double speed = celx.safeGetNumber(2, AllErrors, "First argument to observer:setspeed must be a number");
  654.     obs->setTargetSpeed((float)speed);
  655.     return 0;
  656. }
  657. static int observer_getspeed(lua_State* l)
  658. {
  659.     CelxLua celx(l);
  660.     celx.checkArgs(1, 1, "No argument expected for observer:getspeed()");
  661.     
  662.     Observer* obs = this_observer(l);
  663.     
  664.     lua_pushnumber(l, (lua_Number)obs->getTargetSpeed());
  665.     return 1;
  666. }
  667. static int observer_setfov(lua_State* l)
  668. {
  669.     CelxLua celx(l);
  670.     celx.checkArgs(2, 2, "One argument expected to observer:setfov()");
  671.     
  672.     Observer* obs = this_observer(l);
  673.     double fov = celx.safeGetNumber(2, AllErrors, "Argument to observer:setfov() must be a number");
  674.     if ((fov >= degToRad(0.001f)) && (fov <= degToRad(120.0f)))
  675.     {
  676.         obs->setFOV((float) fov);
  677.         celx.appCore(AllErrors)->setZoomFromFOV();
  678.     }
  679.     return 0;
  680. }
  681. static int observer_getfov(lua_State* l)
  682. {
  683.     CelxLua celx(l);
  684.     celx.checkArgs(1, 1, "No argument expected to observer:getfov()");
  685.     
  686.     Observer* obs = this_observer(l);
  687.     lua_pushnumber(l, obs->getFOV());
  688.     return 1;
  689. }
  690. static int observer_splitview(lua_State* l)
  691. {
  692.     CelxLua celx(l);
  693.     celx.checkArgs(2, 3, "One or two arguments expected for observer:splitview()");
  694.     
  695.     Observer* obs = this_observer(l);
  696.     CelestiaCore* appCore = celx.appCore(AllErrors);
  697.     const char* splitType = celx.safeGetString(2, AllErrors, "First argument to observer:splitview() must be a string");
  698.     View::Type type = (compareIgnoringCase(splitType, "h") == 0) ? View::HorizontalSplit : View::VerticalSplit;
  699.     double splitPos = celx.safeGetNumber(3, WrongType, "Number expected as argument to observer:splitview()", 0.5);
  700.     if (splitPos < 0.1)
  701.         splitPos = 0.1;
  702.     if (splitPos > 0.9)
  703.         splitPos = 0.9;
  704.     View* view = getViewByObserver(appCore, obs);
  705.     appCore->splitView(type, view, (float)splitPos);
  706.     return 0;
  707. }
  708. static int observer_deleteview(lua_State* l)
  709. {
  710.     CelxLua celx(l);
  711.     celx.checkArgs(1, 1, "No argument expected for observer:deleteview()");
  712.     
  713.     Observer* obs = this_observer(l);
  714.     CelestiaCore* appCore = celx.appCore(AllErrors);
  715.     View* view = getViewByObserver(appCore, obs);
  716.     appCore->deleteView(view);
  717.     return 0;
  718. }
  719. static int observer_singleview(lua_State* l)
  720. {
  721.     CelxLua celx(l);
  722.     celx.checkArgs(1, 1, "No argument expected for observer:singleview()");
  723.     
  724.     Observer* obs = this_observer(l);
  725.     CelestiaCore* appCore = celx.appCore(AllErrors);
  726.     View* view = getViewByObserver(appCore, obs);
  727.     appCore->singleView(view);
  728.     return 0;
  729. }
  730. static int observer_makeactiveview(lua_State* l)
  731. {
  732.     CelxLua celx(l);
  733.     celx.checkArgs(1, 1, "No argument expected for observer:makeactiveview()");
  734.     Observer* obs = this_observer(l);
  735.     CelestiaCore* appCore = celx.appCore(AllErrors);
  736.     View* view = getViewByObserver(appCore, obs);
  737.     appCore->setActiveView(view);
  738.     return 0;
  739. }
  740. static int observer_equal(lua_State* l)
  741. {
  742.     CelxLua celx(l);
  743.     celx.checkArgs(2, 2, "Wrong number of arguments for comparison!");
  744.     
  745.     Observer* o1 = this_observer(l);
  746.     Observer* o2 = to_observer(l, 2);
  747.     
  748.     lua_pushboolean(l, (o1 == o2));
  749.     return 1;
  750. }
  751. static int observer_setlocationflags(lua_State* l)
  752. {
  753.     CelxLua celx(l);
  754.     celx.checkArgs(2, 2, "One argument expected for observer:setlocationflags()");
  755.     Observer* obs = this_observer(l);
  756.     if (!lua_istable(l, 2))
  757.     {
  758.         celx.doError("Argument to observer:setlocationflags() must be a table");
  759.     }
  760.     
  761.     lua_pushnil(l);
  762.     int locationFlags = obs->getLocationFilter();
  763.     while (lua_next(l, -2) != 0)
  764.     {
  765.         string key;
  766.         bool value = false;
  767.         if (lua_isstring(l, -2))
  768.         {
  769.             key = lua_tostring(l, -2);
  770.         }
  771.         else
  772.         {
  773.             celx.doError("Keys in table-argument to observer:setlocationflags() must be strings");
  774.         }
  775.         if (lua_isboolean(l, -1))
  776.         {
  777.             value = lua_toboolean(l, -1) != 0;
  778.         }
  779.         else
  780.         {
  781.             celx.doError("Values in table-argument to observer:setlocationflags() must be boolean");
  782.         }
  783.         if (CelxLua::LocationFlagMap.count(key) == 0)
  784.         {
  785.             cerr << "Unknown key: " << key << "n";
  786.         }
  787.         else
  788.         {
  789.             int flag = CelxLua::LocationFlagMap[key];
  790.             if (value)
  791.             {
  792.                 locationFlags |= flag;
  793.             }
  794.             else
  795.             {
  796.                 locationFlags &= ~flag;
  797.             }
  798.         }
  799.         lua_pop(l,1);
  800.     }
  801.     obs->setLocationFilter(locationFlags);
  802.     return 0;
  803. }
  804. static int observer_getlocationflags(lua_State* l)
  805. {
  806.     CelxLua celx(l);
  807.     celx.checkArgs(1, 1, "No arguments expected for observer:getlocationflags()");
  808.     Observer* obs = this_observer(l);
  809.     lua_newtable(l);
  810.     CelxLua::FlagMap::const_iterator it = CelxLua::LocationFlagMap.begin();
  811.     const int locationFlags = obs->getLocationFilter();
  812.     while (it != CelxLua::LocationFlagMap.end())
  813.     {
  814.         string key = it->first;
  815.         lua_pushstring(l, key.c_str());
  816.         lua_pushboolean(l, (it->second & locationFlags) != 0);
  817.         lua_settable(l,-3);
  818.         it++;
  819.     }
  820.     return 1;
  821. }
  822. void CreateObserverMetaTable(lua_State* l)
  823. {
  824.     CelxLua celx(l);
  825.     celx.createClassMetatable(Celx_Observer);
  826.     
  827.     celx.registerMethod("__tostring", observer_tostring);
  828.     celx.registerMethod("isvalid", observer_isvalid);
  829.     celx.registerMethod("goto", observer_goto);
  830.     celx.registerMethod("gotolonglat", observer_gotolonglat);
  831.     celx.registerMethod("gotolocation", observer_gotolocation);
  832.     celx.registerMethod("gotodistance", observer_gotodistance);
  833.     celx.registerMethod("gotosurface", observer_gotosurface);
  834.     celx.registerMethod("cancelgoto", observer_cancelgoto);
  835.     celx.registerMethod("setposition", observer_setposition);
  836.     celx.registerMethod("lookat", observer_lookat);
  837.     celx.registerMethod("setorientation", observer_setorientation);
  838.     celx.registerMethod("getorientation", observer_getorientation);
  839.     celx.registerMethod("getspeed", observer_getspeed);
  840.     celx.registerMethod("setspeed", observer_setspeed);
  841.     celx.registerMethod("getfov", observer_getfov);
  842.     celx.registerMethod("setfov", observer_setfov);
  843.     celx.registerMethod("rotate", observer_rotate);
  844.     celx.registerMethod("center", observer_center);
  845.     celx.registerMethod("centerorbit", observer_centerorbit);
  846.     celx.registerMethod("follow", observer_follow);
  847.     celx.registerMethod("synchronous", observer_synchronous);
  848.     celx.registerMethod("chase", observer_chase);
  849.     celx.registerMethod("lock", observer_lock);
  850.     celx.registerMethod("track", observer_track);
  851.     celx.registerMethod("gettrackedobject", observer_gettrackedobject);
  852.     celx.registerMethod("travelling", observer_travelling);
  853.     celx.registerMethod("getframe", observer_getframe);
  854.     celx.registerMethod("setframe", observer_setframe);
  855.     celx.registerMethod("gettime", observer_gettime);
  856.     celx.registerMethod("getposition", observer_getposition);
  857.     celx.registerMethod("getsurface", observer_getsurface);
  858.     celx.registerMethod("setsurface", observer_setsurface);
  859.     celx.registerMethod("splitview", observer_splitview);
  860.     celx.registerMethod("deleteview", observer_deleteview);
  861.     celx.registerMethod("singleview", observer_singleview);
  862.     celx.registerMethod("makeactiveview", observer_makeactiveview);
  863.     celx.registerMethod("getlocationflags", observer_getlocationflags);
  864.     celx.registerMethod("setlocationflags", observer_setlocationflags);
  865.     celx.registerMethod("__eq", observer_equal);
  866.     
  867.     lua_pop(l, 1); // remove metatable from stack
  868. }