2001-11-27 18:50:04 -07:00
|
|
|
// celestiacore.cpp
|
|
|
|
//
|
|
|
|
// Platform-independent UI handling and initialization for Celestia.
|
|
|
|
// winmain, gtkmain, and glutmain are thin, platform-specific modules
|
|
|
|
// that sit directly on top of CelestiaCore and feed it mouse and
|
|
|
|
// keyboard events. CelestiaCore then turns those events into calls
|
|
|
|
// to Renderer and Simulation.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2002-09-22 08:46:50 -06:00
|
|
|
#include <cstdio>
|
2001-11-27 18:50:04 -07:00
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cctype>
|
|
|
|
#include <cstring>
|
2002-03-26 21:41:23 -07:00
|
|
|
#include <cassert>
|
2002-10-12 17:00:00 -06:00
|
|
|
#include <ctime>
|
2003-07-29 23:54:45 -06:00
|
|
|
#include <locale>
|
2002-01-03 14:01:11 -07:00
|
|
|
#include <celengine/gl.h>
|
|
|
|
#include <celmath/vecmath.h>
|
|
|
|
#include <celmath/quaternion.h>
|
|
|
|
#include <celmath/mathlib.h>
|
|
|
|
#include <celutil/util.h>
|
2002-01-07 20:04:38 -07:00
|
|
|
#include <celutil/filetype.h>
|
|
|
|
#include <celutil/directory.h>
|
2002-01-03 14:01:11 -07:00
|
|
|
#include <celengine/astro.h>
|
|
|
|
#include <celengine/overlay.h>
|
|
|
|
#include <celengine/execution.h>
|
|
|
|
#include <celengine/cmdparser.h>
|
2002-02-18 01:23:57 -07:00
|
|
|
// #include <celengine/solarsysxml.h>
|
2002-02-13 13:38:49 -07:00
|
|
|
#include <celengine/multitexture.h>
|
2001-11-27 18:50:04 -07:00
|
|
|
#include "favorites.h"
|
|
|
|
#include "celestiacore.h"
|
2002-02-13 13:38:49 -07:00
|
|
|
#include <celutil/debug.h>
|
2003-01-23 15:42:43 -07:00
|
|
|
#include "url.h"
|
2001-12-10 21:20:05 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
static const int DragThreshold = 3;
|
|
|
|
|
|
|
|
// Perhaps you'll want to put this stuff in configuration file.
|
|
|
|
static const float fIncrementFactor = 10.0f;
|
|
|
|
static const double fMinSlewRate = 3.0;
|
|
|
|
static const double fMaxKeyAccel = 20.0;
|
|
|
|
static const float fAltitudeThreshold = 4.0f;
|
|
|
|
static const float RotationBraking = 10.0f;
|
|
|
|
static const float RotationDecay = 2.0f;
|
2002-05-02 01:58:50 -06:00
|
|
|
static const double MaximumTimeRate = 1.0e15;
|
2003-02-12 03:28:32 -07:00
|
|
|
static const float stdFOV = degToRad(45.0f);
|
|
|
|
static const float MaximumFOV = degToRad(120.0f);
|
|
|
|
static const float MinimumFOV = degToRad(0.001f);
|
2002-10-22 11:26:51 -06:00
|
|
|
static float KeyRotationAccel = degToRad(120.0f);
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2001-12-10 21:20:05 -07:00
|
|
|
|
2002-11-16 20:55:43 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
static void warning(string s)
|
|
|
|
{
|
|
|
|
cout << s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extremely basic implementation of an ExecutionEnvironment for
|
|
|
|
// running scripts.
|
|
|
|
class CoreExecutionEnvironment : public ExecutionEnvironment
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
CelestiaCore& core;
|
|
|
|
|
|
|
|
public:
|
|
|
|
CoreExecutionEnvironment(CelestiaCore& _core) : core(_core)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Simulation* getSimulation() const
|
|
|
|
{
|
|
|
|
return core.getSimulation();
|
|
|
|
}
|
|
|
|
|
|
|
|
Renderer* getRenderer() const
|
|
|
|
{
|
|
|
|
return core.getRenderer();
|
|
|
|
}
|
|
|
|
|
2002-09-22 03:24:45 -06:00
|
|
|
void showText(string s, int horig, int vorig, int hoff, int voff,
|
|
|
|
double duration)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-09-22 03:24:45 -06:00
|
|
|
core.showText(s, horig, vorig, hoff, voff, duration);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
View::View(View::Type _type,
|
|
|
|
Observer* _observer,
|
2003-02-11 09:43:37 -07:00
|
|
|
float _x, float _y,
|
|
|
|
float _width, float _height) :
|
2003-02-18 14:11:18 -07:00
|
|
|
type(_type),
|
2003-02-11 09:43:37 -07:00
|
|
|
observer(_observer),
|
2003-02-18 14:11:18 -07:00
|
|
|
parent(0),
|
|
|
|
child1(0),
|
|
|
|
child2(0),
|
2003-02-11 09:43:37 -07:00
|
|
|
x(_x),
|
|
|
|
y(_y),
|
|
|
|
width(_width),
|
2003-02-23 02:04:45 -07:00
|
|
|
height(_height),
|
|
|
|
renderFlags(0),
|
2003-06-03 14:11:09 -06:00
|
|
|
labelMode(0),
|
|
|
|
zoom(1),
|
|
|
|
alternateZoom(1)
|
2003-02-11 09:43:37 -07:00
|
|
|
{
|
|
|
|
}
|
2003-02-12 03:28:32 -07:00
|
|
|
|
|
|
|
void View::mapWindowToView(float wx, float wy, float& vx, float& vy) const
|
|
|
|
{
|
|
|
|
vx = (wx - x) / width;
|
|
|
|
vy = (wy + (y + height - 1)) / height;
|
|
|
|
vx = (vx - 0.5f) * (width / height);
|
|
|
|
vy = 0.5f - vy;
|
|
|
|
}
|
2003-02-18 14:11:18 -07:00
|
|
|
|
|
|
|
void View::walkTreeResize(View* sibling, int sign) {
|
|
|
|
float ratio;
|
|
|
|
switch (parent->type)
|
|
|
|
{
|
|
|
|
case View::HorizontalSplit:
|
|
|
|
ratio = parent->height / (parent->height - height);
|
|
|
|
sibling->height *= ratio;
|
|
|
|
if (sign == 1)
|
|
|
|
{
|
|
|
|
sibling->y = parent->y + (sibling->y - parent->y) * ratio;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sibling->y = parent->y + (sibling->y - (y + height)) * ratio;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case View::VerticalSplit:
|
|
|
|
ratio = parent->width / (parent->width - width);
|
|
|
|
sibling->width *= ratio;
|
|
|
|
if (sign == 1)
|
|
|
|
{
|
|
|
|
sibling->x = parent->x + (sibling->x - parent->x) * ratio;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sibling->x = parent->x + (sibling->x - (x + width) ) * ratio;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case View::ViewWindow:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sibling->child1) walkTreeResize(sibling->child1, sign);
|
|
|
|
if (sibling->child2) walkTreeResize(sibling->child2, sign);
|
|
|
|
}
|
|
|
|
|
2003-03-29 17:21:33 -07:00
|
|
|
bool View::walkTreeResizeDelta(View* v, float delta, bool check)
|
2003-03-08 17:32:11 -07:00
|
|
|
{
|
|
|
|
View *p=v;
|
|
|
|
int sign = -1;
|
|
|
|
float ratio;
|
2003-03-29 17:21:33 -07:00
|
|
|
double newSize;
|
2003-03-08 17:32:11 -07:00
|
|
|
|
2003-03-29 17:21:33 -07:00
|
|
|
if (v->child1)
|
|
|
|
{
|
|
|
|
if (!walkTreeResizeDelta(v->child1, delta, check))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v->child2)
|
|
|
|
{
|
|
|
|
if (!walkTreeResizeDelta(v->child2, delta, check))
|
|
|
|
return false;
|
|
|
|
}
|
2003-03-08 17:32:11 -07:00
|
|
|
|
|
|
|
while ( p != child1 && p != child2 && (p = p->parent) ) ;
|
|
|
|
if (p == child1) sign = 1;
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case View::HorizontalSplit:
|
|
|
|
delta = -delta;
|
|
|
|
ratio = (p->height + sign * delta) / p->height;
|
2003-03-29 17:21:33 -07:00
|
|
|
newSize = v->height * ratio;
|
|
|
|
if (newSize <= .1) return false;
|
|
|
|
if (check) return true;
|
|
|
|
v->height = newSize;
|
2003-03-08 17:32:11 -07:00
|
|
|
if (sign == 1)
|
|
|
|
{
|
|
|
|
v->y = p->y + (v->y - p->y) * ratio;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v->y = p->y + delta + (v->y - p->y) * ratio;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case View::VerticalSplit:
|
|
|
|
ratio = (p->width + sign * delta) / p->width;
|
2003-03-29 17:21:33 -07:00
|
|
|
newSize = v->width * ratio;
|
|
|
|
if (newSize <= .1) return false;
|
|
|
|
if (check) return true;
|
|
|
|
v->width = newSize;
|
2003-03-08 17:32:11 -07:00
|
|
|
if (sign == 1)
|
|
|
|
{
|
|
|
|
v->x = p->x + (v->x - p->x) * ratio;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v->x = p->x + delta + (v->x - p->x) * ratio;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case View::ViewWindow:
|
|
|
|
break;
|
|
|
|
}
|
2003-03-29 17:21:33 -07:00
|
|
|
|
|
|
|
return true;
|
2003-03-08 17:32:11 -07:00
|
|
|
}
|
2003-02-11 09:43:37 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
CelestiaCore::CelestiaCore() :
|
|
|
|
config(NULL),
|
2002-01-07 15:48:32 -07:00
|
|
|
universe(NULL),
|
2001-11-27 18:50:04 -07:00
|
|
|
favorites(NULL),
|
|
|
|
destinations(NULL),
|
|
|
|
sim(NULL),
|
|
|
|
renderer(NULL),
|
|
|
|
overlay(NULL),
|
|
|
|
width(1),
|
|
|
|
height(1),
|
|
|
|
font(NULL),
|
|
|
|
titleFont(NULL),
|
|
|
|
messageText(""),
|
2002-09-22 03:24:45 -06:00
|
|
|
messageHOrigin(0),
|
|
|
|
messageVOrigin(0),
|
|
|
|
messageHOffset(0),
|
|
|
|
messageVOffset(0),
|
|
|
|
messageStart(0.0),
|
|
|
|
messageDuration(0.0),
|
2001-11-27 18:50:04 -07:00
|
|
|
typedText(""),
|
|
|
|
textEnterMode(false),
|
|
|
|
hudDetail(1),
|
|
|
|
wireframe(false),
|
|
|
|
editMode(false),
|
2003-02-11 09:43:37 -07:00
|
|
|
altAzimuthMode(false),
|
2003-03-08 17:32:11 -07:00
|
|
|
lightTravelFlag(false),
|
2003-02-23 02:04:45 -07:00
|
|
|
flashFrameStart(0.0),
|
2001-12-11 17:11:19 -07:00
|
|
|
timer(NULL),
|
2001-11-27 18:50:04 -07:00
|
|
|
currentScript(NULL),
|
|
|
|
initScript(NULL),
|
|
|
|
demoScript(NULL),
|
|
|
|
runningScript(NULL),
|
|
|
|
execEnv(NULL),
|
2003-04-12 23:58:34 -06:00
|
|
|
#ifdef CELX
|
|
|
|
celxScript(NULL),
|
|
|
|
scriptAwakenTime(0.0),
|
|
|
|
#endif // CELX
|
2001-11-27 18:50:04 -07:00
|
|
|
timeZoneBias(0),
|
|
|
|
showFPSCounter(false),
|
|
|
|
nFrames(0),
|
|
|
|
fps(0.0),
|
|
|
|
fpsCounterStartTime(0.0),
|
2002-06-22 09:18:47 -06:00
|
|
|
oldFOV(stdFOV),
|
2001-11-27 18:50:04 -07:00
|
|
|
mouseMotion(0.0f),
|
|
|
|
dollyMotion(0.0),
|
|
|
|
dollyTime(0.0),
|
|
|
|
zoomMotion(0.0),
|
|
|
|
zoomTime(0.0),
|
2001-12-11 17:11:19 -07:00
|
|
|
sysTime(0.0),
|
2001-11-27 18:50:04 -07:00
|
|
|
currentTime(0.0),
|
|
|
|
timeScale(1.0),
|
|
|
|
paused(false),
|
|
|
|
joystickRotation(0.0f, 0.0f, 0.0f),
|
|
|
|
KeyAccel(1.0),
|
2001-12-10 21:20:05 -07:00
|
|
|
movieCapture(NULL),
|
|
|
|
recording(false),
|
2001-11-27 18:50:04 -07:00
|
|
|
contextMenuCallback(NULL),
|
|
|
|
logoTexture(NULL),
|
2002-11-07 22:08:34 -07:00
|
|
|
alerter(NULL),
|
2003-02-11 09:43:37 -07:00
|
|
|
historyCurrent(0),
|
2003-03-08 17:32:11 -07:00
|
|
|
activeView(0),
|
|
|
|
showActiveViewFrame(false),
|
|
|
|
showViewFrames(true),
|
2003-05-31 04:55:44 -06:00
|
|
|
resizeSplit(0),
|
2003-06-03 14:11:09 -06:00
|
|
|
typedTextCompletionIdx(-1),
|
|
|
|
screenDpi(96),
|
|
|
|
distanceToScreen(400)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-02 15:07:11 -07:00
|
|
|
/* Get a renderer here so it may be queried for capabilities of the
|
|
|
|
underlying engine even before rendering is enabled. It's initRenderer()
|
|
|
|
routine will be called much later. */
|
|
|
|
renderer = new Renderer();
|
2001-12-11 17:11:19 -07:00
|
|
|
timer = CreateTimer();
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
execEnv = new CoreExecutionEnvironment(*this);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < KeyCount; i++)
|
2003-07-18 23:46:57 -06:00
|
|
|
{
|
2001-11-27 18:50:04 -07:00
|
|
|
keysPressed[i] = false;
|
2003-07-18 23:46:57 -06:00
|
|
|
shiftKeysPressed[i] = false;
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
for (i = 0; i < JoyButtonCount; i++)
|
|
|
|
joyButtonsPressed[i] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CelestiaCore::~CelestiaCore()
|
|
|
|
{
|
2001-12-10 21:20:05 -07:00
|
|
|
if (movieCapture != NULL)
|
|
|
|
recordEnd();
|
2001-11-27 18:50:04 -07:00
|
|
|
delete execEnv;
|
|
|
|
}
|
|
|
|
|
2002-02-28 16:29:13 -07:00
|
|
|
void CelestiaCore::readFavoritesFile()
|
|
|
|
{
|
|
|
|
// Set up favorites list
|
|
|
|
if (config->favoritesFile != "")
|
|
|
|
{
|
|
|
|
ifstream in(config->favoritesFile.c_str(), ios::in);
|
|
|
|
|
|
|
|
if (in.good())
|
|
|
|
{
|
|
|
|
favorites = ReadFavoritesList(in);
|
|
|
|
if (favorites == NULL)
|
|
|
|
{
|
|
|
|
warning("Error reading favorites file.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
void CelestiaCore::writeFavoritesFile()
|
|
|
|
{
|
|
|
|
if (config->favoritesFile != "")
|
|
|
|
{
|
|
|
|
ofstream out(config->favoritesFile.c_str(), ios::out);
|
|
|
|
if (out.good())
|
|
|
|
WriteFavoritesList(*favorites, out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::activateFavorite(FavoritesEntry& fav)
|
|
|
|
{
|
|
|
|
sim->cancelMotion();
|
|
|
|
sim->setTime(fav.jd);
|
2002-01-09 16:04:14 -07:00
|
|
|
sim->setObserverPosition(fav.position);
|
|
|
|
sim->setObserverOrientation(fav.orientation);
|
2002-01-09 17:15:02 -07:00
|
|
|
sim->setSelection(sim->findObjectFromPath(fav.selectionName));
|
|
|
|
sim->setFrame(fav.coordSys, sim->getSelection());
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
2002-10-03 03:46:42 -06:00
|
|
|
void CelestiaCore::addFavorite(string name, string parentFolder, FavoritesList::iterator* iter)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-02-27 12:37:14 -07:00
|
|
|
FavoritesList::iterator pos;
|
|
|
|
if(!iter)
|
|
|
|
pos = favorites->end();
|
|
|
|
else
|
2002-10-03 03:46:42 -06:00
|
|
|
pos = *iter;
|
2001-11-27 18:50:04 -07:00
|
|
|
FavoritesEntry* fav = new FavoritesEntry();
|
|
|
|
fav->jd = sim->getTime();
|
|
|
|
fav->position = sim->getObserver().getPosition();
|
|
|
|
fav->orientation = sim->getObserver().getOrientation();
|
|
|
|
fav->name = name;
|
2002-02-27 12:37:14 -07:00
|
|
|
fav->isFolder = false;
|
|
|
|
fav->parentFolder = parentFolder;
|
2002-01-09 17:15:02 -07:00
|
|
|
fav->selectionName = sim->getSelection().getName();
|
|
|
|
fav->coordSys = sim->getFrame().coordSys;
|
|
|
|
|
2002-02-27 12:37:14 -07:00
|
|
|
favorites->insert(pos, fav);
|
|
|
|
}
|
|
|
|
|
2002-10-03 03:46:42 -06:00
|
|
|
void CelestiaCore::addFavoriteFolder(string name, FavoritesList::iterator* iter)
|
2002-02-27 12:37:14 -07:00
|
|
|
{
|
|
|
|
FavoritesList::iterator pos;
|
|
|
|
if(!iter)
|
|
|
|
pos = favorites->end();
|
|
|
|
else
|
2002-10-03 03:46:42 -06:00
|
|
|
pos = *iter;
|
2002-02-27 12:37:14 -07:00
|
|
|
FavoritesEntry* fav = new FavoritesEntry();
|
|
|
|
fav->name = name;
|
|
|
|
fav->isFolder = true;
|
|
|
|
|
|
|
|
favorites->insert(pos, fav);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
2002-10-03 03:46:42 -06:00
|
|
|
FavoritesList* CelestiaCore::getFavorites()
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
return favorites;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DestinationList* CelestiaCore::getDestinations()
|
|
|
|
{
|
|
|
|
return destinations;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Used in the super-secret edit mode
|
|
|
|
void showSelectionInfo(const Selection& sel)
|
|
|
|
{
|
2003-06-25 11:40:24 -06:00
|
|
|
if (sel.deepsky() != NULL)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2003-06-25 11:40:24 -06:00
|
|
|
cout << sel.deepsky()->getName() << '\n';
|
2001-11-27 18:50:04 -07:00
|
|
|
Vec3f axis;
|
|
|
|
float angle;
|
2003-06-25 11:40:24 -06:00
|
|
|
sel.deepsky()->getOrientation().getAxisAngle(axis, angle);
|
2001-11-27 18:50:04 -07:00
|
|
|
cout << "Orientation: " << '[' << axis.x << ',' << axis.y << ',' << axis.z << "], " << radToDeg(angle) << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::cancelScript()
|
|
|
|
{
|
|
|
|
if (runningScript != NULL)
|
|
|
|
{
|
|
|
|
delete runningScript;
|
|
|
|
runningScript = NULL;
|
|
|
|
}
|
2003-04-16 11:19:49 -06:00
|
|
|
#ifdef CELX
|
|
|
|
else if (celxScript != NULL)
|
|
|
|
{
|
|
|
|
// The script is complete
|
|
|
|
delete celxScript;
|
|
|
|
celxScript = NULL;
|
|
|
|
scriptAwakenTime = 0.0;
|
|
|
|
}
|
|
|
|
#endif
|
2001-11-27 18:50:04 -07:00
|
|
|
messageText = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-26 18:50:54 -07:00
|
|
|
void CelestiaCore::runScript(CommandSequence* script)
|
|
|
|
{
|
|
|
|
if (runningScript == NULL && script != NULL)
|
|
|
|
runningScript = new Execution(*script, *execEnv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-11 02:57:17 -06:00
|
|
|
void CelestiaCore::runScript(const string& filename)
|
|
|
|
{
|
|
|
|
#ifdef CELX
|
2003-04-12 23:58:34 -06:00
|
|
|
if (runningScript == NULL && celxScript == NULL)
|
2003-04-11 02:57:17 -06:00
|
|
|
{
|
|
|
|
ifstream scriptfile(filename.c_str());
|
|
|
|
if (!scriptfile.good())
|
|
|
|
{
|
2003-05-06 03:44:09 -06:00
|
|
|
char errMsg[1024];
|
|
|
|
sprintf(errMsg, "Error opening script '%s'", filename.c_str());
|
|
|
|
if (alerter != NULL)
|
|
|
|
alerter->fatalError(errMsg);
|
|
|
|
else
|
|
|
|
flash(errMsg);
|
2003-04-11 02:57:17 -06:00
|
|
|
}
|
|
|
|
|
2003-04-12 23:58:34 -06:00
|
|
|
celxScript = new LuaState();
|
|
|
|
celxScript->init(this);
|
2003-05-06 03:44:09 -06:00
|
|
|
int status = celxScript->loadScript(scriptfile, filename);
|
2003-04-11 02:57:17 -06:00
|
|
|
if (status != 0)
|
|
|
|
{
|
2003-05-06 03:44:09 -06:00
|
|
|
string errMsg = celxScript->getErrorMessage();
|
|
|
|
if (errMsg.empty())
|
|
|
|
errMsg = "Unknown error opening script";
|
|
|
|
if (alerter != NULL)
|
|
|
|
alerter->fatalError(errMsg);
|
|
|
|
else
|
|
|
|
flash(errMsg);
|
|
|
|
|
2003-04-12 23:58:34 -06:00
|
|
|
delete celxScript;
|
|
|
|
celxScript = NULL;
|
2003-04-11 02:57:17 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-04-12 23:58:34 -06:00
|
|
|
// Coroutine execution; control may be transferred between the
|
|
|
|
// script and Celestia's event loop
|
|
|
|
if (celxScript->createThread())
|
|
|
|
{
|
|
|
|
resumeScript();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-06 03:44:09 -06:00
|
|
|
char* errMsg = "Script coroutine initialization failed";
|
|
|
|
if (alerter != NULL)
|
|
|
|
alerter->fatalError(errMsg);
|
|
|
|
else
|
|
|
|
flash(errMsg);
|
2003-04-12 23:58:34 -06:00
|
|
|
delete celxScript;
|
|
|
|
celxScript = NULL;
|
|
|
|
}
|
2003-04-11 02:57:17 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-12 23:58:34 -06:00
|
|
|
void CelestiaCore::resumeScript()
|
|
|
|
{
|
|
|
|
#ifdef CELX
|
|
|
|
if (celxScript != NULL)
|
|
|
|
{
|
|
|
|
int nArgs = celxScript->resume();
|
|
|
|
if (!celxScript->isAlive())
|
|
|
|
{
|
|
|
|
// The script is complete
|
|
|
|
delete celxScript;
|
|
|
|
celxScript = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The script has returned control to us, but it is not completed.
|
|
|
|
lua_State* state = celxScript->getState();
|
|
|
|
|
|
|
|
// The values on the stack indicate what event will wake up the
|
|
|
|
// script. For now, we just support wait()
|
|
|
|
double delay;
|
|
|
|
if (nArgs == 1 && lua_isnumber(state, -1))
|
|
|
|
delay = lua_tonumber(state, -1);
|
|
|
|
else
|
|
|
|
delay = 0.0;
|
|
|
|
scriptAwakenTime = currentTime + delay;
|
|
|
|
|
|
|
|
// Clean up the stack
|
|
|
|
lua_pop(state, nArgs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // CELX
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
bool checkMask(int modifiers, int mask)
|
|
|
|
{
|
|
|
|
return (modifiers & mask) == mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::mouseButtonDown(float x, float y, int button)
|
|
|
|
{
|
|
|
|
mouseMotion = 0.0f;
|
2003-03-08 17:32:11 -07:00
|
|
|
|
|
|
|
if (views.size() > 1 && button == LeftButton) // look if click is near a view border
|
|
|
|
{
|
|
|
|
View *v1 = 0, *v2 = 0;
|
|
|
|
for(std::vector<View*>::iterator i = views.begin(); i != views.end(); i++)
|
|
|
|
{
|
|
|
|
View* v = *i;
|
|
|
|
float vx, vy, vxp, vyp;
|
|
|
|
vx = ( x / width - v->x ) / v->width;
|
|
|
|
vy = ( (1 - y / height ) - v->y ) / v->height;
|
|
|
|
vxp = vx * v->width * width;
|
|
|
|
vyp = vy * v->height * height;
|
|
|
|
if ( vx >=0 && vx <= 1 && ( abs(vyp) <= 2 || abs(vyp - v->height * height) <= 2)
|
|
|
|
|| vy >=0 && vy <= 1 && ( abs(vxp) <= 2 || abs(vxp - v->width * width) <= 2) )
|
|
|
|
{
|
|
|
|
if (v1 == 0)
|
|
|
|
{
|
|
|
|
v1 = v;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v2 = v;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (v2 != 0) {
|
|
|
|
// Look for common ancestor to v1 & v2 = split being draged.
|
|
|
|
View *p1 = v1, *p2 = v2;
|
|
|
|
while ( (p1 = p1->parent) )
|
|
|
|
{
|
|
|
|
p2 = v2;
|
|
|
|
while ( (p2 = p2->parent) && p1 != p2) ;
|
|
|
|
if (p2 != 0) break;
|
|
|
|
}
|
|
|
|
if (p2 != 0)
|
|
|
|
{
|
|
|
|
resizeSplit = p1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::mouseButtonUp(float x, float y, int button)
|
|
|
|
{
|
2003-02-11 16:43:52 -07:00
|
|
|
|
2002-01-23 17:51:26 -07:00
|
|
|
// Four pixel tolerance for picking
|
2003-02-12 03:28:32 -07:00
|
|
|
float pickTolerance = sim->getActiveObserver()->getFOV() / height * 4.0f;
|
2002-01-23 17:51:26 -07:00
|
|
|
|
2003-03-08 17:32:11 -07:00
|
|
|
if (resizeSplit)
|
|
|
|
{
|
|
|
|
resizeSplit = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
// If the mouse hasn't moved much since it was pressed, treat this
|
|
|
|
// as a selection or context menu event. Otherwise, assume that the
|
|
|
|
// mouse was dragged and ignore the event.
|
|
|
|
if (mouseMotion < DragThreshold)
|
|
|
|
{
|
|
|
|
if (button == LeftButton)
|
|
|
|
{
|
2003-02-11 16:43:52 -07:00
|
|
|
if (x < views[activeView]->x * width || x > (views[activeView]->x + views[activeView]->width) * width
|
|
|
|
|| (height - y) < views[activeView]->y * height || (height - y) > (views[activeView]->y + views[activeView]->height) * height)
|
|
|
|
{
|
|
|
|
std::vector<View*>::iterator i = views.begin();
|
|
|
|
int n = 0;
|
|
|
|
while (i < views.end() && (x < (*i)->x * width || x > ((*i)->x + (*i)->width) * width
|
|
|
|
|| (height - y) < (*i)->y * height || (height - y) > ((*i)->y + (*i)->height) * height))
|
|
|
|
{
|
|
|
|
i++; n++;
|
|
|
|
}
|
|
|
|
activeView = n;
|
|
|
|
sim->setActiveObserver(views[activeView]->observer);
|
2003-03-11 03:00:25 -07:00
|
|
|
if (!showActiveViewFrame)
|
|
|
|
flashFrameStart = currentTime;
|
2003-02-11 16:43:52 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-02-12 03:28:32 -07:00
|
|
|
float pickX, pickY;
|
|
|
|
float aspectRatio = ((float) width / (float) height);
|
|
|
|
views[activeView]->mapWindowToView((float) x / (float) width,
|
|
|
|
(float) y / (float) height,
|
|
|
|
pickX, pickY);
|
|
|
|
Vec3f pickRay =
|
|
|
|
sim->getActiveObserver()->getPickRay(pickX * aspectRatio, pickY);
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
Selection oldSel = sim->getSelection();
|
2002-01-23 17:51:26 -07:00
|
|
|
Selection newSel = sim->pickObject(pickRay, pickTolerance);
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2001-11-27 18:50:04 -07:00
|
|
|
sim->setSelection(newSel);
|
|
|
|
if (!oldSel.empty() && oldSel == newSel)
|
|
|
|
sim->centerSelection();
|
|
|
|
}
|
|
|
|
else if (button == RightButton)
|
|
|
|
{
|
2003-02-12 03:28:32 -07:00
|
|
|
float pickX, pickY;
|
|
|
|
float aspectRatio = ((float) width / (float) height);
|
|
|
|
views[activeView]->mapWindowToView((float) x / (float) width,
|
|
|
|
(float) y / (float) height,
|
|
|
|
pickX, pickY);
|
|
|
|
Vec3f pickRay =
|
|
|
|
sim->getActiveObserver()->getPickRay(pickX * aspectRatio, pickY);
|
|
|
|
|
2002-01-23 17:51:26 -07:00
|
|
|
Selection sel = sim->pickObject(pickRay, pickTolerance);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (!sel.empty())
|
|
|
|
{
|
|
|
|
if (contextMenuCallback != NULL)
|
|
|
|
contextMenuCallback(x, y, sel);
|
|
|
|
}
|
|
|
|
}
|
2002-05-15 13:03:59 -06:00
|
|
|
else if (button == MiddleButton)
|
|
|
|
{
|
2003-06-03 14:11:09 -06:00
|
|
|
if (views[activeView]->zoom != 1)
|
2003-03-08 17:32:11 -07:00
|
|
|
{
|
2003-06-03 14:11:09 -06:00
|
|
|
views[activeView]->alternateZoom = views[activeView]->zoom;
|
|
|
|
views[activeView]->zoom = 1;
|
2002-05-15 13:03:59 -06:00
|
|
|
}
|
|
|
|
else
|
2003-02-12 03:28:32 -07:00
|
|
|
{
|
2003-06-03 14:11:09 -06:00
|
|
|
views[activeView]->zoom = views[activeView]->alternateZoom;
|
2003-02-12 03:28:32 -07:00
|
|
|
}
|
2003-06-03 14:11:09 -06:00
|
|
|
setFOVFromZoom();
|
2002-09-22 08:46:50 -06:00
|
|
|
|
|
|
|
// If AutoMag, adapt the faintestMag to the new fov
|
|
|
|
if((renderer->getRenderFlags() & Renderer::ShowAutoMag) != 0)
|
|
|
|
setFaintestAutoMag();
|
2002-05-15 13:03:59 -06:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::mouseWheel(float motion, int modifiers)
|
|
|
|
{
|
|
|
|
if (motion != 0.0)
|
|
|
|
{
|
|
|
|
if ((modifiers & ShiftKey) != 0)
|
|
|
|
{
|
|
|
|
zoomTime = currentTime;
|
|
|
|
zoomMotion = 0.25f * motion;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dollyTime = currentTime;
|
|
|
|
dollyMotion = 0.25f * motion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::mouseMove(float dx, float dy, int modifiers)
|
|
|
|
{
|
2003-03-08 17:32:11 -07:00
|
|
|
if (resizeSplit != 0)
|
|
|
|
{
|
|
|
|
switch(resizeSplit->type) {
|
|
|
|
case View::HorizontalSplit:
|
2003-03-29 17:21:33 -07:00
|
|
|
if ( resizeSplit->walkTreeResizeDelta(resizeSplit->child1, dy / height, true)
|
|
|
|
&& resizeSplit->walkTreeResizeDelta(resizeSplit->child2, dy / height, true))
|
|
|
|
{
|
|
|
|
resizeSplit->walkTreeResizeDelta(resizeSplit->child1, dy / height, false);
|
|
|
|
resizeSplit->walkTreeResizeDelta(resizeSplit->child2, dy / height, false);
|
|
|
|
}
|
2003-03-08 17:32:11 -07:00
|
|
|
break;
|
|
|
|
case View::VerticalSplit:
|
2003-03-29 17:21:33 -07:00
|
|
|
if ( resizeSplit->walkTreeResizeDelta(resizeSplit->child1, dx / width, true)
|
|
|
|
&& resizeSplit->walkTreeResizeDelta(resizeSplit->child2, dx / width, true)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
resizeSplit->walkTreeResizeDelta(resizeSplit->child1, dx / width, false);
|
|
|
|
resizeSplit->walkTreeResizeDelta(resizeSplit->child2, dx / width, false);
|
|
|
|
}
|
2003-03-08 17:32:11 -07:00
|
|
|
break;
|
|
|
|
case View::ViewWindow:
|
|
|
|
break;
|
|
|
|
}
|
2003-06-03 14:11:09 -06:00
|
|
|
setFOVFromZoom();
|
2003-03-08 17:32:11 -07:00
|
|
|
return;
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
if ((modifiers & (LeftButton | RightButton)) != 0)
|
|
|
|
{
|
|
|
|
if (editMode && checkMask(modifiers, LeftButton | ShiftKey | ControlKey))
|
|
|
|
{
|
|
|
|
// Rotate the selected object
|
|
|
|
Selection sel = sim->getSelection();
|
|
|
|
Quatf q(1);
|
2003-06-25 11:40:24 -06:00
|
|
|
if (sel.getType() == Selection::Type_DeepSky)
|
|
|
|
q = sel.deepsky()->getOrientation();
|
|
|
|
else if (sel.getType() == Selection::Type_Body)
|
|
|
|
q = sel.body()->getOrientation();
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
q.yrotate(dx / width);
|
|
|
|
q.xrotate(dy / height);
|
|
|
|
|
2003-06-25 11:40:24 -06:00
|
|
|
if (sel.getType() == Selection::Type_DeepSky)
|
|
|
|
sel.deepsky()->setOrientation(q);
|
|
|
|
else if (sel.getType() == Selection::Type_Body)
|
|
|
|
sel.body()->setOrientation(q);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
2003-05-28 03:14:48 -06:00
|
|
|
else if (editMode && checkMask(modifiers, RightButton | ShiftKey | ControlKey))
|
|
|
|
{
|
|
|
|
// Rotate the selected object about an axis from its center to the
|
|
|
|
// viewer.
|
|
|
|
Selection sel = sim->getSelection();
|
2003-06-25 11:40:24 -06:00
|
|
|
if (sel.deepsky() != NULL)
|
2003-05-28 03:14:48 -06:00
|
|
|
{
|
|
|
|
double t = sim->getTime();
|
|
|
|
Vec3d v = sel.getPosition(t) - sim->getObserver().getPosition();
|
|
|
|
Vec3f axis((float) v.x, (float) v.y, (float) v.z);
|
|
|
|
axis.normalize();
|
|
|
|
|
|
|
|
Quatf r;
|
|
|
|
r.setAxisAngle(axis, dx / width);
|
|
|
|
|
2003-06-25 11:40:24 -06:00
|
|
|
Quatf q = sel.deepsky()->getOrientation();
|
|
|
|
sel.deepsky()->setOrientation(r * q);
|
2003-05-28 03:14:48 -06:00
|
|
|
}
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
else if (checkMask(modifiers, LeftButton | RightButton) ||
|
|
|
|
checkMask(modifiers, LeftButton | ControlKey))
|
|
|
|
{
|
|
|
|
float amount = dy / height;
|
|
|
|
sim->changeOrbitDistance(amount * 5);
|
|
|
|
}
|
|
|
|
else if (checkMask(modifiers, LeftButton | ShiftKey))
|
|
|
|
{
|
|
|
|
// Mouse zoom control
|
|
|
|
float amount = dy / height;
|
2002-11-16 20:55:43 -07:00
|
|
|
float minFOV = MinimumFOV;
|
|
|
|
float maxFOV = MaximumFOV;
|
2003-02-12 03:28:32 -07:00
|
|
|
float fov = sim->getActiveObserver()->getFOV();
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
if (fov < minFOV)
|
|
|
|
fov = minFOV;
|
|
|
|
|
|
|
|
// In order for the zoom to have the right feel, it should be
|
|
|
|
// exponential.
|
|
|
|
float newFOV = minFOV + (float) exp(log(fov - minFOV) + amount * 4);
|
|
|
|
if (newFOV < minFOV)
|
|
|
|
newFOV = minFOV;
|
|
|
|
else if (newFOV > maxFOV)
|
|
|
|
newFOV = maxFOV;
|
2003-02-12 03:28:32 -07:00
|
|
|
sim->getActiveObserver()->setFOV(newFOV);
|
2003-06-03 14:11:09 -06:00
|
|
|
setZoomFromFOV();
|
|
|
|
|
2003-02-12 03:28:32 -07:00
|
|
|
if ((renderer->getRenderFlags() & Renderer::ShowAutoMag))
|
2002-09-22 15:45:23 -06:00
|
|
|
{
|
2002-09-22 08:46:50 -06:00
|
|
|
setFaintestAutoMag();
|
2002-09-22 15:45:23 -06:00
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Magnitude limit: %.2f", sim->getFaintestVisible());
|
|
|
|
flash(buf);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Quatf q(1);
|
|
|
|
// For a small field of view, rotate the camera more finely
|
|
|
|
float coarseness = 1.5f;
|
|
|
|
if ((modifiers & RightButton) == 0)
|
2003-02-12 03:28:32 -07:00
|
|
|
coarseness = radToDeg(sim->getActiveObserver()->getFOV()) / 30.0f;
|
2001-11-27 18:50:04 -07:00
|
|
|
q.yrotate(dx / width * coarseness);
|
|
|
|
q.xrotate(dy / height * coarseness);
|
|
|
|
if ((modifiers & RightButton) != 0)
|
|
|
|
sim->orbit(q);
|
|
|
|
else
|
|
|
|
sim->rotate(~q);
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseMotion += abs(dy) + abs(dx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::joystickAxis(int axis, float amount)
|
|
|
|
{
|
|
|
|
float deadZone = 0.25f;
|
|
|
|
|
|
|
|
if (abs(amount) < deadZone)
|
|
|
|
amount = 0.0f;
|
|
|
|
else
|
|
|
|
amount = (amount - deadZone) * (1.0f / (1.0f - deadZone));
|
|
|
|
|
|
|
|
amount = sign(amount) * square(amount);
|
|
|
|
|
|
|
|
if (axis == Joy_XAxis)
|
|
|
|
joystickRotation.y = amount;
|
|
|
|
else if (axis == Joy_YAxis)
|
|
|
|
joystickRotation.x = -amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::joystickButton(int button, bool down)
|
|
|
|
{
|
|
|
|
if (button >= 0 && button < JoyButtonCount)
|
|
|
|
joyButtonsPressed[button] = down;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-18 23:46:57 -06:00
|
|
|
void CelestiaCore::keyDown(int key, int modifiers)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case Key_F1:
|
|
|
|
sim->setTargetSpeed(0);
|
|
|
|
break;
|
|
|
|
case Key_F2:
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(astro::kilometersToMicroLightYears(1.0));
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
case Key_F3:
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(astro::kilometersToMicroLightYears(1000.0));
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
case Key_F4:
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(astro::kilometersToMicroLightYears(astro::speedOfLight));
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
case Key_F5:
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(astro::kilometersToMicroLightYears(astro::speedOfLight * 10.0));
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
case Key_F6:
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(astro::AUtoMicroLightYears(1.0));
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
case Key_F7:
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(1e6);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
2001-12-10 21:20:05 -07:00
|
|
|
case Key_F11:
|
|
|
|
if (movieCapture != NULL)
|
2001-12-11 17:11:19 -07:00
|
|
|
{
|
|
|
|
if (isRecording())
|
|
|
|
recordPause();
|
|
|
|
else
|
|
|
|
recordBegin();
|
|
|
|
}
|
2001-12-10 21:20:05 -07:00
|
|
|
break;
|
|
|
|
case Key_F12:
|
|
|
|
if (movieCapture != NULL)
|
|
|
|
recordEnd();
|
|
|
|
break;
|
2001-11-27 18:50:04 -07:00
|
|
|
case Key_NumPad2:
|
|
|
|
case Key_NumPad4:
|
|
|
|
case Key_NumPad6:
|
|
|
|
case Key_NumPad7:
|
|
|
|
case Key_NumPad8:
|
|
|
|
case Key_NumPad9:
|
|
|
|
sim->setTargetSpeed(sim->getTargetSpeed());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
if (KeyAccel < fMaxKeyAccel)
|
2001-11-27 18:50:04 -07:00
|
|
|
KeyAccel *= 1.1;
|
|
|
|
|
|
|
|
// Only process alphanumeric keys if we're not in text enter mode
|
|
|
|
if (islower(key))
|
|
|
|
key = toupper(key);
|
|
|
|
if (!(key >= 'A' && key <= 'Z' && textEnterMode))
|
2003-07-18 23:46:57 -06:00
|
|
|
{
|
|
|
|
if (modifiers & ShiftKey)
|
|
|
|
shiftKeysPressed[key] = true;
|
|
|
|
else
|
|
|
|
keysPressed[key] = true;
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
2003-07-18 23:46:57 -06:00
|
|
|
void CelestiaCore::keyUp(int key, int modifiers)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
KeyAccel = 1.0;
|
|
|
|
if (islower(key))
|
|
|
|
key = toupper(key);
|
|
|
|
keysPressed[key] = false;
|
2003-07-18 23:46:57 -06:00
|
|
|
shiftKeysPressed[key] = false;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::charEntered(char c)
|
|
|
|
{
|
2003-02-12 03:28:32 -07:00
|
|
|
Observer* observer = sim->getActiveObserver();
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (textEnterMode)
|
|
|
|
{
|
2003-05-31 04:55:44 -06:00
|
|
|
if ( c == ' ' || isalpha(c) || isdigit(c) || ispunct(c))
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
typedText += c;
|
2003-05-31 04:55:44 -06:00
|
|
|
typedTextCompletion = sim->getObjectCompletion(typedText);
|
2003-06-03 14:11:09 -06:00
|
|
|
typedTextCompletionIdx = -1;
|
|
|
|
#ifdef AUTO_COMPLETION
|
2003-05-31 15:40:40 -06:00
|
|
|
if (typedTextCompletion.size() == 1)
|
|
|
|
{
|
|
|
|
std::string::size_type pos = typedText.rfind('/', typedText.length());
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
typedText = typedText.substr(0, pos + 1) + typedTextCompletion[0];
|
|
|
|
else
|
2003-05-31 04:55:44 -06:00
|
|
|
typedText = typedTextCompletion[0];
|
2003-05-31 15:40:40 -06:00
|
|
|
}
|
2003-06-03 14:11:09 -06:00
|
|
|
#endif
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
else if (c == '\b')
|
|
|
|
{
|
2003-05-31 04:55:44 -06:00
|
|
|
typedTextCompletionIdx = -1;
|
2001-11-27 18:50:04 -07:00
|
|
|
if (typedText.size() > 0)
|
2003-05-31 04:55:44 -06:00
|
|
|
{
|
2003-06-03 14:11:09 -06:00
|
|
|
#ifdef AUTO_COMPLETION
|
2003-05-31 04:55:44 -06:00
|
|
|
do
|
|
|
|
{
|
2003-06-03 14:11:09 -06:00
|
|
|
#endif
|
2003-05-31 04:55:44 -06:00
|
|
|
typedText = string(typedText, 0, typedText.size() - 1);
|
|
|
|
if (typedText.size() > 0)
|
|
|
|
{
|
|
|
|
typedTextCompletion = sim->getObjectCompletion(typedText);
|
|
|
|
} else {
|
|
|
|
typedTextCompletion.clear();
|
|
|
|
}
|
2003-06-03 14:11:09 -06:00
|
|
|
#ifdef AUTO_COMPLETION
|
2003-05-31 04:55:44 -06:00
|
|
|
} while (typedText.size() > 0 && typedTextCompletion.size() == 1);
|
2003-06-03 14:11:09 -06:00
|
|
|
#endif
|
2003-05-31 04:55:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (c == '\011') // TAB
|
|
|
|
{
|
|
|
|
if (typedTextCompletionIdx + 1 < typedTextCompletion.size())
|
|
|
|
typedTextCompletionIdx++;
|
|
|
|
else if (typedTextCompletion.size() > 0 && typedTextCompletionIdx + 1 == typedTextCompletion.size())
|
|
|
|
typedTextCompletionIdx = 0;
|
|
|
|
if (typedTextCompletionIdx >= 0) {
|
2003-05-31 15:40:40 -06:00
|
|
|
std::string::size_type pos = typedText.rfind('/', typedText.length());
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
typedText = typedText.substr(0, pos + 1) + typedTextCompletion[typedTextCompletionIdx];
|
|
|
|
else
|
|
|
|
typedText = typedTextCompletion[typedTextCompletionIdx];
|
2003-05-31 04:55:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (c == Key_BackTab)
|
|
|
|
{
|
|
|
|
if (typedTextCompletionIdx > 0)
|
|
|
|
typedTextCompletionIdx--;
|
|
|
|
else if (typedTextCompletionIdx == 0)
|
|
|
|
typedTextCompletionIdx = typedTextCompletion.size() - 1;
|
|
|
|
else if (typedTextCompletion.size() > 0)
|
|
|
|
typedTextCompletionIdx = typedTextCompletion.size() - 1;
|
|
|
|
if (typedTextCompletionIdx >= 0) {
|
2003-05-31 15:40:40 -06:00
|
|
|
std::string::size_type pos = typedText.rfind('/', typedText.length());
|
|
|
|
if (pos != std::string::npos)
|
|
|
|
typedText = typedText.substr(0, pos + 1) + typedTextCompletion[typedTextCompletionIdx];
|
|
|
|
else
|
|
|
|
typedText = typedTextCompletion[typedTextCompletionIdx];
|
2003-05-31 04:55:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (c == '\033') // ESC
|
|
|
|
{
|
|
|
|
typedText = "";
|
|
|
|
textEnterMode = false;
|
|
|
|
typedTextCompletion.clear();
|
|
|
|
typedTextCompletionIdx = -1;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
else if (c == '\n' || c == '\r')
|
|
|
|
{
|
|
|
|
if (typedText != "")
|
|
|
|
{
|
|
|
|
Selection sel = sim->findObjectFromPath(typedText);
|
2003-05-31 04:55:44 -06:00
|
|
|
if (!sel.empty())
|
2002-11-07 22:08:34 -07:00
|
|
|
{
|
|
|
|
addToHistory();
|
2001-11-27 18:50:04 -07:00
|
|
|
sim->setSelection(sel);
|
2002-11-07 22:08:34 -07:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
typedText = "";
|
|
|
|
}
|
|
|
|
textEnterMode = false;
|
2003-05-31 04:55:44 -06:00
|
|
|
typedTextCompletion.clear();
|
|
|
|
typedTextCompletionIdx = -1;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-02-13 13:38:49 -07:00
|
|
|
char C = toupper(c);
|
|
|
|
switch (C)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\001': // Ctrl+A
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowAtmospheres);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\002': // Ctrl+B
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowBoundaries);
|
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\n':
|
|
|
|
case '\r':
|
|
|
|
textEnterMode = true;
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-10-12 17:00:00 -06:00
|
|
|
case '\b':
|
|
|
|
sim->setSelection(Selection());
|
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\014': // Ctrl+L
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowNightMaps);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2003-01-31 21:42:56 -07:00
|
|
|
case '\013': // Ctrl+K
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowMarkers);
|
2003-02-04 17:22:44 -07:00
|
|
|
if (renderer->getRenderFlags() & Renderer::ShowMarkers)
|
|
|
|
{
|
|
|
|
flash("Markers enabled");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
flash("Markers disabled");
|
2003-01-31 21:42:56 -07:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
|
|
|
break;
|
|
|
|
|
2002-02-18 01:23:57 -07:00
|
|
|
case '\005': // Ctrl+E
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowEclipseShadows);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2002-02-18 01:23:57 -07:00
|
|
|
break;
|
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
case '\007': // Ctrl+G
|
|
|
|
flash("Goto surface");
|
|
|
|
addToHistory();
|
|
|
|
//if (sim->getFrame().coordSys == astro::Universal)
|
|
|
|
sim->geosynchronousFollow();
|
|
|
|
sim->gotoSurface(5.0);
|
|
|
|
// sim->gotoSelection(0.0001, Vec3f(0, 1, 0), astro::ObserverLocal);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\006': // Ctrl+F
|
|
|
|
flash("Alt-azimuth mode");
|
|
|
|
addToHistory();
|
|
|
|
altAzimuthMode = !altAzimuthMode;
|
|
|
|
break;
|
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
case 127: // Delete
|
|
|
|
deleteView();
|
|
|
|
break;
|
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
case '\011': // TAB
|
|
|
|
activeView++;
|
2003-02-12 03:41:48 -07:00
|
|
|
if (activeView >= (int) views.size())
|
2003-02-11 09:43:37 -07:00
|
|
|
activeView = 0;
|
|
|
|
sim->setActiveObserver(views[activeView]->observer);
|
2003-03-11 03:00:25 -07:00
|
|
|
if (!showActiveViewFrame)
|
|
|
|
flashFrameStart = currentTime;
|
2003-02-11 09:43:37 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\020': // Ctrl+P
|
2003-06-02 04:27:43 -06:00
|
|
|
if (!sim->getSelection().empty())
|
|
|
|
{
|
|
|
|
Selection sel = sim->getSelection();
|
|
|
|
if (sim->getUniverse()->isMarked(sel, 1))
|
|
|
|
{
|
|
|
|
sim->getUniverse()->unmarkObject(sel, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sim->getUniverse()->markObject(sel,
|
|
|
|
10.0f,
|
|
|
|
Color(0.0f, 1.0f, 0.0f, 0.9f),
|
|
|
|
Marker::Diamond,
|
|
|
|
1);
|
|
|
|
}
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2003-02-11 09:57:16 -07:00
|
|
|
case '\025': // Ctrl+U
|
2003-02-18 14:11:18 -07:00
|
|
|
splitView(View::VerticalSplit);
|
2003-02-11 09:43:37 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '\022': // Ctrl+R
|
2003-02-18 14:11:18 -07:00
|
|
|
splitView(View::HorizontalSplit);
|
2003-02-11 09:43:37 -07:00
|
|
|
break;
|
|
|
|
|
2003-02-12 03:28:32 -07:00
|
|
|
case '\004': // Ctrl+D
|
|
|
|
singleView();
|
|
|
|
break;
|
|
|
|
|
2002-02-28 15:13:10 -07:00
|
|
|
case '\023': // Ctrl+S
|
2003-07-08 09:29:24 -06:00
|
|
|
renderer->setStarStyle((Renderer::StarStyle) (((int) renderer->getStarStyle() + 1) %
|
|
|
|
(int) Renderer::StarStyleCount));
|
|
|
|
switch (renderer->getStarStyle())
|
|
|
|
{
|
|
|
|
case Renderer::FuzzyPointStars:
|
|
|
|
flash("Star style: fuzzy points");
|
|
|
|
break;
|
|
|
|
case Renderer::PointStars:
|
|
|
|
flash("Star style: points");
|
|
|
|
break;
|
|
|
|
case Renderer::ScaledDiscStars:
|
|
|
|
flash("Star style: scaled discs");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2002-02-28 15:13:10 -07:00
|
|
|
break;
|
|
|
|
|
2002-09-22 08:46:50 -06:00
|
|
|
case '\024': // Ctrl+T
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowCometTails);
|
|
|
|
if (renderer->getRenderFlags() & Renderer::ShowCometTails)
|
|
|
|
{
|
|
|
|
flash("Comet tails enabled");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
flash("Comet tails disabled");
|
|
|
|
notifyWatchers(RenderFlagsChanged);
|
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\026': // Ctrl+V
|
2003-02-21 01:04:56 -07:00
|
|
|
{
|
|
|
|
GLContext* context = renderer->getGLContext();
|
|
|
|
GLContext::GLRenderPath path = context->getRenderPath();
|
|
|
|
GLContext::GLRenderPath newPath = context->nextRenderPath();
|
|
|
|
|
|
|
|
if (newPath != path)
|
|
|
|
{
|
|
|
|
switch (newPath)
|
|
|
|
{
|
|
|
|
case GLContext::GLPath_Basic:
|
|
|
|
flash("Render path: Basic");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_Multitexture:
|
|
|
|
flash("Render path: Multitexture");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_NvCombiner:
|
|
|
|
flash("Render path: NVIDIA combiners");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_DOT3_ARBVP:
|
|
|
|
flash("Render path: OpenGL vertex program");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_NvCombiner_NvVP:
|
|
|
|
flash("Render path: NVIDIA vertex program and combiners");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_NvCombiner_ARBVP:
|
|
|
|
flash("Render path: OpenGL vertex program/NVIDIA combiners");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_ARBFP_ARBVP:
|
|
|
|
flash("Render path: OpenGL 1.5 vertex/fragment program");
|
|
|
|
break;
|
|
|
|
case GLContext::GLPath_NV30:
|
|
|
|
flash("Render path: NVIDIA GeForce FX");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
context->setRenderPath(newPath);
|
|
|
|
notifyWatchers(RenderFlagsChanged);
|
|
|
|
}
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-03-14 14:48:51 -07:00
|
|
|
case '\027': // Ctrl+W
|
|
|
|
wireframe = !wireframe;
|
|
|
|
renderer->setRenderMode(wireframe ? GL_LINE : GL_FILL);
|
|
|
|
break;
|
|
|
|
|
2002-01-25 02:37:54 -07:00
|
|
|
case '\030': // Ctrl+X
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowSmoothLines);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2002-01-25 02:37:54 -07:00
|
|
|
break;
|
|
|
|
|
2002-06-22 09:18:47 -06:00
|
|
|
case '\031': // Ctrl+Y
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowAutoMag);
|
2002-09-22 03:24:45 -06:00
|
|
|
if (renderer->getRenderFlags() & Renderer::ShowAutoMag)
|
2002-09-22 08:46:50 -06:00
|
|
|
{
|
2002-09-22 03:24:45 -06:00
|
|
|
flash("Auto-magnitude enabled");
|
2002-09-22 08:46:50 -06:00
|
|
|
setFaintestAutoMag();
|
|
|
|
}
|
2002-09-22 03:24:45 -06:00
|
|
|
else
|
|
|
|
flash("Auto-magnitude disabled");
|
2002-06-22 09:18:47 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\033': // Escape
|
|
|
|
cancelScript();
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
if (textEnterMode == true)
|
|
|
|
{
|
|
|
|
textEnterMode = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-02-11 09:43:37 -07:00
|
|
|
if (sim->getObserverMode() == Observer::Travelling)
|
|
|
|
sim->setObserverMode(Observer::Free);
|
2002-01-04 06:32:19 -07:00
|
|
|
else
|
|
|
|
sim->setFrame(astro::Universal, Selection());
|
2002-01-10 17:04:14 -07:00
|
|
|
if (!sim->getTrackedObject().empty())
|
|
|
|
sim->setTrackedObject(Selection());
|
2002-01-04 06:32:19 -07:00
|
|
|
}
|
2002-09-22 03:24:45 -06:00
|
|
|
flash("Cancel");
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case ' ':
|
|
|
|
if (paused)
|
|
|
|
{
|
|
|
|
sim->setTimeScale(timeScale);
|
|
|
|
// CheckMenuItem(menuBar, ID_TIME_FREEZE, MF_UNCHECKED);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
timeScale = sim->getTimeScale();
|
|
|
|
sim->setTimeScale(0.0);
|
|
|
|
// CheckMenuItem(menuBar, ID_TIME_FREEZE, MF_CHECKED);
|
|
|
|
}
|
|
|
|
paused = !paused;
|
2002-09-22 03:24:45 -06:00
|
|
|
if (paused)
|
|
|
|
flash("Pause");
|
|
|
|
else
|
|
|
|
flash("Resume");
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '!':
|
|
|
|
if (editMode)
|
|
|
|
showSelectionInfo(sim->getSelection());
|
2002-10-12 17:00:00 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
double t = (double) time(NULL) / 86400.0 +
|
|
|
|
(double) astro::Date(1970, 1, 1);
|
|
|
|
sim->setTime(t);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2003-06-18 12:36:37 -06:00
|
|
|
case '&':
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::LocationLabels);
|
|
|
|
notifyWatchers(LabelFlagsChanged);
|
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '*':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2003-01-01 16:54:00 -07:00
|
|
|
sim->reverseObserverOrientation();
|
2003-01-26 15:13:15 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '?':
|
|
|
|
addToHistory();
|
|
|
|
if (!sim->getSelection().empty())
|
|
|
|
{
|
|
|
|
Vec3d v = sim->getSelection().getPosition(sim->getTime()) -
|
|
|
|
sim->getObserver().getPosition();
|
|
|
|
int hours, mins;
|
|
|
|
float secs;
|
|
|
|
char buf[128];
|
|
|
|
if (astro::microLightYearsToKilometers(v.length()) >=
|
|
|
|
86400.0 * astro::speedOfLight)
|
|
|
|
{
|
|
|
|
// Light travel time in years, if >= 1day
|
|
|
|
sprintf(buf,"Light travel time: %.4f yr ",
|
|
|
|
v.length() * 1.0e-6);
|
|
|
|
flash(buf, 2.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If Light travel delay < 1 day, display in [ hr : min : sec ]
|
|
|
|
getLightTravelDelay(v.length(), hours, mins, secs);
|
|
|
|
if (hours == 0)
|
|
|
|
sprintf(buf,"Light travel time: %d min %.1f s",
|
|
|
|
mins, secs);
|
|
|
|
else
|
|
|
|
sprintf(buf,"Light travel time: %d h %d min %.1f s"
|
|
|
|
,hours, mins, secs);
|
|
|
|
flash(buf, 2.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
addToHistory();
|
2003-03-08 17:32:11 -07:00
|
|
|
|
2003-06-25 11:40:24 -06:00
|
|
|
if (sim->getSelection().body() &&
|
2003-05-01 10:36:09 -06:00
|
|
|
(sim->getTargetSpeed() < 0.99 *
|
|
|
|
astro::kilometersToMicroLightYears(astro::speedOfLight)))
|
2003-01-26 15:13:15 -07:00
|
|
|
{
|
2003-05-01 10:36:09 -06:00
|
|
|
Vec3d v = sim->getSelection().getPosition(sim->getTime()) -
|
|
|
|
sim->getObserver().getPosition();
|
2003-03-08 17:32:11 -07:00
|
|
|
lightTravelFlag = !lightTravelFlag;
|
|
|
|
if (lightTravelFlag)
|
2003-05-01 10:36:09 -06:00
|
|
|
{
|
|
|
|
flash("Light travel delay included",2.0);
|
|
|
|
setLightTravelDelay(v.length());
|
|
|
|
}
|
2003-01-26 15:13:15 -07:00
|
|
|
else
|
2003-05-01 10:36:09 -06:00
|
|
|
{
|
|
|
|
flash("Light travel delay switched off",2.0);
|
|
|
|
setLightTravelDelay(-v.length());
|
|
|
|
}
|
2003-01-26 15:13:15 -07:00
|
|
|
}
|
2003-03-08 17:32:11 -07:00
|
|
|
else
|
2003-05-01 10:36:09 -06:00
|
|
|
{
|
|
|
|
flash("Light travel delay ignored");
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ',':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2003-02-12 03:28:32 -07:00
|
|
|
if (observer->getFOV() > MinimumFOV)
|
2002-09-22 08:46:50 -06:00
|
|
|
{
|
2003-02-12 03:28:32 -07:00
|
|
|
observer->setFOV(observer->getFOV() / 1.05f);
|
2003-06-03 14:11:09 -06:00
|
|
|
setZoomFromFOV();
|
2002-09-22 15:45:23 -06:00
|
|
|
if((renderer->getRenderFlags() & Renderer::ShowAutoMag))
|
|
|
|
{
|
2002-09-22 08:46:50 -06:00
|
|
|
setFaintestAutoMag();
|
2002-09-22 15:45:23 -06:00
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Magnitude limit: %.2f", sim->getFaintestVisible());
|
|
|
|
flash(buf);
|
|
|
|
}
|
2002-09-22 08:46:50 -06:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '.':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2003-02-12 03:28:32 -07:00
|
|
|
if (observer->getFOV() < MaximumFOV)
|
2002-09-22 08:46:50 -06:00
|
|
|
{
|
2003-02-12 03:28:32 -07:00
|
|
|
observer->setFOV(observer->getFOV() * 1.05f);
|
2003-06-03 14:11:09 -06:00
|
|
|
setZoomFromFOV();
|
2002-09-22 08:46:50 -06:00
|
|
|
if((renderer->getRenderFlags() & Renderer::ShowAutoMag) != 0)
|
2002-09-22 15:45:23 -06:00
|
|
|
{
|
2003-06-03 14:11:09 -06:00
|
|
|
setFaintestAutoMag();
|
2002-09-22 15:45:23 -06:00
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Magnitude limit: %.2f", sim->getFaintestVisible());
|
|
|
|
flash(buf);
|
|
|
|
}
|
2002-09-22 08:46:50 -06:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2003-06-08 21:58:41 -06:00
|
|
|
case '+':
|
|
|
|
addToHistory();
|
|
|
|
if (observer->getDisplayedSurface() != "")
|
|
|
|
{
|
|
|
|
observer->setDisplayedSurface("");
|
|
|
|
flash("Using normal surface textures.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
observer->setDisplayedSurface("limit of knowledge");
|
|
|
|
flash("Using limit of knowledge surface textures.");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '/':
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowDiagrams);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '0':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->selectPlanet(-1);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->selectPlanet(c - '1');
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case ';':
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowCelestialSphere);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2002-01-04 06:32:19 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '=':
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::ConstellationLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'B':
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::StarLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'C':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->centerSelection();
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'D':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
|
|
|
if (runningScript == NULL && demoScript != NULL)
|
2002-01-04 06:32:19 -07:00
|
|
|
runningScript = new Execution(*demoScript, *execEnv);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'E':
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::GalaxyLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2002-01-04 06:32:19 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'F':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-09-22 03:24:45 -06:00
|
|
|
flash("Follow");
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->follow();
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'G':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-03-27 18:03:23 -07:00
|
|
|
if (sim->getFrame().coordSys == astro::Universal)
|
|
|
|
sim->follow();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->gotoSelection(5.0, Vec3f(0, 1, 0), astro::ObserverLocal);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'H':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2003-02-11 09:43:37 -07:00
|
|
|
sim->setSelection(sim->getUniverse()->getStarCatalog()->find(0));
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'I':
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowCloudMaps);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'J':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->setTimeScale(-sim->getTimeScale());
|
2002-09-22 03:24:45 -06:00
|
|
|
if (sim->getTimeScale() > 0)
|
|
|
|
flash("Time: Forward");
|
|
|
|
else
|
|
|
|
flash("Time: Backward");
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'K':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-09-22 03:24:45 -06:00
|
|
|
{
|
|
|
|
sim->setTimeScale(sim->getTimeScale() / fIncrementFactor);
|
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Time rate: %.1f", sim->getTimeScale());
|
|
|
|
flash(buf);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'L':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-05-02 01:58:50 -06:00
|
|
|
if (sim->getTimeScale() < MaximumTimeRate)
|
2002-09-22 03:24:45 -06:00
|
|
|
{
|
2002-05-02 01:58:50 -06:00
|
|
|
sim->setTimeScale(sim->getTimeScale() * fIncrementFactor);
|
2002-09-22 03:24:45 -06:00
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Time rate: %.1f", sim->getTimeScale());
|
|
|
|
flash(buf);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'M':
|
2002-03-14 14:48:51 -07:00
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::MoonLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'N':
|
2002-03-14 14:48:51 -07:00
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::SpacecraftLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'O':
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowOrbits);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-03-14 14:48:51 -07:00
|
|
|
case 'P':
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::PlanetLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2002-03-14 14:48:51 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'Q':
|
|
|
|
sim->setTargetSpeed(-sim->getTargetSpeed());
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-02-13 13:38:49 -07:00
|
|
|
case 'R':
|
2002-02-18 01:23:57 -07:00
|
|
|
if (c == 'r') // Skip rangechecking as setResolution does it already
|
|
|
|
renderer->setResolution(renderer->getResolution() - 1);
|
2002-02-13 13:38:49 -07:00
|
|
|
else
|
2002-02-18 01:23:57 -07:00
|
|
|
renderer->setResolution(renderer->getResolution() + 1);
|
2002-09-25 11:40:40 -06:00
|
|
|
switch (renderer->getResolution())
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
flash("Low res textures");
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
flash("Medium res textures");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
flash("High res textures");
|
|
|
|
break;
|
|
|
|
}
|
2002-02-13 13:38:49 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'S':
|
|
|
|
sim->setTargetSpeed(0);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'T':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-10 17:04:14 -07:00
|
|
|
if (sim->getTrackedObject().empty())
|
|
|
|
sim->setTrackedObject(sim->getSelection());
|
|
|
|
else
|
|
|
|
sim->setTrackedObject(Selection());
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'U':
|
|
|
|
renderer->setRenderFlags(renderer->getRenderFlags() ^ Renderer::ShowGalaxies);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(RenderFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'V':
|
2002-03-29 17:36:52 -07:00
|
|
|
setHudDetail((getHudDetail() + 1) % 3);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'W':
|
2003-07-04 18:23:31 -06:00
|
|
|
if (c == 'w')
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::AsteroidLabels);
|
|
|
|
else
|
|
|
|
renderer->setLabelMode(renderer->getLabelMode() ^ Renderer::CometLabels);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(LabelFlagsChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case 'X':
|
|
|
|
sim->setTargetSpeed(sim->getTargetSpeed());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'Y':
|
2002-09-22 03:24:45 -06:00
|
|
|
flash("Sync Orbit");
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->geosynchronousFollow();
|
|
|
|
break;
|
|
|
|
|
2002-03-14 14:48:51 -07:00
|
|
|
case ':':
|
2002-09-22 03:24:45 -06:00
|
|
|
flash("Lock");
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->phaseLock();
|
|
|
|
break;
|
|
|
|
|
2002-03-18 19:55:01 -07:00
|
|
|
case '"':
|
2002-09-22 03:24:45 -06:00
|
|
|
flash("Chase");
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-03-18 19:55:01 -07:00
|
|
|
sim->chase();
|
|
|
|
break;
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
case '[':
|
2003-02-11 09:43:37 -07:00
|
|
|
if ((renderer->getRenderFlags() & Renderer::ShowAutoMag) == 0)
|
|
|
|
{
|
2002-12-11 13:33:23 -07:00
|
|
|
if (sim->getFaintestVisible() > 1.0f)
|
2003-02-11 09:43:37 -07:00
|
|
|
{
|
|
|
|
setFaintest(sim->getFaintestVisible() - 0.2f);
|
|
|
|
notifyWatchers(FaintestChanged);
|
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Magnitude limit: %.2f",sim->getFaintestVisible());
|
|
|
|
flash(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (renderer->getFaintestAM45deg() > 6.0f)
|
|
|
|
{
|
|
|
|
renderer->setFaintestAM45deg(renderer->getFaintestAM45deg() - 0.1f);
|
|
|
|
setFaintestAutoMag();
|
2002-09-22 03:24:45 -06:00
|
|
|
char buf[128];
|
2003-02-11 09:43:37 -07:00
|
|
|
sprintf(buf, "Auto magnitude limit at 45 degrees: %.2f",renderer->getFaintestAM45deg());
|
2002-09-22 03:24:45 -06:00
|
|
|
flash(buf);
|
2002-04-02 04:35:27 -07:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '\\':
|
2002-11-07 22:08:34 -07:00
|
|
|
addToHistory();
|
2002-01-04 06:32:19 -07:00
|
|
|
sim->setTimeScale(1.0);
|
|
|
|
break;
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
case ']':
|
2003-02-11 09:43:37 -07:00
|
|
|
if((renderer->getRenderFlags() & Renderer::ShowAutoMag) == 0)
|
2002-04-02 04:35:27 -07:00
|
|
|
{
|
2002-12-11 13:33:23 -07:00
|
|
|
if (sim->getFaintestVisible() < 15.0f)
|
|
|
|
{
|
|
|
|
setFaintest(sim->getFaintestVisible() + 0.2f);
|
2003-02-11 09:43:37 -07:00
|
|
|
notifyWatchers(FaintestChanged);
|
|
|
|
char buf[128];
|
2002-12-11 13:33:23 -07:00
|
|
|
sprintf(buf, "Magnitude limit: %.2f",sim->getFaintestVisible());
|
2003-02-11 09:43:37 -07:00
|
|
|
flash(buf);
|
|
|
|
}
|
2002-09-22 08:46:50 -06:00
|
|
|
}
|
2002-12-11 13:33:23 -07:00
|
|
|
else if (renderer->getFaintestAM45deg() < 12.0f)
|
|
|
|
{
|
|
|
|
renderer->setFaintestAM45deg(renderer->getFaintestAM45deg() + 0.1f);
|
|
|
|
setFaintestAutoMag();
|
|
|
|
char buf[128];
|
|
|
|
sprintf(buf, "Auto magnitude limit at 45 degrees: %.2f",renderer->getFaintestAM45deg());
|
|
|
|
flash(buf);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '`':
|
|
|
|
showFPSCounter = !showFPSCounter;
|
|
|
|
break;
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
case '{':
|
|
|
|
if (renderer->getAmbientLightLevel() > 0.05f)
|
|
|
|
renderer->setAmbientLightLevel(renderer->getAmbientLightLevel() - 0.05f);
|
|
|
|
else
|
|
|
|
renderer->setAmbientLightLevel(0.0f);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(AmbientLightChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '}':
|
|
|
|
if (renderer->getAmbientLightLevel() < 0.95f)
|
|
|
|
renderer->setAmbientLightLevel(renderer->getAmbientLightLevel() + 0.05f);
|
|
|
|
else
|
|
|
|
renderer->setAmbientLightLevel(1.0f);
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(AmbientLightChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
case '~':
|
|
|
|
editMode = !editMode;
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
|
2003-01-26 15:13:15 -07:00
|
|
|
void CelestiaCore::getLightTravelDelay(double distance, int& hours, int& mins,
|
|
|
|
float& secs)
|
|
|
|
{
|
|
|
|
// light travel time in hours
|
|
|
|
double lt = astro::microLightYearsToKilometers(distance)/
|
|
|
|
(3600.0 * astro::speedOfLight);
|
|
|
|
hours = (int) lt;
|
|
|
|
double mm = (lt - hours) * 60;
|
|
|
|
mins = (int) mm;
|
|
|
|
secs = (float) ((mm - mins) * 60);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::setLightTravelDelay(double distance)
|
|
|
|
{
|
|
|
|
// light travel time in days
|
|
|
|
double lt = astro::microLightYearsToKilometers(distance)/
|
|
|
|
(86400.0 * astro::speedOfLight);
|
|
|
|
sim->setTime(sim->getTime() - lt);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
void CelestiaCore::start(double t)
|
|
|
|
{
|
|
|
|
if (initScript != NULL)
|
|
|
|
runningScript = new Execution(*initScript, *execEnv);
|
|
|
|
|
|
|
|
// Set the simulation starting time to the current system time
|
|
|
|
sim->setTime(t);
|
|
|
|
sim->update(0.0);
|
2002-11-07 22:08:34 -07:00
|
|
|
|
|
|
|
if (startURL != "")
|
|
|
|
goToUrl(startURL);
|
|
|
|
}
|
|
|
|
|
2002-12-15 04:46:16 -07:00
|
|
|
void CelestiaCore::setStartURL(std::string url)
|
|
|
|
{
|
|
|
|
if (!url.substr(0,4).compare("cel:"))
|
|
|
|
{
|
|
|
|
startURL = url;
|
|
|
|
free(initScript);
|
|
|
|
initScript = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-02-18 14:11:18 -07:00
|
|
|
free(initScript);
|
2002-12-15 04:46:16 -07:00
|
|
|
ifstream scriptfile(url.c_str());
|
|
|
|
CommandParser parser(scriptfile);
|
|
|
|
initScript = parser.parse();
|
|
|
|
if (initScript == NULL)
|
|
|
|
{
|
|
|
|
const vector<string>* errors = parser.getErrors();
|
|
|
|
for_each(errors->begin(), errors->end(), printlineFunc<string>(cout));
|
|
|
|
}
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-11 17:11:19 -07:00
|
|
|
void CelestiaCore::tick()
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2001-12-11 17:11:19 -07:00
|
|
|
double lastTime = sysTime;
|
|
|
|
sysTime = timer->getTime();
|
|
|
|
|
|
|
|
// The time step is normally driven by the system clock; however, when
|
|
|
|
// recording a movie, we fix the time step the frame rate of the movie.
|
|
|
|
double dt = 0.0;
|
|
|
|
if (movieCapture != NULL && recording)
|
|
|
|
{
|
|
|
|
dt = 1.0 / movieCapture->getFrameRate();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dt = sysTime - lastTime;
|
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
currentTime += dt;
|
|
|
|
|
2003-04-13 00:10:45 -06:00
|
|
|
#ifdef CELX
|
2003-04-12 23:58:34 -06:00
|
|
|
if (celxScript != NULL && scriptAwakenTime != 0.0)
|
|
|
|
{
|
|
|
|
if (currentTime >= scriptAwakenTime)
|
|
|
|
resumeScript();
|
|
|
|
}
|
2003-04-13 00:10:45 -06:00
|
|
|
#endif // CELX
|
2003-04-12 23:58:34 -06:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
// Mouse wheel zoom
|
|
|
|
if (zoomMotion != 0.0f)
|
|
|
|
{
|
|
|
|
double span = 0.1;
|
|
|
|
double fraction;
|
|
|
|
|
|
|
|
if (currentTime - zoomTime >= span)
|
2001-12-11 17:11:19 -07:00
|
|
|
fraction = (zoomTime + span) - (currentTime - dt);
|
2001-11-27 18:50:04 -07:00
|
|
|
else
|
|
|
|
fraction = dt / span;
|
|
|
|
|
|
|
|
// sim->changeOrbitDistance(zoomMotion * (float) fraction);
|
|
|
|
if (currentTime - zoomTime >= span)
|
|
|
|
zoomMotion = 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mouse wheel dolly
|
|
|
|
if (dollyMotion != 0.0f)
|
|
|
|
{
|
|
|
|
double span = 0.1;
|
|
|
|
double fraction;
|
|
|
|
|
|
|
|
if (currentTime - dollyTime >= span)
|
2001-12-11 17:11:19 -07:00
|
|
|
fraction = (dollyTime + span) - (currentTime - dt);
|
2001-11-27 18:50:04 -07:00
|
|
|
else
|
|
|
|
fraction = dt / span;
|
|
|
|
|
|
|
|
sim->changeOrbitDistance(dollyMotion * (float) fraction);
|
|
|
|
if (currentTime - dollyTime >= span)
|
|
|
|
dollyMotion = 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keyboard dolly
|
|
|
|
if (keysPressed[Key_Home])
|
|
|
|
sim->changeOrbitDistance(-dt * 2);
|
|
|
|
if (keysPressed[Key_End])
|
|
|
|
sim->changeOrbitDistance(dt * 2);
|
|
|
|
|
|
|
|
// Keyboard rotate
|
|
|
|
Vec3f av = sim->getObserver().getAngularVelocity();
|
|
|
|
|
|
|
|
av = av * (float) exp(-dt * RotationDecay);
|
|
|
|
|
2003-02-12 03:28:32 -07:00
|
|
|
float fov = sim->getActiveObserver()->getFOV() / stdFOV;
|
2003-07-18 23:46:57 -06:00
|
|
|
FrameOfReference frame = sim->getFrame();
|
2002-05-08 15:16:52 -06:00
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
if (!altAzimuthMode)
|
|
|
|
{
|
|
|
|
if (keysPressed[Key_Left])
|
|
|
|
av += Vec3f(0, 0, dt * -KeyRotationAccel);
|
|
|
|
if (keysPressed[Key_Right])
|
|
|
|
av += Vec3f(0, 0, dt * KeyRotationAccel);
|
|
|
|
if (keysPressed[Key_Down])
|
|
|
|
av += Vec3f(dt * fov * -KeyRotationAccel, 0, 0);
|
|
|
|
if (keysPressed[Key_Up])
|
|
|
|
av += Vec3f(dt * fov * KeyRotationAccel, 0, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!frame.refObject.empty())
|
|
|
|
{
|
|
|
|
Quatf orientation = sim->getObserver().getOrientation();
|
|
|
|
Vec3d upd = sim->getObserver().getPosition() -
|
|
|
|
frame.refObject.getPosition(sim->getTime());
|
|
|
|
upd.normalize();
|
|
|
|
|
|
|
|
Vec3f up((float) upd.x, (float) upd.y, (float) upd.z);
|
|
|
|
|
|
|
|
Vec3f v = up * (float) (KeyRotationAccel * dt);
|
|
|
|
v = v * (~orientation).toMatrix3();
|
|
|
|
|
|
|
|
if (keysPressed[Key_Left])
|
|
|
|
av -= v;
|
|
|
|
if (keysPressed[Key_Right])
|
|
|
|
av += v;
|
|
|
|
if (keysPressed[Key_Down])
|
|
|
|
av += Vec3f(dt * fov * -KeyRotationAccel, 0, 0);
|
|
|
|
if (keysPressed[Key_Up])
|
|
|
|
av += Vec3f(dt * fov * KeyRotationAccel, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
if (keysPressed[Key_NumPad4])
|
2002-05-15 13:03:59 -06:00
|
|
|
av += Vec3f(0, dt * fov * -KeyRotationAccel, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (keysPressed[Key_NumPad6])
|
2002-05-15 13:03:59 -06:00
|
|
|
av += Vec3f(0, dt * fov * KeyRotationAccel, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (keysPressed[Key_NumPad2])
|
2002-05-15 13:03:59 -06:00
|
|
|
av += Vec3f(dt * fov * -KeyRotationAccel, 0, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (keysPressed[Key_NumPad8])
|
2002-05-15 13:03:59 -06:00
|
|
|
av += Vec3f(dt * fov * KeyRotationAccel, 0, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (keysPressed[Key_NumPad7] || joyButtonsPressed[JoyButton7])
|
2002-05-15 13:03:59 -06:00
|
|
|
av += Vec3f(0, 0, dt * -KeyRotationAccel);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (keysPressed[Key_NumPad9] || joyButtonsPressed[JoyButton8])
|
2002-05-15 13:03:59 -06:00
|
|
|
av += Vec3f(0, 0, dt * KeyRotationAccel);
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2001-12-03 13:18:34 -07:00
|
|
|
//Use Boolean to indicate if sim->setTargetSpeed() is called
|
|
|
|
bool bSetTargetSpeed = false;
|
2001-11-27 18:50:04 -07:00
|
|
|
if (joystickRotation != Vec3f(0.0f, 0.0f, 0.0f))
|
|
|
|
{
|
2001-12-03 13:18:34 -07:00
|
|
|
bSetTargetSpeed = true;
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
av += (float) (dt * KeyRotationAccel) * joystickRotation;
|
|
|
|
sim->setTargetSpeed(sim->getTargetSpeed());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keysPressed[Key_NumPad5])
|
|
|
|
av = av * (float) exp(-dt * RotationBraking);
|
|
|
|
|
|
|
|
sim->getObserver().setAngularVelocity(av);
|
|
|
|
|
|
|
|
if (keysPressed['A'] || joyButtonsPressed[JoyButton2])
|
|
|
|
{
|
2001-12-03 13:18:34 -07:00
|
|
|
bSetTargetSpeed = true;
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (sim->getTargetSpeed() == 0.0f)
|
2002-03-14 14:48:51 -07:00
|
|
|
sim->setTargetSpeed(astro::kilometersToMicroLightYears(0.1f));
|
2001-11-27 18:50:04 -07:00
|
|
|
else
|
|
|
|
sim->setTargetSpeed(sim->getTargetSpeed() * (float) exp(dt * 3));
|
|
|
|
}
|
|
|
|
if (keysPressed['Z'] || joyButtonsPressed[JoyButton1])
|
|
|
|
{
|
2001-12-03 13:18:34 -07:00
|
|
|
bSetTargetSpeed = true;
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
sim->setTargetSpeed(sim->getTargetSpeed() / (float) exp(dt * 3));
|
|
|
|
}
|
2002-01-04 06:32:19 -07:00
|
|
|
if (!bSetTargetSpeed && av.length() > 0.0f)
|
2001-12-03 13:18:34 -07:00
|
|
|
{
|
|
|
|
//Force observer velocity vector to align with observer direction if an observer
|
|
|
|
//angular velocity still exists.
|
|
|
|
sim->setTargetSpeed(sim->getTargetSpeed());
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2003-07-18 23:46:57 -06:00
|
|
|
if (!frame.refObject.empty())
|
|
|
|
{
|
|
|
|
Quatf q(1.0f);
|
|
|
|
|
|
|
|
if (shiftKeysPressed[Key_Left])
|
|
|
|
q = q * Quatf::yrotation(dt * -KeyRotationAccel);
|
|
|
|
if (shiftKeysPressed[Key_Right])
|
|
|
|
q = q * Quatf::yrotation(dt * KeyRotationAccel);
|
|
|
|
if (shiftKeysPressed[Key_Up])
|
|
|
|
q = q * Quatf::xrotation(dt * -KeyRotationAccel);
|
|
|
|
if (shiftKeysPressed[Key_Down])
|
|
|
|
q = q * Quatf::xrotation(dt * KeyRotationAccel);
|
|
|
|
sim->orbit(q);
|
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
// If there's a script running, tick it
|
|
|
|
if (runningScript != NULL)
|
|
|
|
{
|
|
|
|
bool finished = runningScript->tick(dt);
|
|
|
|
if (finished)
|
|
|
|
cancelScript();
|
|
|
|
}
|
|
|
|
|
|
|
|
sim->update(dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::draw()
|
|
|
|
{
|
2003-02-11 09:43:37 -07:00
|
|
|
if (views.size() == 1)
|
|
|
|
{
|
|
|
|
// I'm not certain that a special case for one view is required; but,
|
|
|
|
// it's possible that there exists some broken hardware out there
|
|
|
|
// that has to fall back to software rendering if the scissor test
|
|
|
|
// is enable. To keep performance on this hypothetical hardware
|
|
|
|
// reasonable in the typical single view case, we'll use this
|
|
|
|
// scissorless special case. I'm only paranoid because I've been
|
|
|
|
// burned by crap hardware so many times. cjl
|
2003-02-12 03:28:32 -07:00
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
renderer->resize(width, height);
|
2003-02-11 09:43:37 -07:00
|
|
|
sim->render(*renderer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
for (vector<View*>::iterator iter = views.begin();
|
|
|
|
iter != views.end(); iter++)
|
|
|
|
{
|
|
|
|
View* view = *iter;
|
|
|
|
|
|
|
|
glScissor((GLint) (view->x * width),
|
|
|
|
(GLint) (view->y * height),
|
|
|
|
(GLsizei) (view->width * width),
|
|
|
|
(GLsizei) (view->height * height));
|
|
|
|
glViewport((GLint) (view->x * width),
|
|
|
|
(GLint) (view->y * height),
|
|
|
|
(GLsizei) (view->width * width),
|
|
|
|
(GLsizei) (view->height * height));
|
2003-02-12 03:41:48 -07:00
|
|
|
renderer->resize((int) (view->width * width),
|
|
|
|
(int) (view->height * height));
|
2003-02-11 09:43:37 -07:00
|
|
|
sim->render(*renderer, *view->observer);
|
|
|
|
}
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
renderOverlay();
|
|
|
|
|
2001-12-10 21:20:05 -07:00
|
|
|
if (movieCapture != NULL && recording)
|
|
|
|
movieCapture->captureFrame();
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
// Frame rate counter
|
|
|
|
nFrames++;
|
|
|
|
if (nFrames == 100)
|
|
|
|
{
|
2001-12-11 17:11:19 -07:00
|
|
|
fps = (double) nFrames / (sysTime - fpsCounterStartTime);
|
2001-11-27 18:50:04 -07:00
|
|
|
nFrames = 0;
|
2001-12-11 17:11:19 -07:00
|
|
|
fpsCounterStartTime = sysTime;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
2001-12-11 17:11:19 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
#if 0
|
|
|
|
GLenum err = glGetError();
|
|
|
|
if (err != GL_NO_ERROR)
|
|
|
|
{
|
|
|
|
cout << "GL error: " << gluErrorString(err) << '\n';
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::resize(GLsizei w, GLsizei h)
|
|
|
|
{
|
|
|
|
if (h == 0)
|
|
|
|
h = 1;
|
|
|
|
|
|
|
|
glViewport(0, 0, w, h);
|
|
|
|
if (renderer != NULL)
|
|
|
|
renderer->resize(w, h);
|
|
|
|
if (overlay != NULL)
|
|
|
|
overlay->setWindowSize(w, h);
|
|
|
|
width = w;
|
|
|
|
height = h;
|
2003-06-03 14:11:09 -06:00
|
|
|
|
|
|
|
setFOVFromZoom();
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
void CelestiaCore::splitView(View::Type type)
|
2003-02-11 09:43:37 -07:00
|
|
|
{
|
2003-02-18 14:11:18 -07:00
|
|
|
bool vertical = ( type == View::VerticalSplit );
|
2003-02-11 09:43:37 -07:00
|
|
|
Observer* o = sim->addObserver();
|
2003-03-29 17:21:33 -07:00
|
|
|
bool tooSmall = false;
|
|
|
|
|
|
|
|
switch (type) // If active view is too small, don't split it.
|
|
|
|
{
|
|
|
|
case View::HorizontalSplit:
|
|
|
|
if (views[activeView]->height < 0.2f) tooSmall = true;
|
|
|
|
break;
|
|
|
|
case View::VerticalSplit:
|
|
|
|
if (views[activeView]->width < 0.2f) tooSmall = true;
|
|
|
|
break;
|
|
|
|
case View::ViewWindow:
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tooSmall)
|
|
|
|
{
|
|
|
|
flash("View too small to be split");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
flash("Added view");
|
2003-02-11 09:43:37 -07:00
|
|
|
|
|
|
|
// Make the new observer a copy of the old one
|
|
|
|
// TODO: This works, but an assignment operator for Observer
|
|
|
|
// should be defined.
|
|
|
|
*o = *(sim->getActiveObserver());
|
|
|
|
|
|
|
|
float w = views[activeView]->width * (vertical ? 0.5f : 1.0f);
|
|
|
|
float h = views[activeView]->height * (vertical ? 1.0f : 0.5f);
|
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
View* split = new View(type,
|
|
|
|
0,
|
|
|
|
views[activeView]->x,
|
|
|
|
views[activeView]->y,
|
|
|
|
views[activeView]->width,
|
|
|
|
views[activeView]->height);
|
|
|
|
split->parent = views[activeView]->parent;
|
|
|
|
if (views[activeView]->parent != 0)
|
|
|
|
{
|
|
|
|
if (views[activeView]->parent->child1 == views[activeView])
|
|
|
|
views[activeView]->parent->child1 = split;
|
|
|
|
else
|
|
|
|
views[activeView]->parent->child2 = split;
|
|
|
|
}
|
|
|
|
split->child1 = views[activeView];
|
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
views[activeView]->width = w;
|
|
|
|
views[activeView]->height = h;
|
2003-02-18 14:11:18 -07:00
|
|
|
views[activeView]->parent = split;
|
2003-02-11 09:43:37 -07:00
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
View* view = new View(View::ViewWindow,
|
|
|
|
o,
|
2003-02-11 09:43:37 -07:00
|
|
|
views[activeView]->x + (vertical ? w : 0),
|
|
|
|
views[activeView]->y + (vertical ? 0 : h),
|
|
|
|
w, h);
|
2003-02-18 14:11:18 -07:00
|
|
|
split->child2 = view;
|
|
|
|
view->parent = split;
|
2003-06-03 14:11:09 -06:00
|
|
|
view->zoom = views[activeView]->zoom;
|
2003-02-18 14:11:18 -07:00
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
views.insert(views.end(), view);
|
2003-06-03 14:11:09 -06:00
|
|
|
|
|
|
|
setFOVFromZoom();
|
2003-02-12 03:28:32 -07:00
|
|
|
}
|
|
|
|
|
2003-06-03 14:11:09 -06:00
|
|
|
void CelestiaCore::setFOVFromZoom()
|
|
|
|
{
|
|
|
|
for (std::vector<View*>::iterator i = views.begin(); i < views.end(); i++)
|
|
|
|
if ((*i)->type == View::ViewWindow)
|
|
|
|
{
|
|
|
|
double fov = 2 * atan(height * (*i)->height / (screenDpi / 25.4) / 2. / distanceToScreen) / (*i)->zoom;
|
|
|
|
(*i)->observer->setFOV(fov);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::setZoomFromFOV()
|
|
|
|
{
|
|
|
|
for (std::vector<View*>::iterator i = views.begin(); i < views.end(); i++)
|
|
|
|
if ((*i)->type == View::ViewWindow)
|
|
|
|
{
|
|
|
|
(*i)->zoom = 2 * atan(height * (*i)->height / (screenDpi / 25.4) / 2. / distanceToScreen) / (*i)->observer->getFOV();
|
|
|
|
}
|
|
|
|
}
|
2003-02-12 03:28:32 -07:00
|
|
|
|
|
|
|
void CelestiaCore::singleView()
|
|
|
|
{
|
|
|
|
View* av = views[activeView];
|
|
|
|
|
2003-02-12 03:41:48 -07:00
|
|
|
for (unsigned int i = 0; i < views.size(); i++)
|
2003-02-12 03:28:32 -07:00
|
|
|
{
|
2003-02-12 03:41:48 -07:00
|
|
|
if ((int) i != activeView)
|
2003-02-12 03:28:32 -07:00
|
|
|
{
|
|
|
|
sim->removeObserver(views[i]->observer);
|
2003-02-18 14:11:18 -07:00
|
|
|
delete views[i]->observer;
|
2003-02-12 03:28:32 -07:00
|
|
|
delete views[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
av->x = 0.0f;
|
|
|
|
av->y = 0.0f;
|
|
|
|
av->width = 1.0f;
|
|
|
|
av->height = 1.0f;
|
2003-02-18 14:11:18 -07:00
|
|
|
av->parent = 0;
|
2003-02-11 09:43:37 -07:00
|
|
|
|
2003-02-12 03:28:32 -07:00
|
|
|
views.clear();
|
|
|
|
views.insert(views.end(), av);
|
|
|
|
activeView = 0;
|
2003-06-03 14:11:09 -06:00
|
|
|
setFOVFromZoom();
|
2003-02-11 09:43:37 -07:00
|
|
|
}
|
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
void CelestiaCore::deleteView()
|
|
|
|
{
|
|
|
|
View *v = views[activeView];
|
|
|
|
if (v->parent == 0) return;
|
|
|
|
|
|
|
|
for(std::vector<View*>::iterator i = views.begin(); i < views.end() ; i++)
|
|
|
|
{
|
|
|
|
if (*i == v)
|
|
|
|
{
|
|
|
|
views.erase(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int sign;
|
|
|
|
View *sibling;
|
|
|
|
if (v->parent->child1 == v)
|
|
|
|
{
|
|
|
|
sibling = v->parent->child2;
|
|
|
|
sign = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sibling = v->parent->child1;
|
|
|
|
sign = 1;
|
|
|
|
}
|
|
|
|
sibling->parent = v->parent->parent;
|
|
|
|
if (v->parent->parent != 0) {
|
|
|
|
if (v->parent->parent->child1 == v->parent)
|
|
|
|
v->parent->parent->child1 = sibling;
|
|
|
|
else
|
|
|
|
v->parent->parent->child2 = sibling;
|
|
|
|
}
|
|
|
|
|
|
|
|
v->walkTreeResize(sibling, sign);
|
|
|
|
|
|
|
|
sim->removeObserver(v->observer);
|
|
|
|
delete(v->observer);
|
|
|
|
activeView = 0;
|
|
|
|
sim->setActiveObserver(views[activeView]->observer);
|
|
|
|
|
|
|
|
delete(v->parent);
|
|
|
|
delete(v);
|
2003-03-08 17:32:11 -07:00
|
|
|
|
2003-03-11 03:00:25 -07:00
|
|
|
if (!showActiveViewFrame)
|
|
|
|
flashFrameStart = currentTime;
|
2003-06-03 14:11:09 -06:00
|
|
|
setFOVFromZoom();
|
2003-03-11 03:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CelestiaCore::getFramesVisible() const
|
|
|
|
{
|
|
|
|
return showViewFrames;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::setFramesVisible(bool visible)
|
|
|
|
{
|
|
|
|
showViewFrames = visible;
|
2003-02-18 14:11:18 -07:00
|
|
|
}
|
|
|
|
|
2003-03-19 15:57:06 -07:00
|
|
|
bool CelestiaCore::getActiveFrameVisible() const
|
|
|
|
{
|
|
|
|
return showActiveViewFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::setActiveFrameVisible(bool visible)
|
|
|
|
{
|
|
|
|
showActiveViewFrame = visible;
|
|
|
|
}
|
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
void CelestiaCore::setContextMenuCallback(ContextMenuFunc callback)
|
|
|
|
{
|
|
|
|
contextMenuCallback = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Renderer* CelestiaCore::getRenderer() const
|
|
|
|
{
|
|
|
|
return renderer;
|
|
|
|
}
|
|
|
|
|
|
|
|
Simulation* CelestiaCore::getSimulation() const
|
|
|
|
{
|
|
|
|
return sim;
|
|
|
|
}
|
|
|
|
|
2002-09-22 03:24:45 -06:00
|
|
|
void CelestiaCore::showText(string s,
|
|
|
|
int horig, int vorig,
|
|
|
|
int hoff, int voff,
|
|
|
|
double duration)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
messageText = s;
|
2002-09-22 03:24:45 -06:00
|
|
|
messageHOrigin = horig;
|
|
|
|
messageVOrigin = vorig;
|
|
|
|
messageHOffset = hoff;
|
|
|
|
messageVOffset = voff;
|
|
|
|
messageStart = currentTime;
|
|
|
|
messageDuration = duration;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
2003-07-29 23:54:45 -06:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
static void displayDistance(Overlay& overlay, double distance)
|
|
|
|
{
|
|
|
|
if (abs(distance) >= astro::AUtoLightYears(1000.0f))
|
|
|
|
overlay.printf("%.3f ly", distance);
|
|
|
|
else if (abs(distance) >= astro::kilometersToLightYears(10000000.0))
|
|
|
|
overlay.printf("%.3f au", astro::lightYearsToAU(distance));
|
|
|
|
else if (abs(distance) > astro::kilometersToLightYears(1.0f))
|
|
|
|
overlay.printf("%.3f km", astro::lightYearsToKilometers(distance));
|
|
|
|
else
|
|
|
|
overlay.printf("%.3f m", astro::lightYearsToKilometers(distance) * 1000.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void displayStarNames(Overlay& overlay,
|
|
|
|
Star& star,
|
2002-01-10 17:04:14 -07:00
|
|
|
StarDatabase& starDB,
|
|
|
|
int maxNames = 10)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
StarNameDatabase::NumberIndex::const_iterator iter =
|
|
|
|
starDB.getStarNames(star.getCatalogNumber());
|
|
|
|
|
2002-01-10 17:04:14 -07:00
|
|
|
int count = 0;
|
2001-11-27 18:50:04 -07:00
|
|
|
while (iter != starDB.finalName() &&
|
2002-01-10 17:04:14 -07:00
|
|
|
iter->first == star.getCatalogNumber() &&
|
|
|
|
count < maxNames)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-10 17:04:14 -07:00
|
|
|
if (count != 0)
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay << " / ";
|
|
|
|
overlay << iter->second;
|
|
|
|
iter++;
|
2002-01-10 17:04:14 -07:00
|
|
|
count++;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 hd = star.getCatalogNumber(Star::HDCatalog);
|
|
|
|
uint32 hip = star.getCatalogNumber(Star::HIPCatalog);
|
2002-01-10 17:04:14 -07:00
|
|
|
if (hd != Star::InvalidCatalogNumber && hd != 0 && count < maxNames)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-10 17:04:14 -07:00
|
|
|
if (count != 0)
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay << " / ";
|
|
|
|
overlay << "HD " << hd;
|
2002-01-10 17:04:14 -07:00
|
|
|
count++;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
2002-01-10 17:04:14 -07:00
|
|
|
if (hip != Star::InvalidCatalogNumber && hip != 0 && count < maxNames)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-10 17:04:14 -07:00
|
|
|
if (count != 0)
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay << " / ";
|
2002-09-08 21:51:22 -06:00
|
|
|
if (hip >= 1000000)
|
2002-09-08 01:28:24 -06:00
|
|
|
{
|
|
|
|
uint32 tyc3 = hip / 1000000000;
|
|
|
|
hip -= tyc3 * 1000000000;
|
|
|
|
uint32 tyc2 = hip / 10000;
|
|
|
|
hip -= tyc2 * 10000;
|
|
|
|
uint32 tyc1 = hip;
|
|
|
|
overlay << "TYC " << tyc1 << '-' << tyc2 << '-' << tyc3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
overlay << "HIP " << hip;
|
2002-01-10 17:04:14 -07:00
|
|
|
count++;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void displayStarInfo(Overlay& overlay,
|
|
|
|
int detail,
|
|
|
|
Star& star,
|
2002-01-07 15:48:32 -07:00
|
|
|
const Universe& universe,
|
2001-11-27 18:50:04 -07:00
|
|
|
double distance)
|
|
|
|
{
|
|
|
|
overlay << "Distance: ";
|
|
|
|
displayDistance(overlay, distance);
|
|
|
|
overlay << '\n';
|
|
|
|
|
|
|
|
overlay.printf("Abs (app) mag = %.2f (%.2f)\n",
|
|
|
|
star.getAbsoluteMagnitude(),
|
|
|
|
astro::absToAppMag(star.getAbsoluteMagnitude(), (float) distance));
|
|
|
|
overlay << "Class: " << star.getStellarClass() << '\n';
|
|
|
|
if (detail > 1)
|
|
|
|
{
|
|
|
|
overlay << "Surface Temp: " << star.getTemperature() << " K\n";
|
|
|
|
overlay.printf("Radius: %.2f Rsun\n", star.getRadius() / 696000.0f);
|
|
|
|
|
2003-06-09 03:33:24 -06:00
|
|
|
overlay << "Rotation Period: ";
|
|
|
|
float period = star.getRotationPeriod();
|
|
|
|
if (period > 1.0f)
|
|
|
|
overlay << period << " days\n";
|
|
|
|
else if (period > 1.0f / 24.0f)
|
|
|
|
overlay << period * 24 << " hours\n";
|
|
|
|
else if (period > 1.0f / (24.0f * 60.0f))
|
|
|
|
overlay << period * 24 * 60 << " minutes\n";
|
|
|
|
else
|
|
|
|
overlay << period * 24 * 60 * 60 << " seconds\n";
|
|
|
|
|
2002-01-07 20:04:38 -07:00
|
|
|
SolarSystem* sys = universe.getSolarSystem(&star);
|
|
|
|
if (sys != NULL && sys->getPlanets()->getSystemSize() != 0)
|
|
|
|
overlay << "Planetary companions present\n";
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void displayPlanetInfo(Overlay& overlay,
|
|
|
|
int detail,
|
|
|
|
Body& body,
|
|
|
|
double t,
|
|
|
|
double distance)
|
|
|
|
{
|
|
|
|
// If within fAltitudeThreshold radii of planet, show altitude instead of distance
|
|
|
|
double kmDistance = astro::lightYearsToKilometers(distance);
|
|
|
|
if (kmDistance < fAltitudeThreshold * body.getRadius())
|
|
|
|
{
|
|
|
|
kmDistance -= body.getRadius();
|
|
|
|
overlay << "Altitude: ";
|
|
|
|
distance = astro::kilometersToLightYears(kmDistance);
|
|
|
|
displayDistance(overlay, distance);
|
|
|
|
overlay << '\n';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
overlay << "Distance: ";
|
|
|
|
displayDistance(overlay, distance);
|
|
|
|
overlay << '\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
overlay << "Radius: ";
|
|
|
|
distance = astro::kilometersToLightYears(body.getRadius());
|
|
|
|
displayDistance(overlay, distance);
|
|
|
|
overlay << '\n';
|
|
|
|
|
|
|
|
if (detail > 1)
|
|
|
|
{
|
2001-12-06 01:34:37 -07:00
|
|
|
overlay << "Day length: " << body.getRotationElements().period * 24.0 << " hours\n";
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
PlanetarySystem* system = body.getSystem();
|
|
|
|
if (system != NULL)
|
|
|
|
{
|
|
|
|
const Star* sun = system->getStar();
|
|
|
|
if (sun != NULL)
|
|
|
|
{
|
|
|
|
double distFromSun = body.getHeliocentricPosition(t).distanceFromOrigin();
|
|
|
|
float planetTemp = sun->getTemperature() *
|
2002-11-04 00:54:22 -07:00
|
|
|
(float) (::pow(1.0 - body.getAlbedo(), 0.25) *
|
|
|
|
sqrt(sun->getRadius() / (2.0 * distFromSun)));
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay << setprecision(0);
|
|
|
|
overlay << "Temperature: " << planetTemp << " K\n";
|
|
|
|
overlay << setprecision(3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void displayGalaxyInfo(Overlay& overlay,
|
|
|
|
int detail,
|
|
|
|
Galaxy& galaxy,
|
|
|
|
double distance)
|
|
|
|
{
|
|
|
|
overlay << "Type: " << galaxy.getType() << '\n';
|
|
|
|
overlay << "Radius: " << galaxy.getRadius() << " ly\n";
|
|
|
|
}
|
|
|
|
|
2002-01-10 17:04:14 -07:00
|
|
|
static void displaySelectionName(Overlay& overlay,
|
|
|
|
const Selection& sel,
|
|
|
|
const Universe& univ)
|
|
|
|
{
|
2003-06-25 11:40:24 -06:00
|
|
|
switch (sel.getType())
|
|
|
|
{
|
|
|
|
case Selection::Type_Body:
|
|
|
|
overlay << sel.body()->getName();
|
|
|
|
break;
|
|
|
|
case Selection::Type_DeepSky:
|
|
|
|
overlay << sel.deepsky()->getName();
|
|
|
|
break;
|
|
|
|
case Selection::Type_Star:
|
|
|
|
displayStarNames(overlay, *(sel.star()), *univ.getStarCatalog(), 1);
|
|
|
|
break;
|
|
|
|
case Selection::Type_Location:
|
|
|
|
overlay << sel.location()->getName();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2002-01-10 17:04:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-23 02:04:45 -07:00
|
|
|
static void showViewFrame(const View* v, int width, int height)
|
|
|
|
{
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
|
|
glVertex3f(v->x * width, v->y * height, 0.0f);
|
|
|
|
glVertex3f(v->x * width, (v->y + v->height) * height - 1, 0.0f);
|
|
|
|
glVertex3f((v->x + v->width) * width - 1, (v->y + v->height) * height - 1, 0.0f);
|
|
|
|
glVertex3f((v->x + v->width) * width - 1, v->y * height, 0.0f);
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
void CelestiaCore::renderOverlay()
|
|
|
|
{
|
|
|
|
if (font == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
overlay->setFont(font);
|
|
|
|
|
|
|
|
int fontHeight = font->getHeight();
|
|
|
|
int emWidth = font->getWidth("M");
|
|
|
|
|
|
|
|
overlay->begin();
|
|
|
|
|
2003-03-08 17:32:11 -07:00
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
if (views.size() > 1)
|
|
|
|
{
|
2003-03-11 03:00:25 -07:00
|
|
|
// Render a thin border arround all views
|
2003-03-08 17:32:11 -07:00
|
|
|
if (showViewFrames || resizeSplit)
|
|
|
|
{
|
|
|
|
glLineWidth(1.0f);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
|
|
|
|
for(std::vector<View*>::iterator i = views.begin(); i != views.end(); i++)
|
|
|
|
{
|
|
|
|
showViewFrame(*i, width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glLineWidth(1.0f);
|
|
|
|
|
2003-03-11 03:00:25 -07:00
|
|
|
// Render a very simple border around the active view
|
2003-02-11 09:43:37 -07:00
|
|
|
View* av = views[activeView];
|
|
|
|
|
2003-03-08 17:32:11 -07:00
|
|
|
if (showActiveViewFrame)
|
|
|
|
{
|
|
|
|
glLineWidth(2.0f);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glColor4f(0.5f, 0.5f, 1.0f, 1.0f);
|
|
|
|
showViewFrame(av, width, height);
|
|
|
|
glLineWidth(1.0f);
|
|
|
|
}
|
2003-02-23 02:04:45 -07:00
|
|
|
|
|
|
|
if (currentTime < flashFrameStart + 0.5)
|
|
|
|
{
|
|
|
|
glLineWidth(8.0f);
|
|
|
|
glColor4f(0.5f, 0.5f, 1.0f,
|
|
|
|
1.0f - (currentTime - flashFrameStart) / 0.5f);
|
|
|
|
showViewFrame(av, width, height);
|
|
|
|
glLineWidth(1.0f);
|
|
|
|
}
|
2003-02-11 09:43:37 -07:00
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (hudDetail > 0)
|
|
|
|
{
|
2001-12-04 22:08:11 -07:00
|
|
|
// Time and date
|
2001-11-27 18:50:04 -07:00
|
|
|
glPushMatrix();
|
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 1.0f);
|
2003-03-08 17:32:11 -07:00
|
|
|
glTranslatef(width - (11 + timeZoneName.length() + 3) * emWidth,
|
2002-01-04 17:35:40 -07:00
|
|
|
height - fontHeight, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay->beginText();
|
2002-12-09 14:19:26 -07:00
|
|
|
|
|
|
|
bool time_displayed = false;
|
2003-03-08 17:32:11 -07:00
|
|
|
double lt = 0.0;
|
2003-05-01 10:36:09 -06:00
|
|
|
|
2003-06-25 11:40:24 -06:00
|
|
|
if (sim->getSelection().getType() == Selection::Type_Body &&
|
2003-05-01 10:36:09 -06:00
|
|
|
(sim->getTargetSpeed() < 0.99 *
|
|
|
|
astro::kilometersToMicroLightYears(astro::speedOfLight)))
|
2003-03-08 17:32:11 -07:00
|
|
|
{
|
|
|
|
if (lightTravelFlag)
|
|
|
|
{
|
|
|
|
Vec3d v = sim->getSelection().getPosition(sim->getTime()) -
|
|
|
|
sim->getObserver().getPosition();
|
|
|
|
// light travel time in days
|
|
|
|
lt = astro::microLightYearsToKilometers(v.length())/
|
|
|
|
(86400.0 * astro::speedOfLight);
|
|
|
|
}
|
2003-05-01 10:36:09 -06:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lt = 0.0;
|
2003-03-08 17:32:11 -07:00
|
|
|
}
|
2003-05-01 10:36:09 -06:00
|
|
|
|
|
|
|
|
2003-03-08 17:32:11 -07:00
|
|
|
if (timeZoneBias != 0 && sim->getTime() < 2465442 && sim->getTime()
|
|
|
|
> 2415733)
|
|
|
|
{
|
|
|
|
|
2003-05-01 10:36:09 -06:00
|
|
|
time_t time = (int)astro::julianDateToSeconds(sim->getTime() - 2440587.5 + lt);
|
2002-12-09 14:19:26 -07:00
|
|
|
struct tm *localt = localtime(&time);
|
|
|
|
if (localt != NULL) {
|
|
|
|
astro::Date d;
|
|
|
|
d.year = localt->tm_year + 1900;
|
|
|
|
d.month = localt->tm_mon + 1;
|
|
|
|
d.day = localt->tm_mday;
|
|
|
|
d.hour = localt->tm_hour;
|
|
|
|
d.minute = localt->tm_min;
|
|
|
|
d.seconds = (int)localt->tm_sec;
|
2003-03-08 17:32:11 -07:00
|
|
|
*overlay << d << " " << tzname[localt->tm_isdst>0?1:0];
|
2002-12-09 14:19:26 -07:00
|
|
|
time_displayed = true;
|
2003-05-01 10:36:09 -06:00
|
|
|
if (lightTravelFlag && lt > 0.0)
|
2003-03-08 17:32:11 -07:00
|
|
|
{
|
|
|
|
glColor4f(0.42f, 1.0f, 1.0f, 1.0f);
|
|
|
|
*overlay <<" LT" << '\n';
|
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 1.0f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*overlay << '\n';
|
|
|
|
|
2002-12-09 14:19:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!time_displayed) {
|
2003-05-01 10:36:09 -06:00
|
|
|
*overlay << astro::Date(sim->getTime() + lt);
|
2003-03-08 17:32:11 -07:00
|
|
|
*overlay << " UTC";
|
2003-05-01 10:36:09 -06:00
|
|
|
if (lightTravelFlag && lt > 0.0)
|
2003-03-08 17:32:11 -07:00
|
|
|
{
|
|
|
|
glColor4f(0.42f, 1.0f, 1.0f, 1.0f);
|
|
|
|
*overlay <<" LT" << '\n';
|
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 1.0f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*overlay << '\n';
|
2002-12-09 14:19:26 -07:00
|
|
|
}
|
2002-01-04 17:35:40 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (paused)
|
|
|
|
{
|
|
|
|
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
*overlay << "Paused";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double timeScale = sim->getTimeScale();
|
2003-04-13 00:24:52 -06:00
|
|
|
|
|
|
|
*overlay << setprecision(0);
|
2001-12-04 22:31:09 -07:00
|
|
|
if (abs(abs(timeScale) - 1) < 1e-6)
|
2001-12-04 22:08:11 -07:00
|
|
|
{
|
|
|
|
if (sign(timeScale) == 1)
|
|
|
|
*overlay << "Real time";
|
|
|
|
else
|
|
|
|
*overlay << "-Real time";
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
else if (abs(timeScale) == 0.0f)
|
|
|
|
*overlay << "Time stopped";
|
|
|
|
else if (abs(timeScale) > 1.0)
|
|
|
|
*overlay << timeScale << "x faster";
|
|
|
|
else
|
|
|
|
*overlay << 1.0 / timeScale << "x slower";
|
2003-04-13 00:24:52 -06:00
|
|
|
*overlay << setprecision(3);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
overlay->endText();
|
|
|
|
glPopMatrix();
|
|
|
|
|
2001-12-04 22:08:11 -07:00
|
|
|
// Speed
|
2001-11-27 18:50:04 -07:00
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(0, fontHeight * 2 + 5, 0);
|
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
overlay->beginText();
|
|
|
|
*overlay << '\n';
|
|
|
|
if (showFPSCounter)
|
|
|
|
*overlay << "FPS: " << fps;
|
|
|
|
overlay->setf(ios::fixed);
|
|
|
|
*overlay << "\nSpeed: " << setprecision(3);
|
|
|
|
|
|
|
|
double speed = sim->getObserver().getVelocity().length();
|
2002-03-14 14:48:51 -07:00
|
|
|
if (speed < astro::kilometersToMicroLightYears(1.0f))
|
|
|
|
*overlay << astro::microLightYearsToKilometers(speed) * 1000.0f << " m/s";
|
|
|
|
else if (speed < astro::kilometersToMicroLightYears(10000.0f))
|
|
|
|
*overlay << astro::microLightYearsToKilometers(speed) << " km/s";
|
|
|
|
else if (speed < astro::kilometersToMicroLightYears((float) astro::speedOfLight * 100.0f))
|
|
|
|
*overlay << astro::microLightYearsToKilometers(speed) / astro::speedOfLight << 'c';
|
|
|
|
else if (speed < astro::AUtoMicroLightYears(1000.0f))
|
|
|
|
*overlay << astro::microLightYearsToAU(speed) << " AU/s";
|
2001-11-27 18:50:04 -07:00
|
|
|
else
|
2002-03-14 14:48:51 -07:00
|
|
|
*overlay << speed * 1e-6 << " ly/s";
|
2001-11-27 18:50:04 -07:00
|
|
|
*overlay << setprecision(3);
|
|
|
|
|
|
|
|
overlay->endText();
|
|
|
|
glPopMatrix();
|
|
|
|
|
2002-01-10 17:04:14 -07:00
|
|
|
// Field of view and camera mode in lower right corner
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(width - emWidth * 15, fontHeight * 3 + 5, 0);
|
|
|
|
overlay->beginText();
|
|
|
|
glColor4f(0.6f, 0.6f, 1.0f, 1);
|
2001-11-28 09:14:56 -07:00
|
|
|
|
2003-02-11 09:43:37 -07:00
|
|
|
if (sim->getObserverMode() == Observer::Travelling)
|
2002-05-02 01:58:50 -06:00
|
|
|
{
|
|
|
|
*overlay << "Travelling ";
|
|
|
|
double timeLeft = sim->getArrivalTime() - sim->getRealTime();
|
|
|
|
if (timeLeft >= 1)
|
|
|
|
*overlay << '(' << (int) timeLeft << ')';
|
|
|
|
*overlay << '\n';
|
|
|
|
}
|
2002-01-10 17:04:14 -07:00
|
|
|
else
|
2002-05-02 01:58:50 -06:00
|
|
|
{
|
2002-01-10 17:04:14 -07:00
|
|
|
*overlay << '\n';
|
2002-05-02 01:58:50 -06:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2002-01-10 17:04:14 -07:00
|
|
|
if (!sim->getTrackedObject().empty())
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-10 17:04:14 -07:00
|
|
|
*overlay << "Track ";
|
|
|
|
displaySelectionName(*overlay, sim->getTrackedObject(),
|
|
|
|
*sim->getUniverse());
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
2002-01-10 17:04:14 -07:00
|
|
|
*overlay << '\n';
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-10 17:04:14 -07:00
|
|
|
FrameOfReference frame = sim->getFrame();
|
|
|
|
|
|
|
|
switch (frame.coordSys)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
case astro::Ecliptical:
|
2002-01-10 17:04:14 -07:00
|
|
|
*overlay << "Follow ";
|
|
|
|
displaySelectionName(*overlay, frame.refObject,
|
|
|
|
*sim->getUniverse());
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
|
|
|
case astro::Geographic:
|
2002-01-10 17:04:14 -07:00
|
|
|
*overlay << "Sync Orbit ";
|
|
|
|
displaySelectionName(*overlay, frame.refObject,
|
|
|
|
*sim->getUniverse());
|
2001-11-27 18:50:04 -07:00
|
|
|
break;
|
2002-03-18 19:55:01 -07:00
|
|
|
case astro::PhaseLock:
|
|
|
|
*overlay << "Lock ";
|
|
|
|
displaySelectionName(*overlay, frame.refObject,
|
|
|
|
*sim->getUniverse());
|
|
|
|
*overlay << " -> ";
|
|
|
|
displaySelectionName(*overlay, frame.targetObject,
|
|
|
|
*sim->getUniverse());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case astro::Chase:
|
|
|
|
*overlay << "Chase ";
|
|
|
|
displaySelectionName(*overlay, frame.refObject,
|
|
|
|
*sim->getUniverse());
|
|
|
|
break;
|
|
|
|
|
2002-01-02 15:07:11 -07:00
|
|
|
default:
|
|
|
|
break;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
2002-01-10 17:04:14 -07:00
|
|
|
|
|
|
|
*overlay << '\n';
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 1.0f);
|
2002-01-10 17:04:14 -07:00
|
|
|
|
|
|
|
// Field of view
|
2003-02-12 03:28:32 -07:00
|
|
|
float fov = radToDeg(sim->getActiveObserver()->getFOV());
|
2002-01-10 17:04:14 -07:00
|
|
|
int degrees, minutes;
|
|
|
|
double seconds;
|
2003-02-12 03:28:32 -07:00
|
|
|
astro::decimalToDegMinSec((double) fov, degrees, minutes, seconds);
|
2002-01-10 17:04:14 -07:00
|
|
|
|
2002-01-04 06:32:19 -07:00
|
|
|
if (degrees > 0)
|
2003-06-03 14:11:09 -06:00
|
|
|
overlay->printf("FOV: %d %02d' %.1f\"", degrees, minutes, seconds);
|
2002-01-04 06:32:19 -07:00
|
|
|
else if (minutes > 0)
|
2003-06-03 14:11:09 -06:00
|
|
|
overlay->printf("FOV: %02d' %.1f\"", minutes, seconds);
|
2001-11-28 09:14:56 -07:00
|
|
|
else
|
2003-06-03 14:11:09 -06:00
|
|
|
overlay->printf("FOV: %.1f\"", seconds);
|
|
|
|
overlay->printf(" (%.2f x)\n", views[activeView]->zoom);
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay->endText();
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Selection info
|
|
|
|
Selection sel = sim->getSelection();
|
|
|
|
if (!sel.empty() && hudDetail > 0)
|
|
|
|
{
|
|
|
|
glPushMatrix();
|
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 1.0f);
|
|
|
|
glTranslatef(0, height - titleFont->getHeight(), 0);
|
|
|
|
|
|
|
|
overlay->beginText();
|
2002-01-09 16:04:14 -07:00
|
|
|
Vec3d v = sel.getPosition(sim->getTime()) -
|
2001-11-27 18:50:04 -07:00
|
|
|
sim->getObserver().getPosition();
|
2003-06-25 11:40:24 -06:00
|
|
|
switch (sel.getType())
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2003-06-25 11:40:24 -06:00
|
|
|
case Selection::Type_Star:
|
|
|
|
{
|
|
|
|
overlay->setFont(titleFont);
|
|
|
|
displayStarNames(*overlay,
|
|
|
|
*(sel.star()),
|
|
|
|
*(sim->getUniverse()->getStarCatalog()));
|
|
|
|
overlay->setFont(font);
|
|
|
|
*overlay << '\n';
|
|
|
|
displayStarInfo(*overlay,
|
|
|
|
hudDetail,
|
|
|
|
*(sel.star()),
|
|
|
|
*(sim->getUniverse()),
|
|
|
|
v.length() * 1e-6);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Selection::Type_Body:
|
|
|
|
{
|
|
|
|
overlay->setFont(titleFont);
|
|
|
|
*overlay << sel.body()->getName();
|
|
|
|
overlay->setFont(font);
|
|
|
|
*overlay << '\n';
|
|
|
|
displayPlanetInfo(*overlay,
|
|
|
|
hudDetail,
|
|
|
|
*(sel.body()),
|
|
|
|
sim->getTime(),
|
|
|
|
v.length() * 1e-6);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Selection::Type_DeepSky:
|
|
|
|
{
|
|
|
|
overlay->setFont(titleFont);
|
|
|
|
*overlay << sel.deepsky()->getName();
|
|
|
|
overlay->setFont(font);
|
|
|
|
*overlay << '\n';
|
|
|
|
*overlay << "Distance: ";
|
|
|
|
displayDistance(*overlay, v.length() * 1e-6);
|
|
|
|
*overlay << '\n';
|
2003-01-28 22:47:50 -07:00
|
|
|
#if 0
|
2003-06-25 11:40:24 -06:00
|
|
|
displayGalaxyInfo(*overlay, hudDetail, *sel.galaxy,
|
|
|
|
v.length() * 1e-6);
|
2003-01-28 22:47:50 -07:00
|
|
|
#endif
|
2003-06-25 11:40:24 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Selection::Type_Location:
|
2003-06-29 10:26:08 -06:00
|
|
|
overlay->setFont(titleFont);
|
|
|
|
*overlay << sel.location()->getName();
|
|
|
|
overlay->setFont(font);
|
|
|
|
*overlay << '\n';
|
2003-06-25 11:40:24 -06:00
|
|
|
break;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
2003-06-25 11:40:24 -06:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay->endText();
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Text input
|
|
|
|
if (textEnterMode)
|
|
|
|
{
|
|
|
|
overlay->setFont(titleFont);
|
2003-05-31 04:55:44 -06:00
|
|
|
// glPushMatrix();
|
2001-11-27 18:50:04 -07:00
|
|
|
glColor4f(0.7f, 0.7f, 1.0f, 0.2f);
|
2003-05-31 04:55:44 -06:00
|
|
|
overlay->rect(0, 0, width, 100);
|
|
|
|
glTranslatef(0, fontHeight * 3 + 35, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
glColor4f(0.6f, 0.6f, 1.0f, 1);
|
2003-05-31 04:55:44 -06:00
|
|
|
overlay->beginText();
|
2001-11-27 18:50:04 -07:00
|
|
|
*overlay << "Target name: " << typedText;
|
2003-05-31 04:55:44 -06:00
|
|
|
overlay->endText();
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay->setFont(font);
|
2003-06-03 14:11:09 -06:00
|
|
|
if (typedTextCompletion.size() >= 1)
|
2003-05-31 04:55:44 -06:00
|
|
|
{
|
|
|
|
int nb_cols = 4;
|
|
|
|
int nb_lines = 3;
|
2003-06-03 16:19:22 -06:00
|
|
|
int start = 0;
|
2003-05-31 04:55:44 -06:00
|
|
|
glTranslatef( 3, - font->getHeight() - 3, 0);
|
|
|
|
std::vector<std::string>::const_iterator iter = typedTextCompletion.begin();
|
|
|
|
if (typedTextCompletionIdx >= nb_cols * nb_lines)
|
|
|
|
{
|
|
|
|
start = (typedTextCompletionIdx / nb_lines + 1 - nb_cols) * nb_lines;
|
|
|
|
iter += start;
|
|
|
|
}
|
|
|
|
for (int i=0; iter < typedTextCompletion.end() && i < nb_cols; i++)
|
|
|
|
{
|
|
|
|
glPushMatrix();
|
|
|
|
overlay->beginText();
|
|
|
|
for (int j = 0; iter < typedTextCompletion.end() && j < nb_lines; iter++, j++)
|
|
|
|
{
|
|
|
|
if (i * nb_lines + j == typedTextCompletionIdx - start)
|
|
|
|
glColor4f(1.0f, 0.6f, 0.6f, 1);
|
|
|
|
else
|
|
|
|
glColor4f(0.6f, 0.6f, 1.0f, 1);
|
|
|
|
*overlay << *iter << "\n";
|
|
|
|
}
|
|
|
|
overlay->endText();
|
|
|
|
glPopMatrix();
|
|
|
|
glTranslatef( (width/nb_cols), 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// glPopMatrix();
|
|
|
|
// overlay->setFont(font);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Text messages
|
2002-09-22 03:24:45 -06:00
|
|
|
if (messageText != "" && currentTime < messageStart + messageDuration)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-09-22 03:24:45 -06:00
|
|
|
int emWidth = titleFont->getWidth("M");
|
|
|
|
int fontHeight = titleFont->getHeight();
|
|
|
|
int x = messageHOffset * emWidth;
|
|
|
|
int y = messageVOffset * fontHeight;
|
|
|
|
|
|
|
|
if (messageHOrigin == 0)
|
|
|
|
x += width / 2;
|
|
|
|
else if (messageHOrigin > 0)
|
|
|
|
x += width;
|
|
|
|
if (messageVOrigin == 0)
|
|
|
|
y += height / 2;
|
|
|
|
else if (messageVOrigin > 0)
|
|
|
|
y += height;
|
|
|
|
else if (messageVOrigin < 0)
|
|
|
|
y -= fontHeight;
|
2002-09-22 15:45:23 -06:00
|
|
|
#if 0
|
2002-09-22 03:24:45 -06:00
|
|
|
cout << '(' << x << ',' << y << ") horig=" << messageHOrigin << ", vorigin=" << messageVOrigin << '\n';
|
2002-09-22 15:45:23 -06:00
|
|
|
#endif
|
2002-09-22 03:24:45 -06:00
|
|
|
overlay->setFont(titleFont);
|
2001-11-27 18:50:04 -07:00
|
|
|
glPushMatrix();
|
2002-09-22 03:24:45 -06:00
|
|
|
|
|
|
|
float alpha = 1.0f;
|
|
|
|
if (currentTime > messageStart + messageDuration - 0.5)
|
|
|
|
alpha = (float) ((messageStart + messageDuration - currentTime) / 0.5);
|
|
|
|
glColor4f(1, 1, 1, alpha);
|
|
|
|
glTranslatef(x, y, 0);
|
2001-11-27 18:50:04 -07:00
|
|
|
overlay->beginText();
|
|
|
|
*overlay << messageText;
|
|
|
|
overlay->endText();
|
|
|
|
glPopMatrix();
|
2002-09-22 03:24:45 -06:00
|
|
|
overlay->setFont(font);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
2001-12-10 21:20:05 -07:00
|
|
|
if (movieCapture != NULL)
|
|
|
|
{
|
|
|
|
int movieWidth = movieCapture->getWidth();
|
|
|
|
int movieHeight = movieCapture->getHeight();
|
|
|
|
glPushMatrix();
|
|
|
|
glColor4f(1, 0, 0, 1);
|
|
|
|
overlay->rect((width - movieWidth) / 2 - 1, (height - movieHeight) / 2 - 1,
|
|
|
|
movieWidth + 1, movieHeight + 1, false);
|
|
|
|
glTranslatef((width - movieWidth) / 2, (height + movieHeight) / 2 + 2, 0);
|
|
|
|
*overlay << movieWidth << 'x' << movieHeight << " at " <<
|
|
|
|
movieCapture->getFrameRate() << " fps";
|
|
|
|
if (recording)
|
|
|
|
*overlay << " Recording";
|
|
|
|
else
|
|
|
|
*overlay << " Paused";
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
|
2002-03-08 12:36:50 -07:00
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef((width + movieWidth) / 2 - emWidth * 5,
|
|
|
|
(height + movieHeight) / 2 + 2, 0);
|
|
|
|
float sec = movieCapture->getFrameCount() /
|
|
|
|
movieCapture->getFrameRate();
|
|
|
|
int min = (int) (sec / 60);
|
|
|
|
sec -= min * 60.0f;
|
|
|
|
overlay->printf("%3d:%05.2f", min, sec);
|
|
|
|
glPopMatrix();
|
|
|
|
|
2001-12-10 21:20:05 -07:00
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef((width - movieWidth) / 2,
|
|
|
|
(height - movieHeight) / 2 - fontHeight - 2, 0);
|
|
|
|
*overlay << "F11 Start/Pause F12 Stop";
|
|
|
|
glPopMatrix();
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (editMode)
|
|
|
|
{
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef((width - font->getWidth("Edit Mode")) / 2, height - fontHeight, 0);
|
|
|
|
glColor4f(1, 0, 1, 1);
|
|
|
|
*overlay << "Edit Mode";
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show logo at start
|
|
|
|
if (logoTexture != NULL)
|
|
|
|
{
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
if (currentTime < 5.0)
|
|
|
|
{
|
|
|
|
int xSize = (int) (logoTexture->getWidth() * 0.8f);
|
|
|
|
int ySize = (int) (logoTexture->getHeight() * 0.8f);
|
|
|
|
int left = (width - xSize) / 2;
|
|
|
|
int bottom = height / 2;
|
|
|
|
|
|
|
|
float topAlpha, botAlpha;
|
|
|
|
if (currentTime < 4.0)
|
|
|
|
{
|
|
|
|
botAlpha = (float) clamp(currentTime / 1.0);
|
|
|
|
topAlpha = (float) clamp(currentTime / 4.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
botAlpha = topAlpha = (float) (5.0 - currentTime);
|
|
|
|
}
|
|
|
|
|
2003-07-29 23:54:45 -06:00
|
|
|
logoTexture->bind();
|
2001-11-27 18:50:04 -07:00
|
|
|
glBegin(GL_QUADS);
|
|
|
|
glColor4f(0.8f, 0.8f, 1.0f, botAlpha);
|
|
|
|
glTexCoord2f(0, 1);
|
|
|
|
glVertex2f(left, bottom);
|
|
|
|
glTexCoord2f(1, 1);
|
|
|
|
glVertex2f(left + xSize, bottom);
|
|
|
|
glColor4f(0.6f, 0.6f, 1.0f, topAlpha);
|
|
|
|
glTexCoord2f(1, 0);
|
|
|
|
glVertex2f(left + xSize, bottom + ySize);
|
|
|
|
glTexCoord2f(0, 0);
|
|
|
|
glVertex2f(left, bottom + ySize);
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete logoTexture;
|
|
|
|
logoTexture = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
overlay->end();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-03-02 12:06:58 -07:00
|
|
|
class SolarSystemLoader : public EnumFilesHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Universe* universe;
|
|
|
|
SolarSystemLoader(Universe* u) : universe(u) {};
|
|
|
|
|
|
|
|
bool process(const string& filename)
|
|
|
|
{
|
|
|
|
if (DetermineFileType(filename) == Content_CelestiaCatalog)
|
|
|
|
{
|
|
|
|
string fullname = getPath() + '/' + filename;
|
|
|
|
ifstream solarSysFile(fullname.c_str(), ios::in);
|
|
|
|
if (solarSysFile.good())
|
2003-03-11 03:00:25 -07:00
|
|
|
{
|
|
|
|
LoadSolarSystemObjects(solarSysFile,
|
2003-03-23 13:24:03 -07:00
|
|
|
*universe,
|
2003-03-23 14:35:12 -07:00
|
|
|
getPath());
|
2003-03-11 03:00:25 -07:00
|
|
|
}
|
2003-03-02 12:06:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
class DeepSkyLoader : public EnumFilesHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DeepSkyCatalog* catalog;
|
|
|
|
DeepSkyLoader(DeepSkyCatalog* c) : catalog(c) {};
|
|
|
|
|
|
|
|
bool process(const string& filename)
|
|
|
|
{
|
|
|
|
if (DetermineFileType(filename) == Content_CelestiaDeepSkyCatalog)
|
|
|
|
{
|
|
|
|
string fullname = getPath() + '/' + filename;
|
|
|
|
ifstream deepSkyFile(fullname.c_str(), ios::in);
|
|
|
|
if (deepSkyFile.good())
|
|
|
|
{
|
2003-03-24 02:04:13 -07:00
|
|
|
LoadDeepSkyObjects(*catalog, deepSkyFile, getPath());
|
2003-03-02 12:06:58 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Log the failure
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
class StarLoader : public EnumFilesHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
StarDatabase* starDB;
|
|
|
|
StarLoader(StarDatabase* s) : starDB(s) {};
|
|
|
|
|
|
|
|
bool process(const string& filename)
|
|
|
|
{
|
|
|
|
if (DetermineFileType(filename) == Content_CelestiaStarCatalog)
|
|
|
|
{
|
|
|
|
string fullname = getPath() + '/' + filename;
|
|
|
|
ifstream starFile(fullname.c_str(), ios::in);
|
|
|
|
if (starFile.good())
|
|
|
|
{
|
|
|
|
bool success = starDB->load(starFile);
|
|
|
|
if (!success)
|
|
|
|
{
|
|
|
|
DPRINTF(0, "Error reading star file: %s\n",
|
|
|
|
fullname.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
bool CelestiaCore::initSimulation()
|
|
|
|
{
|
|
|
|
// Say we're not ready to render yet.
|
|
|
|
// bReady = false;
|
|
|
|
#ifdef REQUIRE_LICENSE_FILE
|
|
|
|
// Check for the presence of the license file--don't run unless it's there.
|
|
|
|
{
|
|
|
|
ifstream license("License.txt");
|
|
|
|
if (!license.good())
|
|
|
|
{
|
|
|
|
fatalError("License file 'License.txt' is missing!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
config = ReadCelestiaConfig("celestia.cfg");
|
|
|
|
if (config == NULL)
|
|
|
|
{
|
|
|
|
fatalError("Error reading configuration file.");;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-10-22 11:26:51 -06:00
|
|
|
KeyRotationAccel = degToRad(config->rotateAcceleration);
|
|
|
|
|
2002-02-28 16:29:13 -07:00
|
|
|
readFavoritesFile();
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
// If we couldn't read the favorites list from a file, allocate
|
|
|
|
// an empty list.
|
|
|
|
if (favorites == NULL)
|
|
|
|
favorites = new FavoritesList();
|
|
|
|
|
2002-01-07 15:48:32 -07:00
|
|
|
universe = new Universe();
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (!readStars(*config))
|
|
|
|
{
|
|
|
|
fatalError("Cannot read star database.");
|
|
|
|
return false;
|
2002-05-08 02:02:57 -06:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2002-11-16 16:31:31 -07:00
|
|
|
// First read the solar system files listed individually in the
|
|
|
|
// config file.
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-01-07 15:48:32 -07:00
|
|
|
SolarSystemCatalog* solarSystemCatalog = new SolarSystemCatalog();
|
2002-01-07 20:04:38 -07:00
|
|
|
universe->setSolarSystemCatalog(solarSystemCatalog);
|
2001-11-27 18:50:04 -07:00
|
|
|
for (vector<string>::const_iterator iter = config->solarSystemFiles.begin();
|
|
|
|
iter != config->solarSystemFiles.end();
|
|
|
|
iter++)
|
|
|
|
{
|
|
|
|
ifstream solarSysFile(iter->c_str(), ios::in);
|
|
|
|
if (!solarSysFile.good())
|
|
|
|
{
|
|
|
|
warning("Error opening solar system catalog.\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-03-23 13:24:03 -07:00
|
|
|
LoadSolarSystemObjects(solarSysFile, *universe, "");
|
2002-01-07 20:04:38 -07:00
|
|
|
}
|
|
|
|
}
|
2002-11-16 16:31:31 -07:00
|
|
|
}
|
2002-01-07 20:04:38 -07:00
|
|
|
|
2002-02-18 01:23:57 -07:00
|
|
|
#if 0
|
2003-03-02 12:06:58 -07:00
|
|
|
// XML support not ready yet
|
2003-01-31 16:37:47 -07:00
|
|
|
{
|
|
|
|
bool success = LoadSolarSystemObjectsXML("data/test.xml",
|
|
|
|
*universe);
|
|
|
|
if (!success)
|
|
|
|
warning("Error opening test.xml\n");
|
|
|
|
}
|
2002-02-18 01:23:57 -07:00
|
|
|
#endif
|
|
|
|
|
2002-11-16 16:31:31 -07:00
|
|
|
// Next, read all the solar system files in the extras directories
|
|
|
|
{
|
|
|
|
for (vector<string>::const_iterator iter = config->extrasDirs.begin();
|
|
|
|
iter != config->extrasDirs.end(); iter++)
|
2002-01-07 20:04:38 -07:00
|
|
|
{
|
2002-11-16 16:31:31 -07:00
|
|
|
if (*iter != "")
|
2002-01-07 20:04:38 -07:00
|
|
|
{
|
2002-11-16 16:31:31 -07:00
|
|
|
Directory* dir = OpenDirectory(*iter);
|
2003-03-02 12:06:58 -07:00
|
|
|
|
|
|
|
SolarSystemLoader loader(universe);
|
|
|
|
loader.pushDir(*iter);
|
|
|
|
dir->enumFiles(loader, true);
|
2002-11-16 16:31:31 -07:00
|
|
|
|
|
|
|
delete dir;
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-31 16:37:47 -07:00
|
|
|
DeepSkyCatalog* deepSkyCatalog = new DeepSkyCatalog();
|
2003-01-28 22:47:50 -07:00
|
|
|
if (config->deepSkyCatalog != "")
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2003-01-28 22:47:50 -07:00
|
|
|
ifstream deepSkyFile(config->deepSkyCatalog.c_str(), ios::in);
|
|
|
|
if (!deepSkyFile.good())
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2003-01-28 22:47:50 -07:00
|
|
|
warning("Error opening deep sky file.\n");
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-03-24 02:04:13 -07:00
|
|
|
LoadDeepSkyObjects(*deepSkyCatalog, deepSkyFile, "");
|
2003-01-31 16:37:47 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, read all the deep sky files in the extras directories
|
|
|
|
{
|
|
|
|
for (vector<string>::const_iterator iter = config->extrasDirs.begin();
|
|
|
|
iter != config->extrasDirs.end(); iter++)
|
|
|
|
{
|
|
|
|
if (*iter != "")
|
|
|
|
{
|
|
|
|
Directory* dir = OpenDirectory(*iter);
|
2003-03-02 12:06:58 -07:00
|
|
|
|
|
|
|
DeepSkyLoader loader(deepSkyCatalog);
|
|
|
|
loader.pushDir(*iter);
|
|
|
|
dir->enumFiles(loader, true);
|
2003-01-31 16:37:47 -07:00
|
|
|
|
|
|
|
delete dir;
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-31 16:37:47 -07:00
|
|
|
universe->setDeepSkyCatalog(deepSkyCatalog);
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
if (config->asterismsFile != "")
|
|
|
|
{
|
|
|
|
ifstream asterismsFile(config->asterismsFile.c_str(), ios::in);
|
|
|
|
if (!asterismsFile.good())
|
|
|
|
{
|
|
|
|
warning("Error opening asterisms file.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-01-07 15:48:32 -07:00
|
|
|
AsterismList* asterisms = ReadAsterismList(asterismsFile,
|
|
|
|
*universe->getStarCatalog());
|
|
|
|
universe->setAsterisms(asterisms);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
}
|
2002-06-21 15:14:51 -06:00
|
|
|
|
2002-06-04 23:27:53 -06:00
|
|
|
if (config->boundariesFile != "")
|
|
|
|
{
|
|
|
|
ifstream boundariesFile(config->boundariesFile.c_str(), ios::in);
|
|
|
|
if (!boundariesFile.good())
|
|
|
|
{
|
|
|
|
warning("Error opening constellation boundaries files.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ConstellationBoundaries* boundaries = ReadBoundaries(boundariesFile);
|
|
|
|
universe->setBoundaries(boundaries);
|
|
|
|
}
|
|
|
|
}
|
2002-06-21 15:14:51 -06:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
// Load initialization script
|
|
|
|
if (config->initScriptFile != "")
|
|
|
|
{
|
|
|
|
ifstream scriptfile(config->initScriptFile.c_str());
|
|
|
|
CommandParser parser(scriptfile);
|
|
|
|
initScript = parser.parse();
|
|
|
|
if (initScript == NULL)
|
|
|
|
{
|
|
|
|
const vector<string>* errors = parser.getErrors();
|
|
|
|
for_each(errors->begin(), errors->end(), printlineFunc<string>(cout));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load demo script
|
|
|
|
if (config->demoScriptFile != "")
|
|
|
|
{
|
|
|
|
ifstream scriptfile(config->demoScriptFile.c_str());
|
|
|
|
CommandParser parser(scriptfile);
|
|
|
|
demoScript = parser.parse();
|
|
|
|
if (demoScript == NULL)
|
|
|
|
{
|
|
|
|
const vector<string>* errors = parser.getErrors();
|
|
|
|
for_each(errors->begin(), errors->end(), printlineFunc<string>(cout));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load destinations list
|
|
|
|
if (config->destinationsFile != "")
|
|
|
|
{
|
|
|
|
ifstream destfile(config->destinationsFile.c_str());
|
|
|
|
if (destfile.good())
|
|
|
|
{
|
|
|
|
destinations = ReadDestinationList(destfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-01-07 15:48:32 -07:00
|
|
|
sim = new Simulation(universe);
|
2002-09-22 08:46:50 -06:00
|
|
|
if((renderer->getRenderFlags() & Renderer::ShowAutoMag) == 0)
|
2001-11-27 18:50:04 -07:00
|
|
|
sim->setFaintestVisible(config->faintestVisible);
|
|
|
|
|
2003-02-18 14:11:18 -07:00
|
|
|
View* view = new View(View::ViewWindow, sim->getActiveObserver(), 0.0f, 0.0f, 1.0f, 1.0f);
|
2003-02-11 09:43:37 -07:00
|
|
|
views.insert(views.end(), view);
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CelestiaCore::initRenderer()
|
|
|
|
{
|
|
|
|
renderer->setRenderFlags(Renderer::ShowStars |
|
|
|
|
Renderer::ShowPlanets |
|
2002-06-22 09:18:47 -06:00
|
|
|
Renderer::ShowAtmospheres |
|
2002-09-22 03:24:45 -06:00
|
|
|
Renderer::ShowAutoMag);
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2003-02-19 10:48:25 -07:00
|
|
|
GLContext* context = new GLContext();
|
|
|
|
assert(context != NULL);
|
|
|
|
if (context == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
context->init(config->ignoreGLExtensions);
|
|
|
|
// Choose the render path, starting with the least desirable
|
|
|
|
context->setRenderPath(GLContext::GLPath_Basic);
|
|
|
|
context->setRenderPath(GLContext::GLPath_Multitexture);
|
|
|
|
context->setRenderPath(GLContext::GLPath_DOT3_ARBVP);
|
|
|
|
context->setRenderPath(GLContext::GLPath_NvCombiner_NvVP);
|
|
|
|
context->setRenderPath(GLContext::GLPath_NvCombiner_ARBVP);
|
|
|
|
cout << "render path: " << context->getRenderPath() << '\n';
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
// Prepare the scene for rendering.
|
2003-02-19 10:48:25 -07:00
|
|
|
if (!renderer->init(context, (int) width, (int) height))
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
|
|
|
fatalError("Failed to initialize renderer");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up the star labels
|
|
|
|
for (vector<string>::const_iterator iter = config->labelledStars.begin();
|
|
|
|
iter != config->labelledStars.end();
|
|
|
|
iter++)
|
|
|
|
{
|
2002-01-07 15:48:32 -07:00
|
|
|
Star* star = universe->getStarCatalog()->find(*iter);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (star != NULL)
|
|
|
|
renderer->addLabelledStar(star);
|
|
|
|
}
|
|
|
|
|
2002-09-22 08:46:50 -06:00
|
|
|
if((renderer->getRenderFlags() & Renderer::ShowAutoMag) != 0)
|
2002-12-11 13:33:23 -07:00
|
|
|
{
|
|
|
|
renderer->setFaintestAM45deg(renderer->getFaintestAM45deg());
|
2002-09-22 08:46:50 -06:00
|
|
|
setFaintestAutoMag();
|
2002-12-11 13:33:23 -07:00
|
|
|
}
|
2002-09-22 08:46:50 -06:00
|
|
|
else
|
|
|
|
{
|
2001-11-27 18:50:04 -07:00
|
|
|
renderer->setBrightnessBias(0.1f);
|
|
|
|
renderer->setSaturationMagnitude(1.0f);
|
2002-09-22 08:46:50 -06:00
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
if (config->mainFont == "")
|
|
|
|
font = LoadTextureFont("fonts/default.txf");
|
|
|
|
else
|
2002-03-28 11:55:43 -07:00
|
|
|
font = LoadTextureFont(string("fonts/") + config->mainFont);
|
2001-11-27 18:50:04 -07:00
|
|
|
if (font == NULL)
|
|
|
|
{
|
|
|
|
cout << "Error loading font; text will not be visible.\n";
|
|
|
|
}
|
|
|
|
font->buildTexture();
|
|
|
|
|
|
|
|
if (config->titleFont != "")
|
|
|
|
titleFont = LoadTextureFont(string("fonts") + "/" + config->titleFont);
|
|
|
|
if (titleFont != NULL)
|
|
|
|
titleFont->buildTexture();
|
|
|
|
else
|
|
|
|
titleFont = font;
|
|
|
|
|
|
|
|
// Set up the overlay
|
|
|
|
overlay = new Overlay();
|
|
|
|
overlay->setWindowSize(width, height);
|
|
|
|
|
|
|
|
if (config->labelFont == "")
|
|
|
|
{
|
|
|
|
renderer->setFont(font);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TextureFont* labelFont = LoadTextureFont(string("fonts") + "/" + config->labelFont);
|
|
|
|
if (labelFont == NULL)
|
|
|
|
{
|
|
|
|
renderer->setFont(font);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
labelFont->buildTexture();
|
|
|
|
renderer->setFont(labelFont);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->logoTextureFile != "")
|
|
|
|
{
|
|
|
|
logoTexture = LoadTextureFromFile(string("textures") + "/" + config->logoTextureFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CelestiaCore::readStars(const CelestiaConfig& cfg)
|
|
|
|
{
|
|
|
|
ifstream starFile(cfg.starDatabaseFile.c_str(), ios::in | ios::binary);
|
|
|
|
if (!starFile.good())
|
|
|
|
{
|
|
|
|
cerr << "Error opening " << cfg.starDatabaseFile << '\n';
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ifstream starNamesFile(cfg.starNamesFile.c_str(), ios::in);
|
|
|
|
if (!starNamesFile.good())
|
|
|
|
{
|
|
|
|
cerr << "Error opening " << cfg.starNamesFile << '\n';
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-05-08 02:02:57 -06:00
|
|
|
StarNameDatabase* starNameDB = StarNameDatabase::readNames(starNamesFile);
|
|
|
|
if (starNameDB == NULL)
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-05-08 02:02:57 -06:00
|
|
|
cerr << "Error reading star names file\n";
|
2001-11-27 18:50:04 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-05-08 02:02:57 -06:00
|
|
|
// StarDatabase* starDB = StarDatabase::read(starFile);
|
|
|
|
StarDatabase* starDB = new StarDatabase();
|
|
|
|
if (!starDB->loadBinary(starFile))
|
2001-11-27 18:50:04 -07:00
|
|
|
{
|
2002-05-08 02:02:57 -06:00
|
|
|
delete starDB;
|
|
|
|
cerr << "Error reading stars file\n";
|
2001-11-27 18:50:04 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2003-05-05 00:27:41 -06:00
|
|
|
starDB->setNameDatabase(starNameDB);
|
|
|
|
|
2002-11-16 16:31:31 -07:00
|
|
|
// Now, read supplemental star files from the extras directories
|
|
|
|
for (vector<string>::const_iterator iter = config->extrasDirs.begin();
|
|
|
|
iter != config->extrasDirs.end(); iter++)
|
2002-05-08 02:02:57 -06:00
|
|
|
{
|
2002-11-16 16:31:31 -07:00
|
|
|
if (*iter != "")
|
2002-05-08 02:02:57 -06:00
|
|
|
{
|
2002-11-16 16:31:31 -07:00
|
|
|
Directory* dir = OpenDirectory(*iter);
|
|
|
|
|
2003-03-02 12:06:58 -07:00
|
|
|
StarLoader loader(starDB);
|
|
|
|
loader.pushDir(*iter);
|
|
|
|
dir->enumFiles(loader, true);
|
|
|
|
|
|
|
|
delete dir;
|
2002-05-08 02:02:57 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
starDB->finish();
|
|
|
|
|
2002-01-07 15:48:32 -07:00
|
|
|
universe->setStarCatalog(starDB);
|
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Set the faintest visible star magnitude; adjust the renderer's
|
|
|
|
// brightness parameters appropriately.
|
|
|
|
void CelestiaCore::setFaintest(float magnitude)
|
|
|
|
{
|
2002-12-11 13:33:23 -07:00
|
|
|
renderer->setBrightnessBias(0.1f);
|
2001-11-27 18:50:04 -07:00
|
|
|
renderer->setSaturationMagnitude(1.0f);
|
|
|
|
sim->setFaintestVisible(magnitude);
|
|
|
|
}
|
|
|
|
|
2002-09-22 08:46:50 -06:00
|
|
|
// Set faintest visible star magnitude and saturation magnitude
|
|
|
|
// for a given field of view;
|
|
|
|
// adjust the renderer's brightness parameters appropriately.
|
|
|
|
void CelestiaCore::setFaintestAutoMag()
|
|
|
|
{
|
|
|
|
float faintestMag;
|
2002-12-11 13:33:23 -07:00
|
|
|
renderer->setBrightnessBias(0.1f);
|
2002-09-22 08:46:50 -06:00
|
|
|
renderer->autoMag(faintestMag);
|
|
|
|
sim->setFaintestVisible(faintestMag);
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
void CelestiaCore::fatalError(const string& msg)
|
|
|
|
{
|
|
|
|
if (alerter == NULL)
|
|
|
|
cout << msg;
|
|
|
|
else
|
|
|
|
alerter->fatalError(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::setAlerter(Alerter* a)
|
|
|
|
{
|
|
|
|
alerter = a;
|
|
|
|
}
|
|
|
|
|
2003-05-04 21:24:43 -06:00
|
|
|
CelestiaCore::Alerter* CelestiaCore::getAlerter() const
|
|
|
|
{
|
|
|
|
return alerter;
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
|
|
|
int CelestiaCore::getTimeZoneBias() const
|
|
|
|
{
|
|
|
|
return timeZoneBias;
|
|
|
|
}
|
|
|
|
|
2003-05-01 10:36:09 -06:00
|
|
|
bool CelestiaCore::getLightDelayActive() const
|
|
|
|
{
|
|
|
|
return lightTravelFlag;
|
|
|
|
}
|
|
|
|
|
2003-06-03 14:11:09 -06:00
|
|
|
void CelestiaCore::setLightDelayActive(bool lightDelayActive )
|
2003-05-01 10:36:09 -06:00
|
|
|
{
|
|
|
|
lightTravelFlag = lightDelayActive ;
|
|
|
|
}
|
2001-11-27 18:50:04 -07:00
|
|
|
|
2002-01-03 15:09:15 -07:00
|
|
|
int CelestiaCore::getTextEnterMode() const
|
|
|
|
{
|
|
|
|
return textEnterMode;
|
|
|
|
}
|
|
|
|
|
2003-06-03 14:11:09 -06:00
|
|
|
void CelestiaCore::setScreenDpi(int dpi)
|
|
|
|
{
|
|
|
|
screenDpi = dpi;
|
|
|
|
setFOVFromZoom();
|
|
|
|
}
|
|
|
|
|
|
|
|
int CelestiaCore::getScreenDpi() const
|
|
|
|
{
|
|
|
|
return screenDpi;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::setDistanceToScreen(int dts)
|
|
|
|
{
|
|
|
|
distanceToScreen = dts;
|
|
|
|
setFOVFromZoom();
|
|
|
|
}
|
|
|
|
|
|
|
|
int CelestiaCore::getDistanceToScreen() const
|
|
|
|
{
|
|
|
|
return distanceToScreen;
|
|
|
|
}
|
2002-01-03 15:09:15 -07:00
|
|
|
|
2001-11-27 18:50:04 -07:00
|
|
|
void CelestiaCore::setTimeZoneBias(int bias)
|
|
|
|
{
|
|
|
|
timeZoneBias = bias;
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(TimeZoneChanged);
|
2001-11-27 18:50:04 -07:00
|
|
|
}
|
|
|
|
|
2002-01-03 15:09:15 -07:00
|
|
|
|
2002-01-04 17:35:40 -07:00
|
|
|
string CelestiaCore::getTimeZoneName() const
|
2002-01-03 15:09:15 -07:00
|
|
|
{
|
2002-01-04 17:35:40 -07:00
|
|
|
return timeZoneName;
|
2002-01-03 15:09:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-04 17:35:40 -07:00
|
|
|
void CelestiaCore::setTimeZoneName(const string& zone)
|
2002-01-03 15:09:15 -07:00
|
|
|
{
|
2002-01-04 17:35:40 -07:00
|
|
|
timeZoneName = zone;
|
2002-01-03 15:09:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-07 19:53:08 -07:00
|
|
|
int CelestiaCore::getHudDetail()
|
|
|
|
{
|
|
|
|
return hudDetail;
|
|
|
|
}
|
2001-12-10 21:20:05 -07:00
|
|
|
|
2002-01-11 19:08:09 -07:00
|
|
|
void CelestiaCore::setHudDetail(int newHudDetail)
|
|
|
|
{
|
2002-04-02 03:14:59 -07:00
|
|
|
hudDetail = newHudDetail%3;
|
2002-06-04 23:27:53 -06:00
|
|
|
notifyWatchers(VerbosityLevelChanged);
|
2002-01-11 19:08:09 -07:00
|
|
|
}
|
|
|
|
|
2001-12-10 21:20:05 -07:00
|
|
|
|
|
|
|
void CelestiaCore::initMovieCapture(MovieCapture* mc)
|
|
|
|
{
|
|
|
|
if (movieCapture == NULL)
|
|
|
|
movieCapture = mc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::recordBegin()
|
|
|
|
{
|
|
|
|
if (movieCapture != NULL)
|
|
|
|
recording = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::recordPause()
|
|
|
|
{
|
|
|
|
recording = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::recordEnd()
|
|
|
|
{
|
|
|
|
if (movieCapture != NULL)
|
|
|
|
{
|
2001-12-11 17:11:19 -07:00
|
|
|
recordPause();
|
2001-12-10 21:20:05 -07:00
|
|
|
movieCapture->end();
|
|
|
|
delete movieCapture;
|
|
|
|
movieCapture = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CelestiaCore::isCaptureActive()
|
|
|
|
{
|
|
|
|
return movieCapture != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CelestiaCore::isRecording()
|
|
|
|
{
|
|
|
|
return recording;
|
|
|
|
}
|
2002-03-26 21:41:23 -07:00
|
|
|
|
2002-09-22 03:24:45 -06:00
|
|
|
void CelestiaCore::flash(const std::string& s, double duration)
|
|
|
|
{
|
|
|
|
if (hudDetail > 0)
|
|
|
|
showText(s, -1, -1, 0, 5, duration);
|
|
|
|
}
|
|
|
|
|
2002-06-04 23:27:53 -06:00
|
|
|
|
2002-03-26 21:41:23 -07:00
|
|
|
void CelestiaCore::addWatcher(CelestiaWatcher* watcher)
|
|
|
|
{
|
|
|
|
assert(watcher != NULL);
|
|
|
|
watchers.insert(watchers.end(), watcher);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::removeWatcher(CelestiaWatcher* watcher)
|
|
|
|
{
|
|
|
|
vector<CelestiaWatcher*>::iterator iter =
|
|
|
|
find(watchers.begin(), watchers.end(), watcher);
|
|
|
|
if (iter != watchers.end())
|
|
|
|
watchers.erase(iter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::notifyWatchers(int property)
|
|
|
|
{
|
|
|
|
for (vector<CelestiaWatcher*>::iterator iter = watchers.begin();
|
|
|
|
iter != watchers.end(); iter++)
|
|
|
|
{
|
2002-06-04 23:27:53 -06:00
|
|
|
(*iter)->notifyChange(this, property);
|
2002-03-26 21:41:23 -07:00
|
|
|
}
|
|
|
|
}
|
2002-11-07 22:08:34 -07:00
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::goToUrl(const std::string& urlStr)
|
|
|
|
{
|
|
|
|
Url url(urlStr, this);
|
|
|
|
url.goTo();
|
|
|
|
notifyWatchers(RenderFlagsChanged|LabelFlagsChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::addToHistory()
|
|
|
|
{
|
|
|
|
Url url(this);
|
|
|
|
if (!history.empty() && historyCurrent < history.size() - 1)
|
|
|
|
{
|
|
|
|
// truncating history to current position
|
2002-11-16 16:31:31 -07:00
|
|
|
while (historyCurrent != history.size() - 1)
|
2002-11-07 22:08:34 -07:00
|
|
|
{
|
|
|
|
history.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
history.push_back(url);
|
|
|
|
historyCurrent = history.size();
|
|
|
|
notifyWatchers(HistoryChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::back()
|
|
|
|
{
|
|
|
|
if (historyCurrent == 0) return;
|
|
|
|
if (historyCurrent == history.size())
|
|
|
|
{
|
|
|
|
addToHistory();
|
|
|
|
historyCurrent = history.size()-1;
|
|
|
|
}
|
|
|
|
historyCurrent--;
|
|
|
|
history[historyCurrent].goTo();
|
|
|
|
notifyWatchers(HistoryChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CelestiaCore::forward()
|
|
|
|
{
|
|
|
|
if (historyCurrent == history.size()-1) return;
|
|
|
|
historyCurrent++;
|
|
|
|
history[historyCurrent].goTo();
|
|
|
|
notifyWatchers(HistoryChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const std::vector<Url>& CelestiaCore::getHistory() const
|
|
|
|
{
|
|
|
|
return history;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<Url>::size_type CelestiaCore::getHistoryCurrent() const
|
|
|
|
{
|
|
|
|
return historyCurrent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CelestiaCore::setHistoryCurrent(std::vector<Url>::size_type curr)
|
|
|
|
{
|
|
|
|
if (curr >= history.size()) return;
|
|
|
|
if (historyCurrent == history.size()) {
|
|
|
|
addToHistory();
|
|
|
|
}
|
|
|
|
historyCurrent = curr;
|
|
|
|
history[curr].goTo();
|
|
|
|
notifyWatchers(HistoryChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
|