00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015 #include <algorithm>
00016 #include <set>
00017 #include <cstdlib>
00018 #include <cctype>
00019 #include <cstring>
00020 #include <cassert>
00021 #include <process.h>
00022 #include <time.h>
00023 #include <windows.h>
00024 #include <commctrl.h>
00025 #include <mmsystem.h>
00026
00027 #include <celmath/vecmath.h>
00028 #include <celmath/quaternion.h>
00029 #include <celmath/mathlib.h>
00030 #include <celutil/debug.h>
00031 #include <celutil/util.h>
00032 #include <celutil/winutil.h>
00033 #include <celutil/filetype.h>
00034 #include <celengine/celestia.h>
00035 #include <celengine/astro.h>
00036 #include <celengine/cmdparser.h>
00037
00038 #include "../celengine/gl.h"
00039 #include "../celengine/glext.h"
00040 #include "celestiacore.h"
00041 #include "imagecapture.h"
00042 #include "avicapture.h"
00043 #include "url.h"
00044 #include "winstarbrowser.h"
00045 #include "winssbrowser.h"
00046 #include "wintourguide.h"
00047 #include "wingotodlg.h"
00048 #include "winviewoptsdlg.h"
00049 #include "winlocations.h"
00050 #include "winbookmarks.h"
00051 #include "wineclipses.h"
00052 #include "winhyperlinks.h"
00053 #include "wintime.h"
00054 #include "winsplash.h"
00055 #include "odmenu.h"
00056
00057 #include "res/resource.h"
00058 #include "wglext.h"
00059
00060 using namespace std;
00061
00062 typedef pair<int,string> IntStrPair;
00063 typedef vector<IntStrPair> IntStrPairVec;
00064
00065 char AppName[] = "Celestia";
00066
00067 static CelestiaCore* appCore = NULL;
00068
00069 static vector<DEVMODE>* displayModes = NULL;
00070 static int currentScreenMode = 0;
00071 static int newScreenMode = 0;
00072 static int lastFullScreenMode = 0;
00073 static RECT windowRect;
00074
00075 static HGLRC glContext;
00076 static HDC deviceContext;
00077
00078 static bool bReady = false;
00079
00080 static LPTSTR CelestiaRegKey = "Software\\Shatters.net\\Celestia";
00081
00082 HINSTANCE appInstance;
00083 HWND mainWindow = 0;
00084
00085 static SolarSystemBrowser* solarSystemBrowser = NULL;
00086 static StarBrowser* starBrowser = NULL;
00087 static TourGuide* tourGuide = NULL;
00088 static GotoObjectDialog* gotoObjectDlg = NULL;
00089 static ViewOptionsDialog* viewOptionsDlg = NULL;
00090 static EclipseFinderDialog* eclipseFinder = NULL;
00091 static LocationsDialog* locationsDlg = NULL;
00092
00093 static HMENU menuBar = 0;
00094 ODMenu odAppMenu;
00095 static HACCEL acceleratorTable = 0;
00096 static bool hideMenuBar = false;
00097
00098
00099 static bool useJoystick = false;
00100 static bool joystickAvailable = false;
00101 static JOYCAPS joystickCaps;
00102
00103 static HCURSOR hDefaultCursor = 0;
00104 bool cursorVisible = true;
00105 static POINT saveCursorPos;
00106 class WinCursorHandler;
00107 WinCursorHandler* cursorHandler = NULL;
00108
00109 static int MovieSizes[5][2] = { { 160, 120 },
00110 { 320, 240 },
00111 { 640, 480 },
00112 { 720, 480 },
00113 { 720, 576 } };
00114 static float MovieFramerates[5] = { 15.0f, 24.0f, 25.0f, 29.97f, 30.0f };
00115
00116 static int movieSize = 1;
00117 static int movieFramerate = 1;
00118
00119
00120 astro::Date newTime(0.0);
00121
00122 #define INFINITE_MOUSE
00123 static int lastX = 0;
00124 static int lastY = 0;
00125 static bool ignoreNextMoveEvent = false;
00126
00127 static const WPARAM ID_GOTO_URL = 62000;
00128
00129 HWND hBookmarkTree;
00130 char bookmarkName[33];
00131
00132 static LRESULT CALLBACK MainWindowProc(HWND hWnd,
00133 UINT uMsg,
00134 WPARAM wParam, LPARAM lParam);
00135
00136
00137 #define MENU_CHOOSE_PLANET 32000
00138 #define MENU_CHOOSE_SURFACE 31000
00139
00140
00141 struct AppPreferences
00142 {
00143 int winWidth;
00144 int winHeight;
00145 int winX;
00146 int winY;
00147 int renderFlags;
00148 int labelMode;
00149 int orbitMask;
00150 float visualMagnitude;
00151 float ambientLight;
00152 int showLocalTime;
00153 int hudDetail;
00154 int fullScreenMode;
00155 uint32 lastVersion;
00156 string altSurfaceName;
00157 uint32 textureResolution;
00158 Renderer::StarStyle starStyle;
00159 GLContext::GLRenderPath renderPath;
00160 bool renderPathSet;
00161 };
00162
00163 void ChangeDisplayMode()
00164 {
00165 DEVMODE device_mode;
00166
00167 memset(&device_mode, 0, sizeof(DEVMODE));
00168
00169 device_mode.dmSize = sizeof(DEVMODE);
00170
00171 device_mode.dmPelsWidth = 800;
00172 device_mode.dmPelsHeight = 600;
00173 device_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
00174
00175 ChangeDisplaySettings(&device_mode, CDS_FULLSCREEN);
00176 }
00177
00178 void RestoreDisplayMode()
00179 {
00180 ChangeDisplaySettings(0, 0);
00181 }
00182
00183
00184
00185
00186
00187 class CelestiaDropTarget : public IDropTarget
00188 {
00189 public:
00190 CelestiaDropTarget();
00191 ~CelestiaDropTarget();
00192
00193 STDMETHOD (QueryInterface)(REFIID idd, void** ppvObject);
00194 STDMETHOD_ (ULONG, AddRef) (void);
00195 STDMETHOD_ (ULONG, Release) (void);
00196
00197
00198 STDMETHOD (DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
00199 STDMETHOD (DragOver) (DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
00200 STDMETHOD (DragLeave)(void);
00201 STDMETHOD (Drop) (LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
00202
00203 private:
00204 ULONG refCount;
00205 };
00206
00207 static CelestiaDropTarget* dropTarget = NULL;
00208
00209 CelestiaDropTarget::CelestiaDropTarget() :
00210 refCount(0)
00211 {
00212 }
00213
00214 CelestiaDropTarget::~CelestiaDropTarget()
00215 {
00216 }
00217
00218 HRESULT CelestiaDropTarget::QueryInterface(REFIID iid, void** ppvObject)
00219 {
00220 if (iid == IID_IUnknown || iid == IID_IDropTarget)
00221 {
00222 *ppvObject = this;
00223 AddRef();
00224 return ResultFromScode(S_OK);
00225 }
00226 else
00227 {
00228 *ppvObject = NULL;
00229 return ResultFromScode(E_NOINTERFACE);
00230 }
00231 }
00232
00233 ULONG CelestiaDropTarget::AddRef(void)
00234 {
00235 return ++refCount;
00236 }
00237
00238 ULONG CelestiaDropTarget::Release(void)
00239 {
00240 if (--refCount == 0)
00241 {
00242 delete this;
00243 return 0;
00244 }
00245
00246 return refCount;
00247 }
00248
00249 STDMETHODIMP
00250 CelestiaDropTarget::DragEnter(IDataObject* pDataObject,
00251 DWORD grfKeyState,
00252 POINTL pt,
00253 DWORD* pdwEffect)
00254 {
00255 return S_OK;
00256 }
00257
00258 STDMETHODIMP
00259 CelestiaDropTarget::DragOver(DWORD grfKeyState,
00260 POINTL pt,
00261 DWORD* pdwEffect)
00262 {
00263 return S_OK;
00264 }
00265
00266 STDMETHODIMP
00267 CelestiaDropTarget::DragLeave(void)
00268 {
00269 return S_OK;
00270 }
00271
00272
00273 STDMETHODIMP
00274 CelestiaDropTarget::Drop(IDataObject* pDataObject,
00275 DWORD grfKeyState,
00276 POINTL pt,
00277 DWORD* pdwEffect)
00278 {
00279
00280 IEnumFORMATETC* enumFormat = NULL;
00281 HRESULT hr = pDataObject->EnumFormatEtc(DATADIR_GET, &enumFormat);
00282 if (FAILED(hr) || enumFormat == NULL)
00283 return E_FAIL;
00284
00285 FORMATETC format;
00286 ULONG nFetched;
00287 while (enumFormat->Next(1, &format, &nFetched) == S_OK)
00288 {
00289 char buf[512];
00290 if (GetClipboardFormatName(format.cfFormat, buf, 511) != 0 &&
00291 !strcmp(buf, "UniformResourceLocator"))
00292 {
00293 STGMEDIUM medium;
00294 if (pDataObject->GetData(&format, &medium) == S_OK)
00295 {
00296 if (medium.tymed == TYMED_HGLOBAL && medium.hGlobal != 0)
00297 {
00298 char* s = (char*) GlobalLock(medium.hGlobal);
00299 Url url(s, appCore);
00300 GlobalUnlock(medium.hGlobal);
00301 url.goTo();
00302 break;
00303 }
00304 }
00305 }
00306 }
00307
00308 enumFormat->Release();
00309
00310 return E_FAIL;
00311 }
00312
00313
00314
00315
00316
00317 class WinCursorHandler : public CelestiaCore::CursorHandler
00318 {
00319 public:
00320 WinCursorHandler(HCURSOR _defaultCursor);
00321 virtual ~WinCursorHandler();
00322 virtual void setCursorShape(CelestiaCore::CursorShape);
00323 virtual CelestiaCore::CursorShape getCursorShape() const;
00324
00325 private:
00326 CelestiaCore::CursorShape shape;
00327 HCURSOR defaultCursor;
00328 HCURSOR sizeVertical;
00329 HCURSOR sizeHorizontal;
00330 };
00331
00332
00333 WinCursorHandler::WinCursorHandler(HCURSOR _defaultCursor) :
00334 shape(CelestiaCore::ArrowCursor),
00335 defaultCursor(_defaultCursor)
00336 {
00337 sizeVertical = LoadCursor(NULL, IDC_SIZENS);
00338 sizeHorizontal = LoadCursor(NULL, IDC_SIZEWE);
00339 }
00340
00341
00342 WinCursorHandler::~WinCursorHandler()
00343 {
00344 }
00345
00346
00347 void WinCursorHandler::setCursorShape(CelestiaCore::CursorShape _shape)
00348 {
00349 shape = _shape;
00350 switch (shape)
00351 {
00352 case CelestiaCore::SizeVerCursor:
00353 SetCursor(sizeVertical);
00354 break;
00355 case CelestiaCore::SizeHorCursor:
00356 SetCursor(sizeHorizontal);
00357 break;
00358 default:
00359 SetCursor(defaultCursor);
00360 break;
00361 }
00362 }
00363
00364
00365 CelestiaCore::CursorShape WinCursorHandler::getCursorShape() const
00366 {
00367 return shape;
00368 }
00369
00370
00371
00372 static void ShowUniversalTime(CelestiaCore* appCore)
00373 {
00374 appCore->setTimeZoneBias(0);
00375 appCore->setTimeZoneName("UTC");
00376 }
00377
00378
00379 static void ShowLocalTime(CelestiaCore* appCore)
00380 {
00381 TIME_ZONE_INFORMATION tzi;
00382 DWORD dst = GetTimeZoneInformation(&tzi);
00383 if (dst != TIME_ZONE_ID_INVALID)
00384 {
00385 LONG dstBias = 0;
00386 WCHAR* tzName = NULL;
00387
00388 if (dst == TIME_ZONE_ID_STANDARD)
00389 {
00390 dstBias = tzi.StandardBias;
00391 tzName = tzi.StandardName;
00392 }
00393 else if (dst == TIME_ZONE_ID_DAYLIGHT)
00394 {
00395 dstBias = tzi.DaylightBias;
00396 tzName = tzi.DaylightName;
00397 }
00398
00399 appCore->setTimeZoneName(" ");
00400 appCore->setTimeZoneBias((tzi.Bias + dstBias) * -60);
00401 }
00402 }
00403
00404
00405 static bool BeginMovieCapture(const std::string& filename,
00406 int width, int height,
00407 float framerate)
00408 {
00409 MovieCapture* movieCapture = new AVICapture();
00410
00411 bool success = movieCapture->start(filename, width, height, framerate);
00412 if (success)
00413 appCore->initMovieCapture(movieCapture);
00414 else
00415 delete movieCapture;
00416
00417 return success;
00418 }
00419
00420
00421 static bool CopyStateURLToClipboard()
00422 {
00423 BOOL b;
00424 b = OpenClipboard(mainWindow);
00425 if (!b)
00426 return false;
00427
00428 Url url(appCore);
00429 string urlString = url.getAsString();
00430
00431 char* s = const_cast<char*>(urlString.c_str());
00432 HGLOBAL clipboardDataHandle = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
00433 strlen(s) + 1);
00434 char* clipboardData = (char*) GlobalLock(clipboardDataHandle);
00435 if (clipboardData != NULL)
00436 {
00437 strcpy(clipboardData, s);
00438 GlobalUnlock(clipboardDataHandle);
00439 EmptyClipboard();
00440 HANDLE h = SetClipboardData(CF_TEXT, clipboardDataHandle);
00441 CloseClipboard();
00442 return h != NULL;
00443 }
00444 else
00445 {
00446 CloseClipboard();
00447 return false;
00448 }
00449 }
00450
00451
00452 static bool ToggleMenuItem(HMENU menu, int id)
00453 {
00454 MENUITEMINFO menuInfo;
00455 menuInfo.cbSize = sizeof(MENUITEMINFO);
00456 menuInfo.fMask = MIIM_STATE;
00457 if (GetMenuItemInfo(menu, id, FALSE, &menuInfo))
00458 {
00459 bool isChecked = ((menuInfo.fState & MFS_CHECKED) != 0);
00460 CheckMenuItem(menu, id, isChecked ? MF_UNCHECKED : MF_CHECKED);
00461 return !isChecked;
00462 }
00463 return false;
00464 }
00465
00466 bool LoadItemTextFromFile(HWND hWnd,
00467 int item,
00468 char* filename)
00469 {
00470
00471 ifstream textFile(filename, ios::in);
00472 string s;
00473
00474 if (!textFile.good())
00475 {
00476 SetDlgItemText(hWnd, item, "License file missing!\r\r\nSee http://www.gnu.org/copyleft/gpl.html");
00477 return true;
00478 }
00479
00480 char c;
00481 while (textFile.get(c))
00482 {
00483 if (c == '\n')
00484 s += "\r\r\n";
00485 else
00486 s += c;
00487 }
00488
00489 SetDlgItemText(hWnd, item, s.c_str());
00490
00491 return true;
00492 }
00493
00494
00495 BOOL APIENTRY AboutProc(HWND hDlg,
00496 UINT message,
00497 UINT wParam,
00498 LONG lParam)
00499 {
00500 switch (message)
00501 {
00502 case WM_INITDIALOG:
00503 MakeHyperlinkFromStaticCtrl(hDlg, IDC_CELESTIALINK);
00504 return(TRUE);
00505
00506 case WM_COMMAND:
00507 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
00508 {
00509 EndDialog(hDlg, 0);
00510 return TRUE;
00511 }
00512 else if (LOWORD(wParam) == IDC_CELESTIALINK)
00513 {
00514 char urlBuf[256];
00515 HWND hCtrl = GetDlgItem(hDlg, IDC_CELESTIALINK);
00516 if (hCtrl)
00517 {
00518 if (GetWindowText(hCtrl, urlBuf, sizeof(urlBuf)) > 0)
00519 {
00520 ShellExecute(hDlg, "open", urlBuf, NULL, NULL, SW_SHOWNORMAL);
00521 return TRUE;
00522 }
00523 }
00524 }
00525 break;
00526 }
00527
00528 return FALSE;
00529 }
00530
00531
00532 BOOL APIENTRY ControlsHelpProc(HWND hDlg,
00533 UINT message,
00534 UINT wParam,
00535 LONG lParam)
00536 {
00537 switch (message)
00538 {
00539 case WM_INITDIALOG:
00540 LoadItemTextFromFile(hDlg, IDC_TEXT_CONTROLSHELP, "controls.txt");
00541 return(TRUE);
00542
00543 case WM_COMMAND:
00544 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
00545 {
00546 EndDialog(hDlg, 0);
00547 return TRUE;
00548 }
00549 break;
00550 }
00551
00552 return FALSE;
00553 }
00554
00555
00556 BOOL APIENTRY LicenseProc(HWND hDlg,
00557 UINT message,
00558 UINT wParam,
00559 LONG lParam)
00560 {
00561 switch (message)
00562 {
00563 case WM_INITDIALOG:
00564 LoadItemTextFromFile(hDlg, IDC_LICENSE_TEXT, "COPYING");
00565 return(TRUE);
00566
00567 case WM_COMMAND:
00568 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
00569 {
00570 EndDialog(hDlg, 0);
00571 return TRUE;
00572 }
00573 break;
00574 }
00575
00576 return FALSE;
00577 }
00578
00579
00580 BOOL APIENTRY GLInfoProc(HWND hDlg,
00581 UINT message,
00582 UINT wParam,
00583 LONG lParam)
00584 {
00585 switch (message)
00586 {
00587 case WM_INITDIALOG:
00588 {
00589 char* vendor = (char*) glGetString(GL_VENDOR);
00590 char* render = (char*) glGetString(GL_RENDERER);
00591 char* version = (char*) glGetString(GL_VERSION);
00592 char* ext = (char*) glGetString(GL_EXTENSIONS);
00593 string s;
00594 s += "Vendor: ";
00595 if (vendor != NULL)
00596 s += vendor;
00597 s += "\r\r\n";
00598
00599 s += "Renderer: ";
00600 if (render != NULL)
00601 s += render;
00602 s += "\r\r\n";
00603
00604 s += "Version: ";
00605 if (version != NULL)
00606 s += version;
00607 s += "\r\r\n";
00608
00609 char buf[100];
00610 GLint simTextures = 1;
00611 if (ExtensionSupported("GL_ARB_multitexture"))
00612 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &simTextures);
00613 sprintf(buf, "Max simultaneous textures: %d\r\r\n",
00614 simTextures);
00615 s += buf;
00616
00617 GLint maxTextureSize = 0;
00618 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
00619 sprintf(buf, "Max texture size: %d\r\r\n",
00620 maxTextureSize);
00621 s += buf;
00622
00623 GLfloat pointSizeRange[2];
00624 glGetFloatv(GL_POINT_SIZE_RANGE, pointSizeRange);
00625 sprintf(buf, "Point size range: %f - %f\r\r\n",
00626 pointSizeRange[0], pointSizeRange[1]);
00627 s += buf;
00628
00629 s += "\r\r\nSupported Extensions:\r\r\n";
00630 if (ext != NULL)
00631 {
00632 string extString(ext);
00633 int pos = extString.find(' ', 0);
00634 while (pos != string::npos)
00635 {
00636 extString.replace(pos, 1, "\r\r\n");
00637 pos = extString.find(' ', pos);
00638 }
00639 s += extString;
00640 }
00641
00642 SetDlgItemText(hDlg, IDC_GLINFO_TEXT, s.c_str());
00643 }
00644 return(TRUE);
00645
00646 case WM_COMMAND:
00647 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
00648 {
00649 EndDialog(hDlg, 0);
00650 return TRUE;
00651 }
00652 break;
00653 }
00654
00655 return FALSE;
00656 }
00657
00658
00659 UINT CALLBACK ChooseMovieParamsProc(HWND hDlg, UINT message,
00660 WPARAM wParam, LPARAM lParam)
00661 {
00662 switch (message)
00663 {
00664 case WM_INITDIALOG:
00665 {
00666 char buf[100];
00667 HWND hwnd = GetDlgItem(hDlg, IDC_COMBO_MOVIE_SIZE);
00668 int nSizes = sizeof MovieSizes / sizeof MovieSizes[0];
00669
00670 int i;
00671 for (i = 0; i < nSizes; i++)
00672 {
00673 sprintf(buf, "%d x %d", MovieSizes[i][0], MovieSizes[i][1]);
00674 SendMessage(hwnd, CB_INSERTSTRING, -1,
00675 reinterpret_cast<LPARAM>(buf));
00676
00677 }
00678 SendMessage(hwnd, CB_SETCURSEL, movieSize, 0);
00679
00680 hwnd = GetDlgItem(hDlg, IDC_COMBO_MOVIE_FRAMERATE);
00681 int nFramerates = sizeof MovieFramerates / sizeof MovieFramerates[0];
00682 for (i = 0; i < nFramerates; i++)
00683 {
00684 sprintf(buf, "%.2f", MovieFramerates[i]);
00685 SendMessage(hwnd, CB_INSERTSTRING, -1,
00686 reinterpret_cast<LPARAM>(buf));
00687 }
00688 SendMessage(hwnd, CB_SETCURSEL, movieFramerate, 0);
00689 }
00690 return TRUE;
00691
00692 case WM_COMMAND:
00693 if (LOWORD(wParam) == IDC_COMBO_MOVIE_SIZE)
00694 {
00695 if (HIWORD(wParam) == CBN_SELCHANGE)
00696 {
00697 HWND hwnd = reinterpret_cast<HWND>(lParam);
00698 int item = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
00699 if (item != CB_ERR)
00700 movieSize = item;
00701 }
00702 return TRUE;
00703 }
00704 else if (LOWORD(wParam) == IDC_COMBO_MOVIE_FRAMERATE)
00705 {
00706 if (HIWORD(wParam) == CBN_SELCHANGE)
00707 {
00708 HWND hwnd = reinterpret_cast<HWND>(lParam);
00709 int item = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
00710 if (item != CB_ERR)
00711 movieFramerate = item;
00712 }
00713 return TRUE;
00714 }
00715 }
00716
00717 return FALSE;
00718 }
00719
00720
00721 BOOL APIENTRY FindObjectProc(HWND hDlg,
00722 UINT message,
00723 UINT wParam,
00724 LONG lParam)
00725 {
00726 switch (message)
00727 {
00728 case WM_INITDIALOG:
00729 return(TRUE);
00730
00731 case WM_COMMAND:
00732 if (LOWORD(wParam) == IDOK)
00733 {
00734 char buf[1024];
00735 int len = GetDlgItemText(hDlg, IDC_FINDOBJECT_EDIT, buf, 1024);
00736 if (len > 0)
00737 {
00738 Selection sel = appCore->getSimulation()->findObject(string(buf));
00739 if (!sel.empty())
00740 appCore->getSimulation()->setSelection(sel);
00741 }
00742 EndDialog(hDlg, 0);
00743 return TRUE;
00744 }
00745 else if (LOWORD(wParam) == IDCANCEL)
00746 {
00747 EndDialog(hDlg, 0);
00748 return FALSE;
00749 }
00750 break;
00751 }
00752
00753 return FALSE;
00754 }
00755
00756
00757 BOOL APIENTRY AddBookmarkFolderProc(HWND hDlg,
00758 UINT message,
00759 UINT wParam,
00760 LONG lParam)
00761 {
00762 switch (message)
00763 {
00764 case WM_INITDIALOG:
00765 {
00766
00767 HWND hParent = GetParent(hDlg);
00768 CenterWindow(hParent, hDlg);
00769
00770
00771 HWND hEdit = GetDlgItem(hDlg, IDC_BOOKMARKFOLDER);
00772 SendMessage(hEdit, EM_LIMITTEXT, 32, 0);
00773
00774
00775 HWND hOK = GetDlgItem(hDlg, IDOK);
00776 HWND hCancel = GetDlgItem(hDlg, IDCANCEL);
00777 EnableWindow(hOK, FALSE);
00778 RemoveButtonDefaultStyle(hOK);
00779 AddButtonDefaultStyle(hCancel);
00780 }
00781 return TRUE;
00782
00783 case WM_COMMAND:
00784 {
00785 if (HIWORD(wParam) == EN_CHANGE)
00786 {
00787 HWND hOK = GetDlgItem(hDlg, IDOK);
00788 HWND hCancel = GetDlgItem(hDlg, IDCANCEL);
00789
00790 if (hOK && hCancel)
00791 {
00792
00793 char name[33];
00794 GetWindowText((HWND)lParam, name, sizeof(name));
00795 if (name[0])
00796 {
00797
00798 RemoveButtonDefaultStyle(hCancel);
00799
00800
00801 EnableWindow(hOK, TRUE);
00802
00803
00804 AddButtonDefaultStyle(hOK);
00805 }
00806 else
00807 {
00808
00809 EnableWindow(hOK, FALSE);
00810
00811
00812 RemoveButtonDefaultStyle(hOK);
00813
00814
00815 AddButtonDefaultStyle(hCancel);
00816 }
00817 }
00818 }
00819 }
00820
00821 if (LOWORD(wParam) == IDOK)
00822 {
00823
00824 char name[33];
00825 HWND hEdit = GetDlgItem(hDlg, IDC_BOOKMARKFOLDER);
00826 if (hEdit)
00827 {
00828 if (GetWindowText(hEdit, name, sizeof(name)))
00829 {
00830
00831 AddNewBookmarkFolderInTree(hBookmarkTree, appCore, name);
00832 }
00833 }
00834
00835 EndDialog(hDlg, 0);
00836 return TRUE;
00837 }
00838 else if (LOWORD(wParam) == IDCANCEL)
00839 {
00840 EndDialog(hDlg, 0);
00841 return FALSE;
00842 }
00843 }
00844
00845 return FALSE;
00846 }
00847
00848 BOOL APIENTRY AddBookmarkProc(HWND hDlg,
00849 UINT message,
00850 UINT wParam,
00851 LONG lParam)
00852 {
00853 switch (message)
00854 {
00855 case WM_INITDIALOG:
00856 {
00857 RECT dlgRect, treeRect;
00858 HWND hCtrl;
00859 if (GetWindowRect(hDlg, &dlgRect))
00860 {
00861 if (hCtrl = GetDlgItem(hDlg, IDC_BOOKMARK_FOLDERTREE))
00862 {
00863 if (GetWindowRect(hCtrl, &treeRect))
00864 {
00865 int width = dlgRect.right - dlgRect.left;
00866 int height = treeRect.top - dlgRect.top;
00867 SetWindowPos(hDlg, HWND_TOP, 0, 0, width, height,
00868 SWP_NOMOVE | SWP_NOZORDER);
00869 }
00870
00871 HTREEITEM hParent;
00872 if (hParent = PopulateBookmarkFolders(hCtrl, appCore, appInstance))
00873 {
00874
00875 TreeView_Expand(hCtrl, hParent, TVE_EXPAND);
00876 }
00877 }
00878 }
00879
00880
00881 HWND hOK = GetDlgItem(hDlg, IDOK);
00882 HWND hCancel = GetDlgItem(hDlg, IDCANCEL);
00883 EnableWindow(hOK, FALSE);
00884 RemoveButtonDefaultStyle(hOK);
00885 AddButtonDefaultStyle(hCancel);
00886
00887
00888 if (hCtrl = GetDlgItem(hDlg, IDC_BOOKMARK_EDIT))
00889 {
00890
00891 Selection sel = appCore->getSimulation()->getSelection();
00892 switch (sel.getType())
00893 {
00894 case Selection::Type_Body:
00895 {
00896 string name = sel.body()->getName();
00897 SetWindowText(hCtrl, (char*)name.c_str());
00898 }
00899 break;
00900
00901 default:
00902 break;
00903 }
00904 }
00905
00906 return(TRUE);
00907 }
00908
00909 case WM_COMMAND:
00910 {
00911 if (HIWORD(wParam) == EN_CHANGE)
00912 {
00913 HWND hOK = GetDlgItem(hDlg, IDOK);
00914 HWND hCancel = GetDlgItem(hDlg, IDCANCEL);
00915
00916 if (hOK && hCancel)
00917 {
00918
00919 char name[33];
00920 GetWindowText((HWND)lParam, name, sizeof(name));
00921 if (name[0])
00922 {
00923
00924 RemoveButtonDefaultStyle(hCancel);
00925
00926
00927 EnableWindow(hOK, TRUE);
00928
00929
00930 AddButtonDefaultStyle(hOK);
00931 }
00932 else
00933 {
00934
00935 EnableWindow(hOK, FALSE);
00936
00937
00938 RemoveButtonDefaultStyle(hOK);
00939
00940
00941 AddButtonDefaultStyle(hCancel);
00942 }
00943 }
00944 }
00945 if (LOWORD(wParam) == IDOK)
00946 {
00947 char name[33];
00948 int len = GetDlgItemText(hDlg, IDC_BOOKMARK_EDIT, name, sizeof(name));
00949 if (len > 0)
00950 {
00951 HWND hTree;
00952 if(hTree = GetDlgItem(hDlg, IDC_BOOKMARK_FOLDERTREE))
00953 {
00954 InsertBookmarkInFavorites(hTree, name, appCore);
00955
00956 appCore->writeFavoritesFile();
00957
00958
00959 BuildFavoritesMenu(menuBar, appCore, appInstance, &odAppMenu);
00960 }
00961 }
00962 EndDialog(hDlg, 0);
00963 return TRUE;
00964 }
00965 else if (LOWORD(wParam) == IDCANCEL)
00966 {
00967 EndDialog(hDlg, 0);
00968 return FALSE;
00969 }
00970 else if (LOWORD(wParam) == IDC_BOOKMARK_CREATEIN)
00971 {
00972 HWND button;
00973 RECT dlgRect, treeRect;
00974 HWND hTree;
00975 char text[16];
00976 if (GetWindowRect(hDlg, &dlgRect))
00977 {
00978 if (hTree = GetDlgItem(hDlg, IDC_BOOKMARK_FOLDERTREE))
00979 {
00980 if (GetWindowRect(hTree, &treeRect))
00981 {
00982 if (button = GetDlgItem(hDlg, IDC_BOOKMARK_CREATEIN))
00983 {
00984 if (GetWindowText(button, text, sizeof(text)))
00985 {
00986 int width = dlgRect.right - dlgRect.left;
00987 if (strstr(text, ">>"))
00988 {
00989
00990 int height = treeRect.bottom - dlgRect.top + 12;
00991 SetWindowPos(hDlg, HWND_TOP, 0, 0, width, height,
00992 SWP_NOMOVE | SWP_NOZORDER);
00993
00994 strcpy(text + strlen(text) - 2, "<<");
00995 SetWindowText(button, text);
00996 }
00997 else
00998 {
00999
01000 int height = treeRect.top - dlgRect.top;
01001 SetWindowPos(hDlg, HWND_TOP, 0, 0, width, height,
01002 SWP_NOMOVE | SWP_NOZORDER);
01003
01004 strcpy(text + strlen(text) - 2, ">>");
01005 SetWindowText(button, text);
01006 }
01007 }
01008 }
01009 }
01010 }
01011 }
01012 }
01013 else if (LOWORD(wParam) == IDC_BOOKMARK_NEWFOLDER)
01014 {
01015 if(hBookmarkTree = GetDlgItem(hDlg, IDC_BOOKMARK_FOLDERTREE))
01016 {
01017 DialogBox(appInstance, MAKEINTRESOURCE(IDD_ADDBOOKMARK_FOLDER),
01018 hDlg, AddBookmarkFolderProc);
01019 }
01020 }
01021 break;
01022 }
01023 }
01024
01025 return FALSE;
01026 }
01027
01028 BOOL APIENTRY RenameBookmarkProc(HWND hDlg,
01029 UINT message,
01030 UINT wParam,
01031 LONG lParam)
01032 {
01033 switch (message)
01034 {
01035 case WM_INITDIALOG:
01036 {
01037
01038 HWND hParent = GetParent(hDlg);
01039 CenterWindow(hParent, hDlg);
01040
01041
01042 HWND hEdit = GetDlgItem(hDlg, IDC_NEWBOOKMARK);
01043 SendMessage(hEdit, EM_LIMITTEXT, 32, 0);
01044
01045
01046 SetWindowText(hEdit, bookmarkName);
01047
01048 return(TRUE);
01049 }
01050
01051 case WM_COMMAND:
01052 {
01053 if (HIWORD(wParam) == EN_CHANGE)
01054 {
01055 HWND hOK = GetDlgItem(hDlg, IDOK);
01056 HWND hCancel = GetDlgItem(hDlg, IDCANCEL);
01057
01058 if (hOK && hCancel)
01059 {
01060
01061 char name[33];
01062 GetWindowText((HWND)lParam, name, sizeof(name));
01063 if (name[0])
01064 {
01065
01066 RemoveButtonDefaultStyle(hCancel);
01067
01068
01069 EnableWindow(hOK, TRUE);
01070
01071
01072 AddButtonDefaultStyle(hOK);
01073 }
01074 else
01075 {
01076
01077 EnableWindow(hOK, FALSE);
01078
01079
01080 RemoveButtonDefaultStyle(hOK);
01081
01082
01083 AddButtonDefaultStyle(hCancel);
01084 }
01085 }
01086 }
01087 if (LOWORD(wParam) == IDOK)
01088 {
01089
01090 char name[33];
01091 HWND hEdit = GetDlgItem(hDlg, IDC_NEWBOOKMARK);
01092 if (hEdit)
01093 {
01094 if (GetWindowText(hEdit, name, sizeof(name)))
01095 RenameBookmarkInFavorites(hBookmarkTree, name, appCore);
01096 }
01097
01098 EndDialog(hDlg, 0);
01099 return TRUE;
01100 }
01101 else if (LOWORD(wParam) == IDCANCEL)
01102 {
01103 EndDialog(hDlg, 0);
01104 return FALSE;
01105 }
01106 }
01107 }
01108
01109 return FALSE;
01110 }
01111
01112 BOOL APIENTRY OrganizeBookmarksProc(HWND hDlg,
01113 UINT message,
01114 UINT wParam,
01115 LONG lParam)
01116 {
01117 static UINT_PTR dragDropTimer;
01118 switch (message)
01119 {
01120 case WM_INITDIALOG:
01121 {
01122 HWND hCtrl;
01123 if (hCtrl = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01124 {
01125 HTREEITEM hParent;
01126 if (hParent = PopulateBookmarksTree(hCtrl, appCore, appInstance))
01127 {
01128
01129 TreeView_Expand(hCtrl, hParent, TVE_EXPAND);
01130 }
01131 }
01132 if (hCtrl = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARKS_DELETE))
01133 EnableWindow(hCtrl, FALSE);
01134 if (hCtrl = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARKS_RENAME))
01135 EnableWindow(hCtrl, FALSE);
01136
01137 return(TRUE);
01138 }
01139
01140 case WM_COMMAND:
01141 {
01142 if (LOWORD(wParam) == IDOK)
01143 {
01144 #if 0
01145 HWND hTree;
01146 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01147 SyncTreeFoldersWithFavoriteFolders(hTree, appCore);
01148 #endif
01149
01150
01151 appCore->writeFavoritesFile();
01152
01153
01154 BuildFavoritesMenu(menuBar, appCore, appInstance, &odAppMenu);
01155
01156 EndDialog(hDlg, 0);
01157 return TRUE;
01158 }
01159 else if (LOWORD(wParam) == IDCANCEL)
01160 {
01161
01162 appCore->readFavoritesFile();
01163
01164 EndDialog(hDlg, 0);
01165 return FALSE;
01166 }
01167 else if (LOWORD(wParam) == IDC_ORGANIZE_BOOKMARKS_NEWFOLDER)
01168 {
01169 if (hBookmarkTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01170 {
01171 DialogBox(appInstance, MAKEINTRESOURCE(IDD_ADDBOOKMARK_FOLDER), hDlg, AddBookmarkFolderProc);
01172 }
01173 }
01174 else if (LOWORD(wParam) == IDC_ORGANIZE_BOOKMARKS_RENAME)
01175 {
01176 if (hBookmarkTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01177 {
01178 HTREEITEM hItem;
01179 TVITEM tvItem;
01180 if (hItem = TreeView_GetSelection(hBookmarkTree))
01181 {
01182 tvItem.hItem = hItem;
01183 tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
01184 tvItem.pszText = bookmarkName;
01185 tvItem.cchTextMax = sizeof(bookmarkName);
01186 if (TreeView_GetItem(hBookmarkTree, &tvItem))
01187 {
01188 DialogBox(appInstance,
01189 MAKEINTRESOURCE(IDD_RENAME_BOOKMARK),
01190 hDlg, RenameBookmarkProc);
01191 }
01192 }
01193 }
01194 }
01195 else if (LOWORD(wParam) == IDC_ORGANIZE_BOOKMARKS_DELETE)
01196 {
01197 HWND hTree;
01198 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01199 DeleteBookmarkFromFavorites(hTree, appCore);
01200 }
01201 break;
01202 }
01203 case WM_NOTIFY:
01204 {
01205 if (((LPNMHDR)lParam)->code == TVN_SELCHANGED)
01206 {
01207 HWND hTree;
01208 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01209 {
01210
01211 HTREEITEM hItem;
01212 if (hItem = TreeView_GetSelection(hTree))
01213 {
01214 HWND hDelete, hRename;
01215 hDelete = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARKS_DELETE);
01216 hRename = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARKS_RENAME);
01217 if (hDelete && hRename)
01218 {
01219 if (TreeView_GetParent(hTree, hItem))
01220 {
01221 EnableWindow(hDelete, TRUE);
01222 EnableWindow(hRename, TRUE);
01223 }
01224 else
01225 {
01226 EnableWindow(hDelete, FALSE);
01227 EnableWindow(hRename, FALSE);
01228 }
01229 }
01230 }
01231 }
01232 }
01233 else if(((LPNMHDR)lParam)->code == TVN_BEGINDRAG)
01234 {
01235
01236 HWND hTree;
01237 TVITEM tvItem;
01238 LPNMTREEVIEW nm = (LPNMTREEVIEW)lParam;
01239 HTREEITEM hItem = nm->itemNew.hItem;
01240
01241 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01242 {
01243 tvItem.hItem = hItem;
01244 tvItem.mask = TVIF_PARAM | TVIF_HANDLE;
01245 if (TreeView_GetItem(hTree, &tvItem))
01246 {
01247 if(tvItem.lParam != 1)
01248 {
01249
01250 dragDropTimer = SetTimer(hDlg, 1, 100, NULL);
01251 OrganizeBookmarksOnBeginDrag(hTree, (LPNMTREEVIEW)lParam);
01252 }
01253 }
01254 }
01255 }
01256 }
01257 break;
01258 case WM_MOUSEMOVE:
01259 {
01260 if(isOrganizeBookmarksDragDropActive())
01261 {
01262 HWND hTree;
01263 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01264 {
01265 OrganizeBookmarksOnMouseMove(hTree, GET_X_LPARAM(lParam),
01266 GET_Y_LPARAM(lParam));
01267 }
01268 }
01269 }
01270 break;
01271 case WM_LBUTTONUP:
01272 {
01273 if(isOrganizeBookmarksDragDropActive())
01274 {
01275 HWND hTree;
01276 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01277 {
01278
01279 KillTimer(hDlg, dragDropTimer);
01280
01281 OrganizeBookmarksOnLButtonUp(hTree);
01282 MoveBookmarkInFavorites(hTree, appCore);
01283 }
01284 }
01285 }
01286 break;
01287 case WM_TIMER:
01288 {
01289 if(isOrganizeBookmarksDragDropActive())
01290 {
01291 if(wParam == 1)
01292 {
01293
01294 HWND hTree;
01295 if (hTree = GetDlgItem(hDlg, IDC_ORGANIZE_BOOKMARK_TREE))
01296 {
01297 DragDropAutoScroll(hTree);
01298 }
01299 }
01300 }
01301 }
01302 break;
01303 }
01304
01305 return FALSE;
01306 }
01307
01308
01309 int selectedScreenMode = 0;
01310 BOOL APIENTRY SelectDisplayModeProc(HWND hDlg,
01311 UINT message,
01312 UINT wParam,
01313 LONG lParam)
01314 {
01315 switch (message)
01316 {
01317 case WM_INITDIALOG:
01318 {
01319 char buf[100];
01320 HWND hwnd = GetDlgItem(hDlg, IDC_COMBO_RESOLUTION);
01321
01322
01323 SendMessage(hwnd, CB_INSERTSTRING, -1,
01324 reinterpret_cast<LPARAM>("Windowed Mode"));
01325
01326 for (vector<DEVMODE>::const_iterator iter= displayModes->begin();
01327 iter != displayModes->end(); iter++)
01328 {
01329 sprintf(buf, "%d x %d x %d",
01330 iter->dmPelsWidth, iter->dmPelsHeight,
01331 iter->dmBitsPerPel);
01332 SendMessage(hwnd, CB_INSERTSTRING, -1,
01333 reinterpret_cast<LPARAM>(buf));
01334 }
01335 SendMessage(hwnd, CB_SETCURSEL, currentScreenMode, 0);
01336 }
01337 return TRUE;
01338
01339 case WM_COMMAND:
01340 if (LOWORD(wParam) == IDOK)
01341 {
01342 newScreenMode = selectedScreenMode;
01343 EndDialog(hDlg, 0);
01344 return TRUE;
01345 }
01346 else if (LOWORD(wParam) == IDCANCEL)
01347 {
01348 EndDialog(hDlg, 0);
01349 return TRUE;
01350 }
01351 else if (LOWORD(wParam) == IDC_COMBO_RESOLUTION)
01352 {
01353 if (HIWORD(wParam) == CBN_SELCHANGE)
01354 {
01355 HWND hwnd = reinterpret_cast<HWND>(lParam);
01356 int item = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
01357 if (item != CB_ERR)
01358 selectedScreenMode = item;
01359 }
01360 return TRUE;
01361 }
01362 }
01363
01364 return FALSE;
01365 }
01366
01367
01368 HMENU CreateMenuBar()
01369 {
01370 return LoadMenu(appInstance, MAKEINTRESOURCE(IDR_MAIN_MENU));
01371 }
01372
01373 static void setMenuItemCheck(int menuItem, bool checked)
01374 {
01375 CheckMenuItem(menuBar, menuItem, checked ? MF_CHECKED : MF_UNCHECKED);
01376 }
01377
01378 struct IntStrPairComparePredicate
01379 {
01380 IntStrPairComparePredicate() : dummy(0)
01381 {
01382 }
01383
01384 bool operator()(const IntStrPair pair1, const IntStrPair pair2) const
01385 {
01386 return (pair1.second.compare(pair2.second) < 0);
01387 }
01388
01389 int dummy;
01390 };
01391
01392 static HMENU CreatePlanetarySystemMenu(string parentName, const PlanetarySystem* psys)
01393 {
01394
01395
01396
01397
01398
01399
01400
01401 vector<IntStrPair> asteroids;
01402 vector<IntStrPair> comets;
01403 vector<IntStrPair> invisibles;
01404 vector<IntStrPair> moons;
01405 vector<IntStrPair> planets;
01406 vector<IntStrPair> spacecraft;
01407
01408
01409 vector<IntStrPairVec> objects;
01410 vector<string> menuNames;
01411
01412
01413 HMENU menu = CreatePopupMenu();
01414 for (int i = 0; i < psys->getSystemSize(); i++)
01415 {
01416 Body* body = psys->getBody(i);
01417 switch(body->getClassification())
01418 {
01419 case Body::Asteroid:
01420 asteroids.push_back(make_pair(i, body->getName()));
01421 break;
01422 case Body::Comet:
01423 comets.push_back(make_pair(i, body->getName()));
01424 break;
01425 case Body::Invisible:
01426 invisibles.push_back(make_pair(i, body->getName()));
01427 break;
01428 case Body::Moon:
01429 moons.push_back(make_pair(i, body->getName()));
01430 break;
01431 case Body::Planet:
01432 planets.push_back(make_pair(i, body->getName()));
01433 break;
01434 case Body::Spacecraft:
01435 spacecraft.push_back(make_pair(i, body->getName()));
01436 break;
01437 }
01438 }
01439
01440
01441 objects.push_back(asteroids);
01442 menuNames.push_back("Asteroids");
01443 objects.push_back(comets);
01444 menuNames.push_back("Comets");
01445 objects.push_back(invisibles);
01446 menuNames.push_back("Invisibles");
01447 objects.push_back(moons);
01448 menuNames.push_back("Moons");
01449 objects.push_back(planets);
01450 menuNames.push_back("Planets");
01451 objects.push_back(spacecraft);
01452 menuNames.push_back("Spacecraft");
01453
01454
01455 IntStrPairComparePredicate pred;
01456 vector<IntStrPairVec>::iterator obj;
01457 vector<IntStrPair>::iterator it;
01458 vector<string>::iterator menuName;
01459 HMENU hSubMenu;
01460 int numSubMenus;
01461
01462
01463 numSubMenus = 0;
01464 for (obj=objects.begin(); obj != objects.end(); obj++)
01465 {
01466 if (obj->size() > 0)
01467 numSubMenus++;
01468 }
01469
01470 menuName = menuNames.begin();
01471 for (obj=objects.begin(); obj != objects.end(); obj++)
01472 {
01473
01474 if (obj->size() > 0)
01475 {
01476
01477 if (obj->size() == 1)
01478 {
01479 it=obj->begin();
01480 AppendMenu(menu, MF_STRING, MENU_CHOOSE_PLANET + it->first, it->second.c_str());
01481 }
01482 else
01483 {
01484
01485 if (parentName != "Sol" || *menuName != "Planets")
01486 sort(obj->begin(), obj->end(), pred);
01487
01488 if (numSubMenus > 1)
01489 {
01490
01491 hSubMenu = CreatePopupMenu();
01492 for(it=obj->begin(); it != obj->end(); it++)
01493 AppendMenu(hSubMenu, MF_STRING, MENU_CHOOSE_PLANET + it->first, it->second.c_str());
01494
01495 AppendMenu(menu, MF_POPUP | MF_STRING, (DWORD)hSubMenu, menuName->c_str());
01496 }
01497 else
01498 {
01499
01500 for(it=obj->begin(); it != obj->end(); it++)
01501 AppendMenu(menu, MF_STRING, MENU_CHOOSE_PLANET + it->first, it->second.c_str());
01502 }
01503 }
01504 }
01505 menuName++;
01506 }
01507
01508 return menu;
01509 }
01510
01511
01512 static HMENU CreateAlternateSurfaceMenu(const vector<string>& surfaces)
01513 {
01514 HMENU menu = CreatePopupMenu();
01515
01516 AppendMenu(menu, MF_STRING, MENU_CHOOSE_SURFACE, "Normal");
01517 for (unsigned int i = 0; i < surfaces.size(); i++)
01518 {
01519 AppendMenu(menu, MF_STRING, MENU_CHOOSE_SURFACE + i + 1,
01520 surfaces[i].c_str());
01521 }
01522
01523 return menu;
01524 }
01525
01526
01527 VOID APIENTRY handlePopupMenu(HWND hwnd,
01528 float x, float y,
01529 const Selection& sel)
01530 {
01531 HMENU hMenu;
01532 string name;
01533
01534 hMenu = CreatePopupMenu();
01535 switch (sel.getType())
01536 {
01537 case Selection::Type_Body:
01538 {
01539 name = sel.body()->getName();
01540 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_CENTER, name.c_str());
01541 AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
01542 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_GOTO, "&Goto");
01543 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_FOLLOW, "&Follow");
01544 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_SYNCORBIT, "S&ync Orbit");
01545 AppendMenu(hMenu, MF_STRING, ID_INFO, "&Info");
01546
01547 const PlanetarySystem* satellites = sel.body()->getSatellites();
01548 if (satellites != NULL && satellites->getSystemSize() != 0)
01549 {
01550 HMENU satMenu = CreatePlanetarySystemMenu(name, satellites);
01551 AppendMenu(hMenu, MF_POPUP | MF_STRING, (DWORD) satMenu,
01552 "&Satellites");
01553 }
01554
01555 vector<string>* altSurfaces = sel.body()->getAlternateSurfaceNames();
01556 if (altSurfaces != NULL)
01557 {
01558 if (altSurfaces->size() != NULL)
01559 {
01560 HMENU surfMenu = CreateAlternateSurfaceMenu(*altSurfaces);
01561 AppendMenu(hMenu, MF_POPUP | MF_STRING, (DWORD) surfMenu,
01562 "&Alternate Surfaces");
01563 }
01564 delete altSurfaces;
01565 }
01566 }
01567 break;
01568
01569 case Selection::Type_Star:
01570 {
01571 Simulation* sim = appCore->getSimulation();
01572 name = sim->getUniverse()->getStarCatalog()->getStarName(*(sel.star()));
01573 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_CENTER, name.c_str());
01574 AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
01575 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_GOTO, "&Goto");
01576 AppendMenu(hMenu, MF_STRING, ID_INFO, "&Info");
01577
01578 SolarSystemCatalog* solarSystemCatalog = sim->getUniverse()->getSolarSystemCatalog();
01579 SolarSystemCatalog::iterator iter = solarSystemCatalog->find(sel.star()->getCatalogNumber());
01580 if (iter != solarSystemCatalog->end())
01581 {
01582 SolarSystem* solarSys = iter->second;
01583 HMENU planetsMenu = CreatePlanetarySystemMenu(name, solarSys->getPlanets());
01584 if (name == "Sol")
01585 AppendMenu(hMenu, MF_POPUP | MF_STRING, (DWORD) planetsMenu, "Orbiting Bodies");
01586 else
01587 AppendMenu(hMenu, MF_POPUP | MF_STRING, (DWORD) planetsMenu, "Planets");
01588 }
01589 }
01590 break;
01591
01592 case Selection::Type_DeepSky:
01593 {
01594 Simulation* sim = appCore->getSimulation();
01595 name = sim->getUniverse()->getDSOCatalog()->getDSOName(sel.deepsky());
01596 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_CENTER, name.c_str());
01597 AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
01598 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_GOTO, "&Goto");
01599 AppendMenu(hMenu, MF_STRING, ID_NAVIGATION_FOLLOW, "&Follow");
01600 AppendMenu(hMenu, MF_STRING, ID_INFO, "&Info");
01601 }
01602 break;
01603
01604 case Selection::Type_Location:
01605 break;
01606
01607 default:
01608 break;
01609 }
01610
01611 if (appCore->getSimulation()->getUniverse()->isMarked(sel, 1))
01612 AppendMenu(hMenu, MF_STRING, ID_TOOLS_UNMARK, "&Unmark");
01613 else
01614 AppendMenu(hMenu, MF_STRING, ID_TOOLS_MARK, "&Mark");
01615
01616 POINT point;
01617 point.x = (int) x;
01618 point.y = (int) y;
01619
01620 if (currentScreenMode == 0)
01621 ClientToScreen(hwnd, (LPPOINT) &point);
01622
01623 appCore->getSimulation()->setSelection(sel);
01624 TrackPopupMenu(hMenu, 0, point.x, point.y, 0, hwnd, NULL);
01625
01626
01627
01628
01629 DestroyMenu(hMenu);
01630
01631 #ifdef INFINITE_MOUSE
01632 ignoreNextMoveEvent = true;
01633 #endif // INFINITE_MOUSE
01634 }
01635
01636
01637
01638 void ShowWWWInfo(const Selection& sel)
01639 {
01640 string url;
01641 switch (sel.getType())
01642 {
01643 case Selection::Type_Body:
01644 {
01645 url = sel.body()->getInfoURL();
01646 if (url.empty())
01647 {
01648 string name = sel.body()->getName();
01649 for (unsigned int i = 0; i < name.size(); i++)
01650 name[i] = tolower(name[i]);
01651
01652 url = string("http://www.nineplanets.org/") + name + ".html";
01653 }
01654 }
01655 break;
01656
01657 case Selection::Type_Star:
01658 {
01659 char name[32];
01660 sprintf(name, "HIP%d", sel.star()->getCatalogNumber() & ~0xf0000000);
01661
01662 url = string("http://simbad.u-strasbg.fr/sim-id.pl?protocol=html&Ident=") + name;
01663 }
01664 break;
01665
01666 case Selection::Type_DeepSky:
01667 url = sel.deepsky()->getInfoURL();
01668 break;
01669
01670 case Selection::Type_Location:
01671 break;
01672
01673 default:
01674 break;
01675 }
01676
01677 ShellExecute(mainWindow,
01678 "open",
01679 url.c_str(),
01680 NULL,
01681 NULL,
01682 0);
01683 }
01684
01685
01686 void ContextMenu(float x, float y, Selection sel)
01687 {
01688 handlePopupMenu(mainWindow, x, y, sel);
01689 }
01690
01691
01692 bool EnableFullScreen(const DEVMODE& dm)
01693 {
01694 DEVMODE devMode;
01695
01696 ZeroMemory(&devMode, sizeof devMode);
01697 devMode.dmSize = sizeof devMode;
01698 devMode.dmPelsWidth = dm.dmPelsWidth;
01699 devMode.dmPelsHeight = dm.dmPelsHeight;
01700 devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
01701
01702 if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) !=
01703 DISP_CHANGE_SUCCESSFUL)
01704 {
01705 MessageBox(NULL,
01706 "Unable to switch to full screen mode; running in window mode",
01707 "Error",
01708 MB_OK | MB_ICONERROR);
01709 return false;
01710 }
01711
01712 return true;
01713 }
01714
01715
01716 void DisableFullScreen()
01717 {
01718 ChangeDisplaySettings(0, 0);
01719 }
01720
01721
01722 unsigned int
01723 ChooseBestMSAAPixelFormat(HDC hdc, int *formats, unsigned int numFormats,
01724 int samplesRequested)
01725 {
01726 int idealFormat = 0;
01727 int bestFormat = 0;
01728 int bestSamples = 0;
01729
01730 for (unsigned int i = 0; i < numFormats; i++)
01731 {
01732 int query = WGL_SAMPLES_ARB;
01733 int result = 0;
01734 bool isFloatFormat = false;
01735
01736 query = WGL_SAMPLES_ARB;
01737 wglGetPixelFormatAttribivARB(hdc, formats[i], 0, 1, &query, &result);
01738
01739 if (result <= samplesRequested && result >= bestSamples)
01740 {
01741 bestSamples = result;
01742 bestFormat = formats[i];
01743 }
01744
01745 if (result == samplesRequested)
01746 idealFormat = formats[i];
01747 }
01748
01749 if (idealFormat != 0)
01750 return idealFormat;
01751
01752 return bestFormat;
01753 }
01754
01755
01756
01757 bool SetDCPixelFormat(HDC hDC)
01758 {
01759 bool msaa = false;
01760 if (appCore->getConfig()->aaSamples > 1 &&
01761 WGLExtensionSupported("WGL_ARB_pixel_format") &&
01762 WGLExtensionSupported("WGL_ARB_multisample"))
01763 {
01764 msaa = true;
01765 }
01766
01767 if (!msaa)
01768 {
01769 static PIXELFORMATDESCRIPTOR pfd = {
01770 sizeof(PIXELFORMATDESCRIPTOR),
01771 1,
01772 PFD_DRAW_TO_WINDOW |
01773 PFD_SUPPORT_OPENGL |
01774 PFD_DOUBLEBUFFER,
01775 PFD_TYPE_RGBA,
01776 GetDeviceCaps(hDC, BITSPIXEL),
01777 0,0,0,0,0,0,
01778 0,0,
01779 0,0,0,0,0,
01780 24,
01781 0,
01782 0,
01783 PFD_MAIN_PLANE,
01784 0,
01785 0,0,0
01786 };
01787
01788
01789 int nPixelFormat = ChoosePixelFormat(hDC, &pfd);
01790 if (nPixelFormat == 0)
01791 {
01792
01793 return false;
01794 }
01795 else
01796 {
01797
01798 SetPixelFormat(hDC, nPixelFormat, &pfd);
01799 return true;
01800 }
01801 }
01802 else
01803 {
01804 PIXELFORMATDESCRIPTOR pfd;
01805
01806 int ifmtList[] = {
01807 WGL_DRAW_TO_WINDOW_ARB, TRUE,
01808 WGL_SUPPORT_OPENGL_ARB, TRUE,
01809 WGL_DOUBLE_BUFFER_ARB, TRUE,
01810 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
01811 WGL_DEPTH_BITS_ARB, 24,
01812 WGL_COLOR_BITS_ARB, 24,
01813 WGL_RED_BITS_ARB, 8,
01814 WGL_GREEN_BITS_ARB, 8,
01815 WGL_BLUE_BITS_ARB, 8,
01816 WGL_ALPHA_BITS_ARB, 0,
01817 WGL_ACCUM_BITS_ARB, 0,
01818 WGL_STENCIL_BITS_ARB, 0,
01819 WGL_SAMPLE_BUFFERS_ARB, appCore->getConfig()->aaSamples > 1,
01820 0
01821 };
01822
01823 int pixelFormatIndex;
01824 int pixFormats[256];
01825 unsigned int numFormats;
01826
01827 wglChoosePixelFormatARB(hDC, ifmtList, NULL, 256, pixFormats, &numFormats);
01828
01829 pixelFormatIndex = ChooseBestMSAAPixelFormat(hDC, pixFormats,
01830 numFormats,
01831 appCore->getConfig()->aaSamples);
01832
01833 DescribePixelFormat(hDC, pixelFormatIndex,
01834 sizeof(PIXELFORMATDESCRIPTOR), &pfd);
01835 if (!SetPixelFormat(hDC, pixelFormatIndex, &pfd))
01836 return false;
01837
01838 return true;
01839 }
01840 }
01841
01842
01843 HWND CreateOpenGLWindow(int x, int y, int width, int height,
01844 int mode, int& newMode)
01845 {
01846 assert(mode >= 0 && mode < displayModes->size());
01847 if (mode != 0)
01848 {
01849 x = 0;
01850 y = 0;
01851 width = displayModes->at(mode - 1).dmPelsWidth;
01852 height = displayModes->at(mode - 1).dmPelsHeight;
01853 }
01854
01855
01856 WNDCLASS wc;
01857 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
01858 wc.lpfnWndProc = (WNDPROC) MainWindowProc;
01859 wc.cbClsExtra = 0;
01860 wc.cbWndExtra = 0;
01861 wc.hInstance = appInstance;
01862 wc.hIcon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_CELESTIA_ICON));
01863 wc.hCursor = hDefaultCursor;
01864 wc.hbrBackground = NULL;
01865 wc.lpszMenuName = NULL;
01866 wc.lpszClassName = AppName;
01867 if (RegisterClass(&wc) == 0)
01868 {
01869 MessageBox(NULL,
01870 "Failed to register the window class.", "Fatal Error",
01871 MB_OK | MB_ICONERROR);
01872 return NULL;
01873 }
01874
01875 newMode = currentScreenMode;
01876 if (mode != 0)
01877 {
01878 if (EnableFullScreen(displayModes->at(mode - 1)))
01879 newMode = mode;
01880 }
01881 else
01882 {
01883 DisableFullScreen();
01884 newMode = 0;
01885 }
01886
01887
01888 DWORD dwStyle;
01889 if (newMode != 0)
01890 {
01891 dwStyle = WS_POPUP;
01892 }
01893 else
01894 {
01895 dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
01896 }
01897
01898
01899 HWND hwnd = CreateWindow(AppName,
01900 AppName,
01901 dwStyle,
01902 x, y,
01903 width, height,
01904 NULL,
01905 NULL,
01906 appInstance,
01907 NULL);
01908
01909 if (hwnd == NULL)
01910 return NULL;
01911
01912 ShowWindow(hwnd, SW_SHOW);
01913 SetForegroundWindow(hwnd);
01914 SetFocus(hwnd);
01915
01916 deviceContext = GetDC(hwnd);
01917 if (!SetDCPixelFormat(deviceContext))
01918 {
01919 MessageBox(NULL,
01920 "Could not get appropriate pixel format for OpenGL rendering.", "Fatal Error",
01921 MB_OK | MB_ICONERROR);
01922 return NULL;
01923 }
01924
01925 if (glContext == NULL)
01926 glContext = wglCreateContext(deviceContext);
01927 wglMakeCurrent(deviceContext, glContext);
01928
01929 if (newMode == 0)
01930 SetMenu(hwnd, menuBar);
01931 else
01932 hideMenuBar = true;
01933
01934 return hwnd;
01935 }
01936
01937
01938 void DestroyOpenGLWindow()
01939 {
01940 #if 0
01941 if (glContext != NULL)
01942 {
01943 wglMakeCurrent(NULL, NULL);
01944 if (!wglDeleteContext(glContext))
01945 {
01946 MessageBox(NULL,
01947 "Releasing GL context failed.", "Error",
01948 MB_OK | MB_ICONERROR);
01949 }
01950 glContext = NULL;
01951 }
01952 #endif
01953
01954 if (deviceContext != NULL)
01955 {
01956 if (!ReleaseDC(mainWindow, deviceContext))
01957 {
01958 MessageBox(NULL,
01959 "Releasing device context failed.", "Error",
01960 MB_OK | MB_ICONERROR);
01961 }
01962 deviceContext = NULL;
01963 }
01964
01965 if (mainWindow != NULL)
01966 {
01967 SetMenu(mainWindow, NULL);
01968 DestroyWindow(mainWindow);
01969 mainWindow = NULL;
01970 }
01971
01972 UnregisterClass(AppName, appInstance);
01973 }
01974
01975
01976 void handleKey(WPARAM key, bool down)
01977 {
01978 int k = -1;
01979 int modifiers = 0;
01980
01981 if (GetKeyState(VK_SHIFT) & 0x8000)
01982 modifiers |= CelestiaCore::ShiftKey;
01983
01984 switch (key)
01985 {
01986 case VK_UP:
01987 k = CelestiaCore::Key_Up;
01988 break;
01989 case VK_DOWN:
01990 k = CelestiaCore::Key_Down;
01991 break;
01992 case VK_LEFT:
01993 k = CelestiaCore::Key_Left;
01994 break;
01995 case VK_RIGHT:
01996 k = CelestiaCore::Key_Right;
01997 break;
01998 case VK_HOME:
01999 k = CelestiaCore::Key_Home;
02000 break;
02001 case VK_END:
02002 k = CelestiaCore::Key_End;
02003 break;
02004 case VK_PRIOR:
02005 k = CelestiaCore::Key_PageUp;
02006 break;
02007 case VK_NEXT:
02008 k = CelestiaCore::Key_PageDown;
02009 break;
02010 case VK_F1:
02011 k = CelestiaCore::Key_F1;
02012 break;
02013 case VK_F2:
02014 k = CelestiaCore::Key_F2;
02015 break;
02016 case VK_F3:
02017 k = CelestiaCore::Key_F3;
02018 break;
02019 case VK_F4:
02020 k = CelestiaCore::Key_F4;
02021 break;
02022 case VK_F5:
02023 k = CelestiaCore::Key_F5;
02024 break;
02025 case VK_F6:
02026 k = CelestiaCore::Key_F6;
02027 break;
02028 case VK_F7:
02029 k = CelestiaCore::Key_F7;
02030 break;
02031 case VK_F8:
02032 if (joystickAvailable && down)
02033 {
02034 appCore->joystickAxis(CelestiaCore::Joy_XAxis, 0);
02035 appCore->joystickAxis(CelestiaCore::Joy_YAxis, 0);
02036 appCore->joystickAxis(CelestiaCore::Joy_ZAxis, 0);
02037 useJoystick = !useJoystick;
02038 }
02039 break;
02040 case VK_F11:
02041 k = CelestiaCore::Key_F11;
02042 break;
02043 case VK_F12:
02044 k = CelestiaCore::Key_F12;
02045 break;
02046
02047 case VK_NUMPAD2:
02048 k = CelestiaCore::Key_NumPad2;
02049 break;
02050 case VK_NUMPAD4:
02051 k = CelestiaCore::Key_NumPad4;
02052 break;
02053 case VK_NUMPAD5:
02054 k = CelestiaCore::Key_NumPad5;
02055 break;
02056 case VK_NUMPAD6:
02057 k = CelestiaCore::Key_NumPad6;
02058 break;
02059 case VK_NUMPAD7:
02060 k = CelestiaCore::Key_NumPad7;
02061 break;
02062 case VK_NUMPAD8:
02063 k = CelestiaCore::Key_NumPad8;
02064 break;
02065 case VK_NUMPAD9:
02066 k = CelestiaCore::Key_NumPad9;
02067 break;
02068 case VK_DELETE:
02069 if (!down)
02070 appCore->charEntered('\177');
02071 break;
02072 case 'A':
02073 case 'Z':
02074 k = key;
02075 break;
02076 }
02077
02078 if (k >= 0)
02079 {
02080 if (down)
02081 appCore->keyDown(k, modifiers);
02082 else
02083 appCore->keyUp(k, modifiers);
02084 }
02085 }
02086
02087 static void syncMenusWithRendererState()
02088 {
02089 int renderFlags = appCore->getRenderer()->getRenderFlags();
02090 int labelMode = appCore->getRenderer()->getLabelMode();
02091 float ambientLight = appCore->getRenderer()->getAmbientLightLevel();
02092
02093 setMenuItemCheck(ID_VIEW_SHOW_FRAMES,
02094 appCore->getFramesVisible());
02095 setMenuItemCheck(ID_VIEW_SYNC_TIME,
02096 appCore->getSimulation()->getSyncTime());
02097
02098 if(abs(0.0 - (double)ambientLight) < 1.0e-3)
02099 {
02100 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_NONE, MF_CHECKED);
02101 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_LOW, MF_UNCHECKED);
02102 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_MEDIUM, MF_UNCHECKED);
02103 }
02104 else if(abs(0.1 - (double)ambientLight) < 1.0e-3)
02105 {
02106 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_NONE, MF_UNCHECKED);
02107 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_LOW, MF_CHECKED);
02108 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_MEDIUM, MF_UNCHECKED);
02109 }
02110 else if(abs(0.25 - (double)ambientLight) < 1.0e-3)
02111 {
02112 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_NONE, MF_UNCHECKED);
02113 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_LOW, MF_UNCHECKED);
02114 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_MEDIUM, MF_CHECKED);
02115 }
02116
02117 Renderer::StarStyle style = appCore->getRenderer()->getStarStyle();
02118 CheckMenuItem(menuBar, ID_RENDER_STARSTYLE_FUZZY,
02119 style == Renderer::FuzzyPointStars ? MF_CHECKED : MF_UNCHECKED);
02120 CheckMenuItem(menuBar, ID_RENDER_STARSTYLE_POINTS,
02121 style == Renderer::PointStars ? MF_CHECKED : MF_UNCHECKED);
02122 CheckMenuItem(menuBar, ID_RENDER_STARSTYLE_DISCS,
02123 style == Renderer::ScaledDiscStars ? MF_CHECKED : MF_UNCHECKED);
02124
02125 MENUITEMINFO menuInfo;
02126 menuInfo.cbSize = sizeof(MENUITEMINFO);
02127 menuInfo.fMask = MIIM_STATE;
02128 if (GetMenuItemInfo(menuBar, ID_TIME_SHOWLOCAL, FALSE, &menuInfo))
02129 {
02130 if (appCore->getTimeZoneBias() == 0)
02131 CheckMenuItem(menuBar, ID_TIME_SHOWLOCAL, MF_UNCHECKED);
02132 else
02133 CheckMenuItem(menuBar, ID_TIME_SHOWLOCAL, MF_CHECKED);
02134 }
02135
02136 CheckMenuItem(menuBar, ID_RENDER_ANTIALIASING,
02137 (renderFlags & Renderer::ShowSmoothLines)?MF_CHECKED:MF_UNCHECKED);
02138 CheckMenuItem(menuBar, ID_RENDER_AUTOMAG,
02139 (renderFlags & Renderer::ShowAutoMag)?MF_CHECKED:MF_UNCHECKED);
02140 }
02141
02142
02143 class WinAlerter : public CelestiaCore::Alerter
02144 {
02145 private:
02146 HWND hwnd;
02147
02148 public:
02149 WinAlerter() : hwnd(NULL) {};
02150 ~WinAlerter() {};
02151
02152 void fatalError(const std::string& msg)
02153 {
02154 MessageBox(NULL,
02155 msg.c_str(),
02156 "Fatal Error",
02157 MB_OK | MB_ICONERROR);
02158 }
02159 };
02160
02161
02162 static bool InitJoystick(JOYCAPS& caps)
02163 {
02164 int nJoysticks = joyGetNumDevs();
02165 if (nJoysticks <= 0)
02166 return false;
02167
02168 if (joyGetDevCaps(JOYSTICKID1, &caps, sizeof caps) != JOYERR_NOERROR)
02169 {
02170 cout << "Error getting joystick caps.\n";
02171 return false;
02172 }
02173
02174 cout << "Using joystick: " << caps.szPname << '\n';
02175
02176 return true;
02177 }
02178
02179
02180 static void HandleJoystick()
02181 {
02182 JOYINFOEX info;
02183
02184 info.dwSize = sizeof info;
02185 info.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNBUTTONS;
02186 MMRESULT err = joyGetPosEx(JOYSTICKID1, &info);
02187
02188 if (err == JOYERR_NOERROR)
02189 {
02190 float x = (float) info.dwXpos / 32768.0f - 1.0f;
02191 float y = (float) info.dwYpos / 32768.0f - 1.0f;
02192
02193 appCore->joystickAxis(CelestiaCore::Joy_XAxis, x);
02194 appCore->joystickAxis(CelestiaCore::Joy_YAxis, y);
02195 appCore->joystickButton(CelestiaCore::JoyButton1,
02196 (info.dwButtons & 0x1) != 0);
02197 appCore->joystickButton(CelestiaCore::JoyButton2,
02198 (info.dwButtons & 0x2) != 0);
02199 appCore->joystickButton(CelestiaCore::JoyButton7,
02200 (info.dwButtons & 0x40) != 0);
02201 appCore->joystickButton(CelestiaCore::JoyButton8,
02202 (info.dwButtons & 0x80) != 0);
02203 }
02204 }
02205
02206 static bool GetRegistryValue(HKEY hKey, LPSTR cpValueName, LPVOID lpBuf, DWORD iBufSize)
02207 {
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226 DWORD dwValueType, dwDataSize=0;
02227 bool bRC=false;
02228
02229 dwDataSize = iBufSize;
02230 if(RegQueryValueEx(hKey, cpValueName, NULL, &dwValueType,
02231 (LPBYTE)lpBuf, &dwDataSize) == ERROR_SUCCESS)
02232 bRC = true;
02233
02234 return bRC;
02235 }
02236
02237 static bool SetRegistryInt(HKEY key, LPCTSTR value, int intVal)
02238 {
02239 LONG err = RegSetValueEx(key,
02240 value,
02241 0,
02242 REG_DWORD,
02243 reinterpret_cast<CONST BYTE*>(&intVal),
02244 sizeof(DWORD));
02245 return err == ERROR_SUCCESS;
02246 }
02247
02248 static bool SetRegistry(HKEY key, LPCTSTR value, const string& strVal)
02249 {
02250 LONG err = RegSetValueEx(key,
02251 value,
02252 0,
02253 REG_SZ,
02254 reinterpret_cast<CONST BYTE*> (strVal.c_str()),
02255 strVal.length() + 1);
02256
02257 return err == ERROR_SUCCESS;
02258 }
02259
02260 static bool SetRegistryBin(HKEY hKey, LPSTR cpValueName, LPVOID lpData, int iDataSize)
02261 {
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280 bool bRC = false;
02281
02282 if (RegSetValueEx(hKey, cpValueName, 0, REG_BINARY,
02283 (LPBYTE) lpData, (DWORD) iDataSize) == ERROR_SUCCESS)
02284 {
02285 bRC = true;
02286 }
02287
02288 return bRC;
02289 }
02290
02291
02292 static bool LoadPreferencesFromRegistry(LPTSTR regkey, AppPreferences& prefs)
02293 {
02294 LONG err;
02295 HKEY key;
02296
02297 DWORD disposition;
02298 err = RegCreateKeyEx(HKEY_CURRENT_USER,
02299 regkey,
02300 0,
02301 NULL,
02302 REG_OPTION_NON_VOLATILE,
02303 KEY_ALL_ACCESS,
02304 NULL,
02305 &key,
02306 &disposition);
02307 if (err != ERROR_SUCCESS)
02308 {
02309 cout << "Error opening registry key: " << err << '\n';
02310 return false;
02311 }
02312
02313 GetRegistryValue(key, "Width", &prefs.winWidth, sizeof(prefs.winWidth));
02314 GetRegistryValue(key, "Height", &prefs.winHeight, sizeof(prefs.winHeight));
02315 GetRegistryValue(key, "XPos", &prefs.winX, sizeof(prefs.winX));
02316 GetRegistryValue(key, "YPos", &prefs.winY, sizeof(prefs.winY));
02317 GetRegistryValue(key, "RenderFlags", &prefs.renderFlags, sizeof(prefs.renderFlags));
02318 GetRegistryValue(key, "LabelMode", &prefs.labelMode, sizeof(prefs.labelMode));
02319 GetRegistryValue(key, "OrbitMask", &prefs.orbitMask, sizeof(prefs.orbitMask));
02320 GetRegistryValue(key, "VisualMagnitude", &prefs.visualMagnitude, sizeof(prefs.visualMagnitude));
02321 GetRegistryValue(key, "AmbientLight", &prefs.ambientLight, sizeof(prefs.ambientLight));
02322 GetRegistryValue(key, "ShowLocalTime", &prefs.showLocalTime, sizeof(prefs.showLocalTime));
02323 GetRegistryValue(key, "HudDetail", &prefs.hudDetail, sizeof(prefs.hudDetail));
02324 GetRegistryValue(key, "FullScreenMode", &prefs.fullScreenMode, sizeof(prefs.fullScreenMode));
02325
02326 prefs.starStyle = Renderer::FuzzyPointStars;
02327 GetRegistryValue(key, "StarStyle", &prefs.starStyle, sizeof(prefs.starStyle));
02328 prefs.renderPath = GLContext::GLPath_Basic;
02329 prefs.renderPathSet = GetRegistryValue(key, "RenderPath", &prefs.renderPath, sizeof(prefs.renderPath));
02330
02331 GetRegistryValue(key, "LastVersion", &prefs.lastVersion, sizeof(prefs.lastVersion));
02332 GetRegistryValue(key, "TextureResolution", &prefs.textureResolution, sizeof(prefs.textureResolution));
02333
02334 char surfaceName[512];
02335 surfaceName[0] = '\0';
02336 if (GetRegistryValue(key, "AltSurface", surfaceName, sizeof(surfaceName)))
02337 prefs.altSurfaceName = string(surfaceName);
02338
02339 if (prefs.lastVersion < 0x01020500)
02340 {
02341 prefs.renderFlags |= Renderer::ShowCometTails;
02342 prefs.renderFlags |= Renderer::ShowRingShadows;
02343 }
02344 prefs.renderFlags &= ~Renderer::ShowAutoMag;
02345
02346 RegCloseKey(key);
02347
02348 return true;
02349 }
02350
02351
02352 static bool SavePreferencesToRegistry(LPTSTR regkey, AppPreferences& prefs)
02353 {
02354 LONG err;
02355 HKEY key;
02356
02357 cout << "Saving preferences . . .\n";
02358 err = RegOpenKeyEx(HKEY_CURRENT_USER,
02359 regkey,
02360 0,
02361 KEY_ALL_ACCESS,
02362 &key);
02363 if (err != ERROR_SUCCESS)
02364 {
02365 cout << "Error opening registry key: " << err << '\n';
02366 return false;
02367 }
02368 cout << "Opened registry key\n";
02369
02370 SetRegistryInt(key, "Width", prefs.winWidth);
02371 SetRegistryInt(key, "Height", prefs.winHeight);
02372 SetRegistryInt(key, "XPos", prefs.winX);
02373 SetRegistryInt(key, "YPos", prefs.winY);
02374 SetRegistryInt(key, "RenderFlags", prefs.renderFlags);
02375 SetRegistryInt(key, "LabelMode", prefs.labelMode);
02376 SetRegistryInt(key, "OrbitMask", prefs.orbitMask);
02377 SetRegistryBin(key, "VisualMagnitude", &prefs.visualMagnitude, sizeof(prefs.visualMagnitude));
02378 SetRegistryBin(key, "AmbientLight", &prefs.ambientLight, sizeof(prefs.ambientLight));
02379 SetRegistryInt(key, "ShowLocalTime", prefs.showLocalTime);
02380 SetRegistryInt(key, "HudDetail", prefs.hudDetail);
02381 SetRegistryInt(key, "FullScreenMode", prefs.fullScreenMode);
02382 SetRegistryInt(key, "LastVersion", prefs.lastVersion);
02383 SetRegistryInt(key, "StarStyle", prefs.starStyle);
02384 SetRegistryInt(key, "RenderPath", prefs.renderPath);
02385 SetRegistry(key, "AltSurface", prefs.altSurfaceName);
02386 SetRegistryInt(key, "TextureResolution", prefs.textureResolution);
02387
02388 RegCloseKey(key);
02389
02390 return true;
02391 }
02392
02393
02394 static bool GetCurrentPreferences(AppPreferences& prefs)
02395 {
02396 WINDOWPLACEMENT placement;
02397
02398 placement.length = sizeof(placement);
02399 if (!GetWindowPlacement(mainWindow, &placement))
02400 return false;
02401
02402 RECT rect = placement.rcNormalPosition;
02403 prefs.winX = rect.left;
02404 prefs.winY = rect.top;
02405 prefs.winWidth = rect.right - rect.left;
02406 prefs.winHeight = rect.bottom - rect.top;
02407 prefs.renderFlags = appCore->getRenderer()->getRenderFlags();
02408 prefs.labelMode = appCore->getRenderer()->getLabelMode();
02409 prefs.orbitMask = appCore->getRenderer()->getOrbitMask();
02410 prefs.visualMagnitude = appCore->getSimulation()->getFaintestVisible();
02411 prefs.ambientLight = appCore->getRenderer()->getAmbientLightLevel();
02412 prefs.showLocalTime = (appCore->getTimeZoneBias() != 0);
02413 prefs.hudDetail = appCore->getHudDetail();
02414 prefs.fullScreenMode = lastFullScreenMode;
02415 prefs.lastVersion = 0x01040100;
02416 prefs.altSurfaceName = appCore->getSimulation()->getActiveObserver()->getDisplayedSurface();
02417 prefs.starStyle = appCore->getRenderer()->getStarStyle();
02418 prefs.renderPath = appCore->getRenderer()->getGLContext()->getRenderPath();
02419 prefs.textureResolution = appCore->getRenderer()->getResolution();
02420
02421 return true;
02422 }
02423
02424
02425 static void HandleCaptureImage(HWND hWnd)
02426 {
02427
02428
02429 OPENFILENAME Ofn;
02430 char szFile[_MAX_PATH+1], szFileTitle[_MAX_PATH+1];
02431
02432 szFile[0] = '\0';
02433 szFileTitle[0] = '\0';
02434
02435
02436 ZeroMemory(&Ofn, sizeof(OPENFILENAME));
02437 Ofn.lStructSize = sizeof(OPENFILENAME);
02438 Ofn.hwndOwner = hWnd;
02439 Ofn.lpstrFilter = "JPEG - JFIF Compliant\0*.jpg;*.jif;*.jpeg\0Portable Network Graphics\0*.png\0";
02440 Ofn.lpstrFile= szFile;
02441 Ofn.nMaxFile = sizeof(szFile);
02442 Ofn.lpstrFileTitle = szFileTitle;
02443 Ofn.nMaxFileTitle = sizeof(szFileTitle);
02444 Ofn.lpstrInitialDir = (LPSTR)NULL;
02445
02446
02447 Ofn.lpstrTitle = "Save As - Specify File to Capture Image";
02448
02449
02450
02451 Ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
02452
02453
02454 if (GetSaveFileName(&Ofn))
02455 {
02456
02457
02458
02459
02460
02461 int viewport[4];
02462 glGetIntegerv(GL_VIEWPORT, viewport);
02463
02464 bool success = false;
02465
02466 DWORD nFileType=0;
02467 char defaultExtensions[][4] = {"jpg", "png"};
02468 if (Ofn.nFileExtension == 0)
02469 {
02470
02471
02472
02473 nFileType = Ofn.nFilterIndex;
02474 strcat(Ofn.lpstrFile, ".");
02475 strcat(Ofn.lpstrFile, defaultExtensions[nFileType-1]);
02476 }
02477 else if (*(Ofn.lpstrFile + Ofn.nFileExtension) == '\0')
02478 {
02479
02480
02481
02482 nFileType = Ofn.nFilterIndex;
02483 strcat(Ofn.lpstrFile, defaultExtensions[nFileType-1]);
02484 }
02485 else
02486 {
02487 switch (DetermineFileType(Ofn.lpstrFile))
02488 {
02489 case Content_JPEG:
02490 nFileType = 1;
02491 break;
02492 case Content_PNG:
02493 nFileType = 2;
02494 break;
02495 default:
02496 nFileType = 0;
02497 break;
02498 }
02499 }
02500
02501 if (nFileType == 1)
02502 {
02503 success = CaptureGLBufferToJPEG(string(Ofn.lpstrFile),
02504 viewport[0], viewport[1],
02505 viewport[2], viewport[3]);
02506 }
02507 else if (nFileType == 2)
02508 {
02509 success = CaptureGLBufferToPNG(string(Ofn.lpstrFile),
02510 viewport[0], viewport[1],
02511 viewport[2], viewport[3]);
02512 }
02513 else
02514 {
02515
02516 DPRINTF(0, "WTF? Unknown file extension specified for screen capture.\n");
02517 }
02518
02519 if (!success)
02520 {
02521 char errorMsg[64];
02522
02523 if(nFileType == 0)
02524 sprintf(errorMsg, "Specified file extension is not recognized.");
02525 else
02526 sprintf(errorMsg, "Could not save image file.");
02527
02528 MessageBox(hWnd, errorMsg, "Error", MB_OK | MB_ICONERROR);
02529 }
02530 }
02531 }
02532
02533
02534 static void HandleCaptureMovie(HWND hWnd)
02535 {
02536
02537
02538
02539
02540 if (appCore->isCaptureActive())
02541 {
02542 MessageBox(hWnd, "Stop current movie capture before starting another one.", "Error", MB_OK | MB_ICONERROR);
02543 return;
02544 }
02545
02546
02547
02548 OPENFILENAME Ofn;
02549 char szFile[_MAX_PATH+1], szFileTitle[_MAX_PATH+1];
02550
02551 szFile[0] = '\0';
02552 szFileTitle[0] = '\0';
02553
02554
02555 ZeroMemory(&Ofn, sizeof(OPENFILENAME));
02556 Ofn.lStructSize = sizeof(OPENFILENAME);
02557 Ofn.hwndOwner = hWnd;
02558 Ofn.lpstrFilter = "Microsoft AVI\0*.avi\0";
02559 Ofn.lpstrFile= szFile;
02560 Ofn.nMaxFile = sizeof(szFile);
02561 Ofn.lpstrFileTitle = szFileTitle;
02562 Ofn.nMaxFileTitle = sizeof(szFileTitle);
02563 Ofn.lpstrInitialDir = (LPSTR)NULL;
02564
02565
02566 Ofn.lpstrTitle = "Save As - Specify Output File for Capture Movie";
02567
02568
02569
02570 Ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_NOCHANGEDIR;
02571
02572 Ofn.hInstance = appInstance;
02573 Ofn.lpTemplateName = MAKEINTRESOURCE(IDD_MOVIE_PARAMS_CHOOSER);
02574 Ofn.lpfnHook = ChooseMovieParamsProc;
02575
02576
02577 if (GetSaveFileName(&Ofn))
02578 {
02579
02580
02581
02582
02583 bool success = false;
02584
02585 DWORD nFileType=0;
02586 char defaultExtensions[][4] = { "avi" };
02587 if (Ofn.nFileExtension == 0)
02588 {
02589
02590
02591
02592 nFileType = Ofn.nFilterIndex;
02593 strcat(Ofn.lpstrFile, ".");
02594 strcat(Ofn.lpstrFile, defaultExtensions[nFileType-1]);
02595 }
02596 else if (*(Ofn.lpstrFile + Ofn.nFileExtension) == '\0')
02597 {
02598
02599
02600
02601 nFileType = Ofn.nFilterIndex;
02602 strcat(Ofn.lpstrFile, defaultExtensions[nFileType-1]);
02603 }
02604 else
02605 {
02606 switch (DetermineFileType(Ofn.lpstrFile))
02607 {
02608 case Content_AVI:
02609 nFileType = 1;
02610 break;
02611 default:
02612 nFileType = 0;
02613 break;
02614 }
02615 }
02616
02617 if (nFileType != 1)
02618 {
02619
02620 DPRINTF(0, "Unknown file extension specified for movie capture.\n");
02621 }
02622 else
02623 {
02624 success = BeginMovieCapture(string(Ofn.lpstrFile),
02625 MovieSizes[movieSize][0],
02626 MovieSizes[movieSize][1],
02627 MovieFramerates[movieFramerate]);
02628 }
02629
02630 if (!success)
02631 {
02632 char errorMsg[64];
02633
02634 if (nFileType == 0)
02635 sprintf(errorMsg, "Specified file extension is not recognized.");
02636 else
02637 sprintf(errorMsg, "Could not capture movie.");
02638
02639 MessageBox(hWnd, errorMsg, "Error", MB_OK | MB_ICONERROR);
02640 }
02641 }
02642 }
02643
02644
02645 static void HandleOpenScript(HWND hWnd, CelestiaCore* appCore)
02646 {
02647
02648
02649 OPENFILENAME Ofn;
02650 char szFile[_MAX_PATH + 1];
02651 char szFileTitle[_MAX_PATH + 1];
02652
02653
02654 char currentDir[_MAX_PATH + 1];
02655 currentDir[0] = '\0';
02656 GetCurrentDirectory(sizeof(currentDir), currentDir);
02657
02658 szFile[0] = '\0';
02659 szFileTitle[0] = '\0';
02660
02661
02662 ZeroMemory(&Ofn, sizeof(OPENFILENAME));
02663 Ofn.lStructSize = sizeof(OPENFILENAME);
02664 Ofn.hwndOwner = hWnd;
02665 Ofn.lpstrFilter = "Celestia Script\0*.celx;*.clx;*.cel\0";
02666 Ofn.lpstrFile= szFile;
02667 Ofn.nMaxFile = sizeof(szFile);
02668 Ofn.lpstrFileTitle = szFileTitle;
02669 Ofn.nMaxFileTitle = sizeof(szFileTitle);
02670 Ofn.lpstrInitialDir = (LPSTR)NULL;
02671
02672
02673
02674
02675
02676 if (GetOpenFileName(&Ofn))
02677 {
02678
02679
02680
02681 ContentType type = DetermineFileType(Ofn.lpstrFile);
02682
02683 if (type == Content_CelestiaScript)
02684 {
02685 appCore->runScript(Ofn.lpstrFile);
02686 }
02687 else if (type == Content_CelestiaLegacyScript)
02688 {
02689 ifstream scriptfile(Ofn.lpstrFile);
02690 if (!scriptfile.good())
02691 {
02692 MessageBox(hWnd, "Error opening script file.", "Error",
02693 MB_OK | MB_ICONERROR);
02694 }
02695 else
02696 {
02697 CommandParser parser(scriptfile);
02698 CommandSequence* script = parser.parse();
02699 if (script == NULL)
02700 {
02701 const vector<string>* errors = parser.getErrors();
02702 const char* errorMsg = "";
02703 if (errors->size() > 0)
02704 errorMsg = (*errors)[0].c_str();
02705 MessageBox(hWnd, errorMsg, "Error in script file.",
02706 MB_OK | MB_ICONERROR);
02707 }
02708 else
02709 {
02710 appCore->cancelScript();
02711 appCore->runScript(script);
02712 }
02713 }
02714 }
02715 }
02716
02717 if (strlen(currentDir) != 0)
02718 SetCurrentDirectory(currentDir);
02719 }
02720
02721
02722 bool operator<(const DEVMODE& a, const DEVMODE& b)
02723 {
02724 if (a.dmBitsPerPel != b.dmBitsPerPel)
02725 return a.dmBitsPerPel < b.dmBitsPerPel;
02726 if (a.dmPelsWidth != b.dmPelsWidth)
02727 return a.dmPelsWidth < b.dmPelsWidth;
02728 if (a.dmPelsHeight != b.dmPelsHeight)
02729 return a.dmPelsHeight < b.dmPelsHeight;
02730 return a.dmDisplayFrequency < b.dmDisplayFrequency;
02731 }
02732
02733 vector<DEVMODE>* EnumerateDisplayModes(unsigned int minBPP)
02734 {
02735 vector<DEVMODE>* modes = new vector<DEVMODE>();
02736 if (modes == NULL)
02737 return NULL;
02738
02739 DEVMODE dm;
02740 int i = 0;
02741 while (EnumDisplaySettings(NULL, i, &dm))
02742 {
02743 if (dm.dmBitsPerPel >= minBPP)
02744 modes->insert(modes->end(), dm);
02745 i++;
02746 }
02747 sort(modes->begin(), modes->end());
02748
02749
02750 if (i == 0)
02751 return modes;
02752
02753
02754
02755 vector<DEVMODE>::iterator keepIter = modes->begin();
02756 vector<DEVMODE>::const_iterator iter = modes->begin();
02757 iter++;
02758 for (; iter != modes->end(); iter++)
02759 {
02760 if (iter->dmPelsWidth != keepIter->dmPelsWidth ||
02761 iter->dmPelsHeight != keepIter->dmPelsHeight ||
02762 iter->dmBitsPerPel != keepIter->dmBitsPerPel)
02763 {
02764 *++keepIter = *iter;
02765 }
02766 }
02767
02768 modes->resize(keepIter - modes->begin() + 1);
02769
02770
02771
02772
02773 lastFullScreenMode = 0;
02774 for (iter = modes->begin(); iter != modes->end(); iter++)
02775 {
02776 if (iter->dmPelsWidth == 640 && iter->dmPelsHeight == 480)
02777 {
02778
02779 lastFullScreenMode = (iter - modes->begin()) + 1;
02780 break;
02781 }
02782 }
02783 if (lastFullScreenMode == 0 && modes->size() > 0)
02784 lastFullScreenMode = 1;
02785
02786 return modes;
02787 }
02788
02789
02790 static char* skipSpace(char* s)
02791 {
02792 while (*s == ' ')
02793 s++;
02794 return s;
02795 }
02796
02797 static char* skipUntilQuote(char* s)
02798 {
02799 while (*s != '"' && s != '\0')
02800 s++;
02801 return s;
02802 }
02803
02804 static char* nextWord(char* s)
02805 {
02806 while (*s != ' ' && *s != '\0')
02807 s++;
02808 return s;
02809 }
02810
02811 static char** splitCommandLine(LPSTR cmdLine,
02812 int& argc)
02813 {
02814 int nArgs = 0;
02815 int maxArgs = 50;
02816 char** argv = new char*[maxArgs];
02817
02818 cmdLine = skipSpace(cmdLine);
02819 while (*cmdLine != '\0')
02820 {
02821 char* startOfWord = cmdLine;
02822 char* endOfWord = cmdLine;
02823 int wordLength = 0;
02824
02825 if (*cmdLine == '"')
02826 {
02827
02828 startOfWord = cmdLine + 1;
02829 endOfWord = skipUntilQuote(startOfWord);
02830 wordLength = endOfWord - startOfWord;
02831 if (*endOfWord != '\0')
02832 endOfWord++;
02833 }
02834 else
02835 {
02836 endOfWord = nextWord(cmdLine);
02837 wordLength = endOfWord - startOfWord;
02838 assert(wordLength != 0);
02839 }
02840
02841 char* newWord = new char[wordLength + 1];
02842 strncpy(newWord, startOfWord, wordLength);
02843 newWord[wordLength] = '\0';
02844
02845 if (nArgs == maxArgs)
02846 {
02847 char** newArgv = new char*[maxArgs * 2];
02848 copy(argv, argv + nArgs, newArgv);
02849 delete argv;
02850 argv = newArgv;
02851 maxArgs *= 2;
02852 }
02853
02854 argv[nArgs] = newWord;
02855 nArgs++;
02856
02857 cmdLine = endOfWord;
02858 cmdLine = skipSpace(cmdLine);
02859 }
02860
02861 argc = nArgs;
02862
02863 return argv;
02864 }
02865
02866
02867 static bool startFullscreen = false;
02868 static bool runOnce = false;
02869 static string startURL;
02870 static string startDirectory;
02871 static string startScript;
02872 static vector<string> extrasDirectories;
02873 static string configFileName;
02874 static bool useAlternateConfigFile = false;
02875 static bool skipSplashScreen = false;
02876
02877 static bool parseCommandLine(int argc, char* argv[])
02878 {
02879 int i = 0;
02880
02881 while (i < argc)
02882 {
02883 bool isLastArg = (i == argc - 1);
02884 if (strcmp(argv[i], "--verbose") == 0)
02885 {
02886 SetDebugVerbosity(1);
02887 }
02888 else if (strcmp(argv[i], "--fullscreen") == 0)
02889 {
02890 startFullscreen = true;
02891 }
02892 else if (strcmp(argv[i], "--once") == 0)
02893 {
02894 runOnce = true;
02895 }
02896 else if (strcmp(argv[i], "--dir") == 0)
02897 {
02898 if (isLastArg)
02899 {
02900 MessageBox(NULL,
02901 "Directory expected after --dir", "Celestia Command Line Error",
02902 MB_OK | MB_ICONERROR);
02903 return false;
02904 }
02905 i++;
02906 startDirectory = string(argv[i]);
02907 }
02908 else if (strcmp(argv[i], "--conf") == 0)
02909 {
02910 if (isLastArg)
02911 {
02912 MessageBox(NULL,
02913 "Configuration file name expected after --conf",
02914 "Celestia Command Line Error",
02915 MB_OK | MB_ICONERROR);
02916 return false;
02917 }
02918 i++;
02919 configFileName = string(argv[i]);
02920 useAlternateConfigFile = true;
02921 }
02922 else if (strcmp(argv[i], "--extrasdir") == 0)
02923 {
02924 if (isLastArg)
02925 {
02926 MessageBox(NULL,
02927 "Directory expected after --extrasdir", "Celestia Command Line Error",
02928 MB_OK | MB_ICONERROR);
02929 return false;
02930 }
02931 i++;
02932 extrasDirectories.push_back(string(argv[i]));
02933 }
02934 else if (strcmp(argv[i], "-u") == 0 || strcmp(argv[i], "--url") == 0)
02935 {
02936 if (isLastArg)
02937 {
02938 MessageBox(NULL,
02939 "URL expected after --url", "Celestia Command Line Error",
02940 MB_OK | MB_ICONERROR);
02941 return false;
02942 }
02943 i++;
02944 startURL = string(argv[i]);
02945 }
02946 else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--nosplash") == 0)
02947 {
02948 skipSplashScreen = true;
02949 }
02950 else
02951 {
02952 char* buf = new char[strlen(argv[i]) + 256];
02953 sprintf(buf, "Invalid command line option '%s'", argv[i]);
02954 MessageBox(NULL,
02955 buf, "Celestia Command Line Error",
02956 MB_OK | MB_ICONERROR);
02957 delete[] buf;
02958 return false;
02959 }
02960
02961 i++;
02962 }
02963
02964 return true;
02965 }
02966
02967
02968 class WinSplashProgressNotifier : public ProgressNotifier
02969 {
02970 public:
02971 WinSplashProgressNotifier(SplashWindow* _splash) : splash(_splash) {};
02972 virtual ~WinSplashProgressNotifier() {};
02973
02974 virtual void update(const string& filename)
02975 {
02976 splash->setMessage(string("Loading: ") + filename);
02977 }
02978
02979 private:
02980 SplashWindow* splash;
02981 };
02982
02983
02984 int APIENTRY WinMain(HINSTANCE hInstance,
02985 HINSTANCE hPrevInstance,
02986 LPSTR lpCmdLine,
02987 int nCmdShow)
02988 {
02989
02990 bReady = false;
02991
02992 appInstance = hInstance;
02993
02994 int argc;
02995 char** argv;
02996 argv = splitCommandLine(lpCmdLine, argc);
02997 bool cmdLineOK = parseCommandLine(argc, argv);
02998 if (!cmdLineOK)
02999 return 1;
03000
03001
03002
03003 if (runOnce)
03004 {
03005
03006
03007
03008 HWND existingWnd = FindWindow(AppName, AppName);
03009 if (existingWnd)
03010 {
03011
03012
03013
03014 if (startURL != "")
03015 {
03016 COPYDATASTRUCT cd;
03017 cd.dwData = 0;
03018 cd.cbData = startURL.length();
03019 cd.lpData = reinterpret_cast<void*>(const_cast<char*>(startURL.c_str()));
03020 SendMessage(existingWnd, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cd));
03021 }
03022 SetForegroundWindow(existingWnd);
03023 Sleep(1000);
03024 exit(0);
03025 }
03026 }
03027
03028
03029
03030 if (startDirectory != "")
03031 SetCurrentDirectory(startDirectory.c_str());
03032
03033 SplashWindow splash("splash.png");
03034 splash.setMessage("Loading data files...");
03035 if (!skipSplashScreen)
03036 splash.showSplash();
03037
03038 OleInitialize(NULL);
03039 dropTarget = new CelestiaDropTarget();
03040 if (dropTarget)
03041 {
03042 if (CoLockObjectExternal(dropTarget, TRUE, TRUE) != S_OK)
03043 {
03044 cout << "Error locking drop target\n";
03045 delete dropTarget;
03046 dropTarget = NULL;
03047 }
03048 }
03049
03050
03051
03052
03053 AppPreferences prefs;
03054 prefs.winWidth = 800;
03055 prefs.winHeight = 600;
03056 prefs.winX = CW_USEDEFAULT;
03057 prefs.winY = CW_USEDEFAULT;
03058 prefs.ambientLight = 0.1f;
03059 prefs.labelMode = 0;
03060 prefs.orbitMask = Body::Planet | Body::Moon;
03061 prefs.renderFlags = Renderer::ShowAtmospheres | Renderer::ShowStars |
03062 Renderer::ShowPlanets | Renderer::ShowSmoothLines |
03063 Renderer::ShowCometTails | Renderer::ShowRingShadows;
03064 prefs.visualMagnitude = 6.0f;
03065 prefs.showLocalTime = 0;
03066 prefs.hudDetail = 1;
03067 prefs.fullScreenMode = -1;
03068 prefs.lastVersion = 0x00000000;
03069 prefs.textureResolution = 1;
03070 LoadPreferencesFromRegistry(CelestiaRegKey, prefs);
03071
03072
03073 int screenWidth = GetSystemMetrics(SM_CXSCREEN);
03074 int screenHeight = GetSystemMetrics(SM_CYSCREEN);
03075 if (prefs.winWidth > screenWidth)
03076 prefs.winWidth = screenWidth;
03077 if (prefs.winHeight > screenHeight)
03078 prefs.winHeight = screenHeight;
03079 if (prefs.winX != CW_USEDEFAULT && prefs.winY != CW_USEDEFAULT)
03080 {
03081 if (prefs.winX + prefs.winWidth > screenWidth)
03082 prefs.winX = screenWidth - prefs.winWidth;
03083 if (prefs.winY + prefs.winHeight > screenHeight)
03084 prefs.winY = screenHeight - prefs.winHeight;
03085 }
03086
03087
03088
03089
03090
03091 windowRect.left = prefs.winX;
03092 windowRect.top = prefs.winY;
03093 windowRect.right = windowRect.left + prefs.winWidth;
03094 windowRect.bottom = windowRect.top + prefs.winHeight;
03095
03096 joystickAvailable = InitJoystick(joystickCaps);
03097
03098 displayModes = EnumerateDisplayModes(16);
03099
03100
03101 if (prefs.fullScreenMode != -1)
03102 lastFullScreenMode = prefs.fullScreenMode;
03103
03104 appCore = new CelestiaCore();
03105 if (appCore == NULL)
03106 {
03107 MessageBox(NULL,
03108 "Out of memory.", "Fatal Error",
03109 MB_OK | MB_ICONERROR);
03110 return false;
03111 }
03112
03113 appCore->setAlerter(new WinAlerter());
03114
03115 WinSplashProgressNotifier* progressNotifier = NULL;
03116 if (!skipSplashScreen)
03117 progressNotifier = new WinSplashProgressNotifier(&splash);
03118
03119 string* altConfig = useAlternateConfigFile ? &configFileName : NULL;
03120 if (!appCore->initSimulation(altConfig, &extrasDirectories, progressNotifier))
03121 {
03122 delete progressNotifier;
03123 return 1;
03124 }
03125
03126 delete progressNotifier;
03127
03128
03129 splash.close();
03130
03131 if (startURL != "")
03132 appCore->setStartURL(startURL);
03133
03134 menuBar = CreateMenuBar();
03135 acceleratorTable = LoadAccelerators(hInstance,
03136 MAKEINTRESOURCE(IDR_ACCELERATORS));
03137
03138 if (appCore->getConfig() != NULL)
03139 {
03140 if (!compareIgnoringCase(appCore->getConfig()->cursor, "arrow"))
03141 hDefaultCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
03142 else if (!compareIgnoringCase(appCore->getConfig()->cursor, "inverting crosshair"))
03143 hDefaultCursor = LoadCursor(appInstance, MAKEINTRESOURCE(IDC_CROSSHAIR));
03144 else
03145 hDefaultCursor = LoadCursor(appInstance, MAKEINTRESOURCE(IDC_CROSSHAIR_OPAQUE));
03146 }
03147
03148 cursorHandler = new WinCursorHandler(hDefaultCursor);
03149 appCore->setCursorHandler(cursorHandler);
03150
03151 InitWGLExtensions(appInstance);
03152
03153 HWND hWnd;
03154 if (startFullscreen)
03155 {
03156 hWnd = CreateOpenGLWindow(0, 0, 800, 600,
03157 lastFullScreenMode, currentScreenMode);
03158
03159
03160
03161 newScreenMode = currentScreenMode;
03162 }
03163 else
03164 {
03165 hWnd = CreateOpenGLWindow(prefs.winX, prefs.winY,
03166 prefs.winWidth, prefs.winHeight,
03167 0, currentScreenMode);
03168 }
03169
03170 if (hWnd == NULL)
03171 {
03172 MessageBox(NULL,
03173 "Failed to create the application window.",
03174 "Fatal Error",
03175 MB_OK | MB_ICONERROR);
03176 return FALSE;
03177 }
03178
03179 if (dropTarget != NULL)
03180 {
03181 HRESULT hr = RegisterDragDrop(hWnd, dropTarget);
03182 if (hr != S_OK)
03183 {
03184 cout << "Failed to register drop target as OLE object.\n";
03185 }
03186 }
03187
03188 mainWindow = hWnd;
03189
03190 UpdateWindow(mainWindow);
03191
03192
03193 INITCOMMONCONTROLSEX icex;
03194 icex.dwSize = sizeof(icex);
03195 icex.dwICC = ICC_DATE_CLASSES;
03196 InitCommonControlsEx(&icex);
03197
03198 extern void RegisterDatePicker();
03199 RegisterDatePicker();
03200
03201 if (!appCore->initRenderer())
03202 {
03203 return 1;
03204 }
03205
03206
03207 if (prefs.lastVersion != 0)
03208 {
03209 appCore->getSimulation()->setFaintestVisible(prefs.visualMagnitude);
03210 appCore->getRenderer()->setRenderFlags(prefs.renderFlags);
03211 appCore->getRenderer()->setLabelMode(prefs.labelMode);
03212 appCore->getRenderer()->setOrbitMask(prefs.orbitMask);
03213 appCore->getRenderer()->setAmbientLightLevel(prefs.ambientLight);
03214 appCore->getRenderer()->setStarStyle(prefs.starStyle);
03215 appCore->setHudDetail(prefs.hudDetail);
03216 if (prefs.showLocalTime == 1)
03217 ShowLocalTime(appCore);
03218 else
03219 ShowUniversalTime(appCore);
03220 appCore->getSimulation()->getActiveObserver()->setDisplayedSurface(prefs.altSurfaceName);
03221 appCore->getRenderer()->setResolution(prefs.textureResolution);
03222 if (prefs.renderPathSet)
03223 {
03224 GLContext* glContext = appCore->getRenderer()->getGLContext();
03225 if (glContext->renderPathSupported(prefs.renderPath))
03226 glContext->setRenderPath(prefs.renderPath);
03227 }
03228 }
03229
03230 BuildFavoritesMenu(menuBar, appCore, appInstance, &odAppMenu);
03231 syncMenusWithRendererState();
03232
03233 appCore->setContextMenuCallback(ContextMenu);
03234
03235 bReady = true;
03236 appCore->start((double) time(NULL) / 86400.0 +
03237 (double) astro::Date(1970, 1, 1));
03238
03239 if (startURL != "")
03240 {
03241 COPYDATASTRUCT cd;
03242 cd.dwData = 0;
03243 cd.cbData = startURL.length();
03244 cd.lpData = reinterpret_cast<void*>(const_cast<char*>(startURL.c_str()));
03245 SendMessage(mainWindow, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cd));
03246 }
03247
03248 MSG msg;
03249 PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
03250 while (msg.message != WM_QUIT)
03251 {
03252 bool isVisible = !IsIconic(mainWindow);
03253
03254
03255 appCore->tick();
03256
03257
03258
03259
03260
03261 BOOL haveMessage;
03262 if (isVisible)
03263 haveMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
03264 else
03265 haveMessage = GetMessage(&msg, NULL, 0U, 0U);
03266
03267 if (haveMessage)
03268 {
03269 bool dialogMessage = false;
03270
03271 if (starBrowser != NULL &&
03272 IsDialogMessage(starBrowser->hwnd, &msg))
03273 dialogMessage = true;
03274 if (solarSystemBrowser != NULL &&
03275 IsDialogMessage(solarSystemBrowser->hwnd, &msg))
03276 dialogMessage = true;
03277 if (tourGuide != NULL &&
03278 IsDialogMessage(tourGuide->hwnd, &msg))
03279 dialogMessage = true;
03280 if (gotoObjectDlg != NULL &&
03281 IsDialogMessage(gotoObjectDlg->hwnd, &msg))
03282 dialogMessage = true;
03283 if (viewOptionsDlg != NULL &&
03284 IsDialogMessage(viewOptionsDlg->hwnd, &msg))
03285 dialogMessage = true;
03286 if (eclipseFinder != NULL &&
03287 IsDialogMessage(eclipseFinder->hwnd, &msg))
03288 dialogMessage = true;
03289 if (locationsDlg != NULL &&
03290 IsDialogMessage(locationsDlg->hwnd, &msg))
03291 dialogMessage = true;
03292
03293
03294 if (!dialogMessage)
03295 {
03296 if (!TranslateAccelerator(mainWindow, acceleratorTable, &msg))
03297 TranslateMessage(&msg);
03298 DispatchMessage(&msg);
03299 }
03300 }
03301 else
03302 {
03303
03304 InvalidateRect(mainWindow, NULL, FALSE);
03305 }
03306
03307 if (useJoystick)
03308 HandleJoystick();
03309
03310 if (currentScreenMode != newScreenMode)
03311 {
03312 if (currentScreenMode == 0)
03313 GetWindowRect(mainWindow, &windowRect);
03314 else
03315 lastFullScreenMode = currentScreenMode;
03316 DestroyOpenGLWindow();
03317 mainWindow = CreateOpenGLWindow(windowRect.left,
03318 windowRect.top,
03319 windowRect.right-windowRect.left,
03320 windowRect.bottom-windowRect.top,
03321 newScreenMode,
03322 currentScreenMode);
03323 UpdateWindow(mainWindow);
03324 }
03325 }
03326
03327
03328 {
03329 AppPreferences prefs;
03330 if (GetCurrentPreferences(prefs))
03331 SavePreferencesToRegistry(CelestiaRegKey, prefs);
03332 }
03333
03334
03335 bReady = false;
03336
03337
03338 if (currentScreenMode != 0)
03339 RestoreDisplayMode();
03340 DestroyOpenGLWindow();
03341
03342 if (appCore != NULL)
03343 delete appCore;
03344
03345 OleUninitialize();
03346
03347 return msg.wParam;
03348 }
03349
03350
03351 bool modifiers(WPARAM wParam, WPARAM mods)
03352 {
03353 return (wParam & mods) == mods;
03354 }
03355
03356
03357 static void RestoreCursor()
03358 {
03359 ShowCursor(TRUE);
03360 cursorVisible = true;
03361 SetCursorPos(saveCursorPos.x, saveCursorPos.y);
03362 }
03363
03364
03365 LRESULT CALLBACK MainWindowProc(HWND hWnd,
03366 UINT uMsg,
03367 WPARAM wParam, LPARAM lParam)
03368 {
03369 switch(uMsg)
03370 {
03371 case WM_CREATE:
03372
03373 odAppMenu.Init(hWnd, menuBar);
03374
03375
03376 odAppMenu.SetItemImage(appInstance, ID_FILE_OPENSCRIPT, IDB_SCRIPT);
03377 odAppMenu.SetItemImage(appInstance, ID_FILE_CAPTUREIMAGE, IDB_CAMERA);
03378 odAppMenu.SetItemImage(appInstance, ID_FILE_CAPTUREMOVIE, IDB_CAMCORDER);
03379 odAppMenu.SetItemImage(appInstance, ID_FILE_EXIT, IDB_EXIT);
03380 odAppMenu.SetItemImage(appInstance, ID_TIME_SETTIME, IDB_CLOCK);
03381 odAppMenu.SetItemImage(appInstance, ID_TIME_FREEZE, IDB_STOP);
03382 odAppMenu.SetItemImage(appInstance, ID_RENDER_VIEWOPTIONS, IDB_SUNGLASSES);
03383 odAppMenu.SetItemImage(appInstance, ID_RENDER_LOCATIONS, IDB_GLOBE);
03384 odAppMenu.SetItemImage(appInstance, ID_HELP_RUNDEMO, IDB_SCRIPT);
03385 odAppMenu.SetItemImage(appInstance, ID_HELP_CONTROLS, IDB_CONFIG);
03386 odAppMenu.SetItemImage(appInstance, ID_HELP_ABOUT, IDB_ABOUT);
03387
03388 DragAcceptFiles(hWnd, TRUE);
03389 break;
03390
03391 case WM_DROPFILES:
03392 break;
03393
03394 case WM_MEASUREITEM:
03395 odAppMenu.MeasureItem(hWnd, lParam);
03396 return TRUE;
03397
03398 case WM_DRAWITEM:
03399 odAppMenu.DrawItem(hWnd, lParam);
03400 return TRUE;
03401
03402 case WM_MOUSEMOVE:
03403 {
03404 int x, y;
03405 x = LOWORD(lParam);
03406 y = HIWORD(lParam);
03407 appCore->mouseMove((float) x, (float) y);
03408
03409 if ((wParam & (MK_LBUTTON | MK_RBUTTON)) != 0)
03410 {
03411 #ifdef INFINITE_MOUSE
03412
03413
03414
03415
03416
03417 POINT pt;
03418 pt.x = lastX;
03419 pt.y = lastY;
03420 ClientToScreen(hWnd, &pt);
03421
03422
03423
03424
03425
03426
03427 if (ignoreNextMoveEvent)
03428 {
03429
03430
03431
03432
03433
03434 ignoreNextMoveEvent = false;
03435 }
03436 else if (cursorVisible)
03437 {
03438
03439 ShowCursor(FALSE);
03440 cursorVisible = false;
03441
03442
03443 saveCursorPos = pt;
03444
03445
03446 RECT rect;
03447 GetClientRect(hWnd, &rect);
03448 POINT center;
03449 center.x = (rect.right - rect.left) / 2;
03450 center.y = (rect.bottom - rect.top) / 2;
03451
03452
03453 x = center.x + (x - lastX);
03454 y = center.y + (y - lastY);
03455 lastX = center.x;
03456 lastY = center.y;
03457
03458 ClientToScreen(hWnd, ¢er);
03459 SetCursorPos(center.x, center.y);
03460 }
03461 else
03462 {
03463 if (x - lastX != 0 || y - lastY != 0)
03464 SetCursorPos(pt.x, pt.y);
03465 }
03466 #else
03467 lastX = x;
03468 lastY = y;
03469 #endif // INFINITE_MOUSE
03470 }
03471
03472 int buttons = 0;
03473 if ((wParam & MK_LBUTTON) != 0)
03474 buttons |= CelestiaCore::LeftButton;
03475 if ((wParam & MK_RBUTTON) != 0)
03476 buttons |= CelestiaCore::RightButton;
03477 if ((wParam & MK_MBUTTON) != 0)
03478 buttons |= CelestiaCore::MiddleButton;
03479 if ((wParam & MK_SHIFT) != 0)
03480 buttons |= CelestiaCore::ShiftKey;
03481 if ((wParam & MK_CONTROL) != 0)
03482 buttons |= CelestiaCore::ControlKey;
03483 appCore->mouseMove((float) (x - lastX), (float) (y - lastY), buttons);
03484
03485 if (currentScreenMode != 0)
03486 {
03487 if (hideMenuBar && y < 10)
03488 {
03489 SetMenu(mainWindow, menuBar);
03490 hideMenuBar = false;
03491 }
03492 else if (!hideMenuBar && y >= 10)
03493 {
03494 SetMenu(mainWindow, NULL);
03495 hideMenuBar = true;
03496 }
03497 }
03498 }
03499
03500 break;
03501
03502 case WM_LBUTTONDOWN:
03503 lastX = LOWORD(lParam);
03504 lastY = HIWORD(lParam);
03505 appCore->mouseButtonDown(LOWORD(lParam), HIWORD(lParam),
03506 CelestiaCore::LeftButton);
03507 break;
03508 case WM_RBUTTONDOWN:
03509 lastX = LOWORD(lParam);
03510 lastY = HIWORD(lParam);
03511 appCore->mouseButtonDown(LOWORD(lParam), HIWORD(lParam),
03512 CelestiaCore::RightButton);
03513 break;
03514 case WM_MBUTTONDOWN:
03515 lastX = LOWORD(lParam);
03516 lastY = HIWORD(lParam);
03517 appCore->mouseButtonDown(LOWORD(lParam), HIWORD(lParam),
03518 CelestiaCore::MiddleButton);
03519 break;
03520
03521 case WM_LBUTTONUP:
03522 if (!cursorVisible)
03523 RestoreCursor();
03524 appCore->mouseButtonUp(LOWORD(lParam), HIWORD(lParam),
03525 CelestiaCore::LeftButton);
03526 break;
03527
03528 case WM_RBUTTONUP:
03529 if (!cursorVisible)
03530 RestoreCursor();
03531 appCore->mouseButtonUp(LOWORD(lParam), HIWORD(lParam),
03532 CelestiaCore::RightButton);
03533 break;
03534
03535 case WM_MBUTTONUP:
03536 lastX = LOWORD(lParam);
03537 lastY = HIWORD(lParam);
03538 appCore->mouseButtonUp(LOWORD(lParam), HIWORD(lParam),
03539 CelestiaCore::MiddleButton);
03540 break;
03541
03542 case WM_MOUSEWHEEL:
03543 {
03544 int modifiers = 0;
03545 if ((wParam & MK_SHIFT) != 0)
03546 modifiers |= CelestiaCore::ShiftKey;
03547 appCore->mouseWheel((short) HIWORD(wParam) > 0 ? -1.0f : 1.0f,
03548 modifiers);
03549 }
03550 break;
03551
03552 case WM_KEYDOWN:
03553 switch (wParam)
03554 {
03555 case VK_ESCAPE:
03556 appCore->charEntered('\033');
03557 break;
03558 case VK_INSERT:
03559 case 'C':
03560 if ((GetKeyState(VK_LCONTROL) | GetKeyState(VK_RCONTROL)) & 0x8000)
03561 {
03562 CopyStateURLToClipboard();
03563 appCore->flash("Copied URL");
03564 }
03565 break;
03566
03567 default:
03568 handleKey(wParam, true);
03569 break;
03570 }
03571 break;
03572
03573 case WM_KEYUP:
03574 handleKey(wParam, false);
03575 break;
03576
03577 case WM_CHAR:
03578 {
03579
03580
03581
03582
03583 char cScanCode = (char) (HIWORD(lParam) & 0xFF);
03584 if((cScanCode >= 71 && cScanCode <= 73) ||
03585 (cScanCode >= 75 && cScanCode <= 77) ||
03586 (cScanCode >= 79 && cScanCode <= 83))
03587 {
03588 break;
03589 }
03590
03591 int charCode = (char) wParam;
03592 int modifiers = 0;
03593 if (GetKeyState(VK_SHIFT) & 0x8000)
03594 modifiers |= CelestiaCore::ShiftKey;
03595
03596
03597 if (charCode == '\011' && (modifiers & CelestiaCore::ShiftKey))
03598 charCode = CelestiaCore::Key_BackTab;
03599
03600 Renderer* r = appCore->getRenderer();
03601 int oldRenderFlags = r->getRenderFlags();
03602 int oldLabelMode = r->getLabelMode();
03603
03604 Renderer::StarStyle oldStarStyle = r->getStarStyle();
03605 appCore->charEntered(charCode, modifiers);
03606 if (r->getRenderFlags() != oldRenderFlags ||
03607 r->getLabelMode() != oldLabelMode ||
03608 r->getStarStyle() != oldStarStyle)
03609 {
03610 syncMenusWithRendererState();
03611 }
03612 }
03613 break;
03614
03615 case WM_COPYDATA:
03616
03617
03618 {
03619 COPYDATASTRUCT* cd = reinterpret_cast<COPYDATASTRUCT*>(lParam);
03620 if (cd != NULL && cd->lpData != NULL)
03621 {
03622 char* urlChars = reinterpret_cast<char*>(cd->lpData);
03623 if (cd->cbData > 3)
03624 {
03625 string urlString(urlChars, cd->cbData);
03626
03627 if (!urlString.substr(0,4).compare("cel:"))
03628 {
03629 appCore->flash("Loading URL");
03630 Url url(string(urlString), appCore);
03631 url.goTo();
03632 }
03633 else if (DetermineFileType(urlString) == Content_CelestiaScript)
03634 {
03635 appCore->runScript(urlString);
03636 }
03637 else
03638 {
03639 ifstream scriptfile(urlString.c_str());
03640 if (!scriptfile.good())
03641 {
03642 appCore->flash("Error opening script");
03643 }
03644 else
03645 {
03646
03647
03648 CommandParser parser(scriptfile);
03649 CommandSequence* script = parser.parse();
03650 if (script == NULL)
03651 {
03652 const vector<string>* errors = parser.getErrors();
03653 const char* errorMsg = "";
03654 if (errors->size() > 0)
03655 {
03656 errorMsg = (*errors)[0].c_str();
03657 appCore->flash(errorMsg);
03658 }
03659 else
03660 {
03661 appCore->flash("Error loading script");
03662 }
03663 }
03664 else
03665 {
03666 appCore->flash("Running script");
03667 appCore->runScript(script);
03668 }
03669 }
03670 }
03671 }
03672 }
03673 }
03674 break;
03675
03676 case WM_COMMAND:
03677 switch (LOWORD(wParam))
03678 {
03679 case ID_NAVIGATION_CENTER:
03680 appCore->charEntered('c');
03681 break;
03682 case ID_NAVIGATION_GOTO:
03683 appCore->charEntered('G');
03684 break;
03685 case ID_NAVIGATION_FOLLOW:
03686 appCore->charEntered('F');
03687 break;
03688 case ID_NAVIGATION_SYNCORBIT:
03689 appCore->charEntered('Y');
03690 break;
03691 case ID_NAVIGATION_TRACK:
03692 appCore->charEntered('T');
03693 break;
03694 case ID_NAVIGATION_HOME:
03695 appCore->charEntered('H');
03696 break;
03697 case ID_NAVIGATION_SELECT:
03698 DialogBox(appInstance, MAKEINTRESOURCE(IDD_FINDOBJECT), hWnd, FindObjectProc);
03699 break;
03700 case ID_NAVIGATION_GOTO_OBJECT:
03701 if (gotoObjectDlg == NULL)
03702 gotoObjectDlg = new GotoObjectDialog(appInstance, hWnd, appCore);
03703 break;
03704 case IDCLOSE:
03705 if (reinterpret_cast<LPARAM>(gotoObjectDlg) == lParam &&
03706 gotoObjectDlg != NULL)
03707 {
03708 delete gotoObjectDlg;
03709 gotoObjectDlg = NULL;
03710 }
03711 else if (reinterpret_cast<LPARAM>(tourGuide) == lParam &&
03712 tourGuide != NULL)
03713 {
03714 delete tourGuide;
03715 tourGuide = NULL;
03716 }
03717 else if (reinterpret_cast<LPARAM>(starBrowser) == lParam &&
03718 starBrowser != NULL)
03719 {
03720 delete starBrowser;
03721 starBrowser = NULL;
03722 }
03723 else if (reinterpret_cast<LPARAM>(solarSystemBrowser) == lParam &&
03724 solarSystemBrowser != NULL)
03725 {
03726 delete solarSystemBrowser;
03727 solarSystemBrowser = NULL;
03728 }
03729 else if (reinterpret_cast<LPARAM>(viewOptionsDlg) == lParam &&
03730 viewOptionsDlg != NULL)
03731 {
03732 delete viewOptionsDlg;
03733 viewOptionsDlg = NULL;
03734 }
03735 else if (reinterpret_cast<LPARAM>(eclipseFinder) == lParam &&
03736 eclipseFinder != NULL)
03737 {
03738 delete eclipseFinder;
03739 eclipseFinder = NULL;
03740 }
03741 else if (reinterpret_cast<LPARAM>(locationsDlg) == lParam &&
03742 locationsDlg != NULL)
03743 {
03744 delete locationsDlg;
03745 locationsDlg = NULL;
03746 }
03747 break;
03748
03749 case ID_NAVIGATION_TOURGUIDE:
03750 if (tourGuide == NULL)
03751 tourGuide = new TourGuide(appInstance, hWnd, appCore);
03752 break;
03753
03754 case ID_NAVIGATION_SSBROWSER:
03755 if (solarSystemBrowser == NULL)
03756 solarSystemBrowser = new SolarSystemBrowser(appInstance, hWnd, appCore);
03757 break;
03758
03759 case ID_NAVIGATION_STARBROWSER:
03760 if (starBrowser == NULL)
03761 starBrowser = new StarBrowser(appInstance, hWnd, appCore);
03762 break;
03763
03764 case ID_NAVIGATION_ECLIPSEFINDER:
03765 if (eclipseFinder == NULL)
03766 eclipseFinder = new EclipseFinderDialog(appInstance, hWnd, appCore);
03767 break;
03768
03769 case ID_RENDER_DISPLAYMODE:
03770 newScreenMode = currentScreenMode;
03771 CreateDialogParam(appInstance,
03772 MAKEINTRESOURCE(IDD_DISPLAYMODE),
03773 hWnd,
03774 SelectDisplayModeProc,
03775 NULL);
03776 break;
03777
03778 case ID_RENDER_FULLSCREEN:
03779 if (currentScreenMode == 0)
03780 newScreenMode = lastFullScreenMode;
03781 else
03782 newScreenMode = 0;
03783 break;
03784
03785 case ID_RENDER_VIEWOPTIONS:
03786 if (viewOptionsDlg == NULL)
03787 viewOptionsDlg = new ViewOptionsDialog(appInstance, hWnd, appCore);
03788 break;
03789
03790 case ID_RENDER_LOCATIONS:
03791 if (locationsDlg == NULL)
03792 locationsDlg = new LocationsDialog(appInstance, hWnd, appCore);
03793 break;
03794
03795 case ID_RENDER_MORESTARS:
03796 appCore->charEntered(']');
03797 break;
03798
03799 case ID_RENDER_FEWERSTARS:
03800 appCore->charEntered('[');
03801 break;
03802
03803 case ID_RENDER_AUTOMAG:
03804 appCore->charEntered('\031');
03805 syncMenusWithRendererState();
03806 break;
03807
03808 case ID_RENDER_AMBIENTLIGHT_NONE:
03809 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_NONE, MF_CHECKED);
03810 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_LOW, MF_UNCHECKED);
03811 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_MEDIUM, MF_UNCHECKED);
03812 appCore->getRenderer()->setAmbientLightLevel(0.0f);
03813 break;
03814 case ID_RENDER_AMBIENTLIGHT_LOW:
03815 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_NONE, MF_UNCHECKED);
03816 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_LOW, MF_CHECKED);
03817 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_MEDIUM, MF_UNCHECKED);
03818 appCore->getRenderer()->setAmbientLightLevel(0.1f);
03819 break;
03820 case ID_RENDER_AMBIENTLIGHT_MEDIUM:
03821 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_NONE, MF_UNCHECKED);
03822 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_LOW, MF_UNCHECKED);
03823 CheckMenuItem(menuBar, ID_RENDER_AMBIENTLIGHT_MEDIUM, MF_CHECKED);
03824 appCore->getRenderer()->setAmbientLightLevel(0.25f);
03825 break;
03826
03827 case ID_RENDER_STARSTYLE_FUZZY:
03828 appCore->getRenderer()->setStarStyle(Renderer::FuzzyPointStars);
03829 syncMenusWithRendererState();
03830 break;
03831
03832 case ID_RENDER_STARSTYLE_POINTS:
03833 appCore->getRenderer()->setStarStyle(Renderer::PointStars);
03834 syncMenusWithRendererState();
03835 break;
03836
03837 case ID_RENDER_STARSTYLE_DISCS:
03838 appCore->getRenderer()->setStarStyle(Renderer::ScaledDiscStars);
03839 syncMenusWithRendererState();
03840 break;
03841
03842 case ID_RENDER_ANTIALIASING:
03843 appCore->charEntered('\030');
03844 syncMenusWithRendererState();
03845 break;
03846
03847 case ID_TIME_FASTER:
03848 appCore->charEntered('L');
03849 break;
03850 case ID_TIME_SLOWER:
03851 appCore->charEntered('K');
03852 break;
03853 case ID_TIME_REALTIME:
03854 appCore->charEntered('\\');
03855 break;
03856
03857 case ID_TIME_FREEZE:
03858 appCore->charEntered(' ');
03859 break;
03860 case ID_TIME_REVERSE:
03861 appCore->charEntered('J');
03862 break;
03863 case ID_TIME_SETTIME:
03864 ShowSetTimeDialog(appInstance, hWnd, appCore);
03865
03866
03867
03868 if (appCore->getTimeZoneBias() == 0)
03869 CheckMenuItem(menuBar, ID_TIME_SHOWLOCAL, MF_UNCHECKED);
03870 else
03871 CheckMenuItem(menuBar, ID_TIME_SHOWLOCAL, MF_CHECKED);
03872 break;
03873 case ID_TIME_SHOWLOCAL:
03874 if (ToggleMenuItem(menuBar, ID_TIME_SHOWLOCAL))
03875 ShowLocalTime(appCore);
03876 else
03877 ShowUniversalTime(appCore);
03878 break;
03879
03880 case ID_VIEW_HSPLIT:
03881 appCore->splitView(View::HorizontalSplit);
03882 break;
03883
03884 case ID_VIEW_VSPLIT:
03885 appCore->splitView(View::VerticalSplit);
03886 break;
03887
03888 case ID_VIEW_SINGLE:
03889 appCore->singleView();
03890 break;
03891
03892 case ID_VIEW_DELETE_ACTIVE:
03893 appCore->deleteView();
03894 break;
03895
03896 case ID_VIEW_SHOW_FRAMES:
03897 appCore->setFramesVisible(!appCore->getFramesVisible());
03898 syncMenusWithRendererState();
03899 break;
03900
03901 case ID_VIEW_SYNC_TIME:
03902 {
03903 Simulation* sim = appCore->getSimulation();
03904 sim->setSyncTime(!sim->getSyncTime());
03905 if (sim->getSyncTime())
03906 sim->synchronizeTime();
03907 syncMenusWithRendererState();
03908 }
03909 break;
03910
03911 case ID_BOOKMARKS_ADDBOOKMARK:
03912 DialogBox(appInstance, MAKEINTRESOURCE(IDD_ADDBOOKMARK), hWnd, AddBookmarkProc);
03913 break;
03914
03915 case ID_BOOKMARKS_ORGANIZE:
03916 DialogBox(appInstance, MAKEINTRESOURCE(IDD_ORGANIZE_BOOKMARKS), hWnd, OrganizeBookmarksProc);
03917 break;
03918
03919 case ID_HELP_RUNDEMO:
03920 appCore->charEntered('D');
03921 break;
03922
03923 case ID_HELP_CONTROLS:
03924 CreateDialogParam(appInstance,
03925 MAKEINTRESOURCE(IDD_CONTROLSHELP),
03926 hWnd,
03927 ControlsHelpProc,
03928 NULL);
03929 break;
03930
03931 case ID_HELP_ABOUT:
03932 DialogBox(appInstance, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);
03933 break;
03934
03935 case ID_HELP_GLINFO:
03936 DialogBox(appInstance, MAKEINTRESOURCE(IDD_GLINFO), hWnd, GLInfoProc);
03937 break;
03938
03939 case ID_HELP_LICENSE:
03940 DialogBox(appInstance, MAKEINTRESOURCE(IDD_LICENSE), hWnd, LicenseProc);
03941 break;
03942
03943 case ID_INFO:
03944 ShowWWWInfo(appCore->getSimulation()->getSelection());
03945 break;
03946
03947 case ID_FILE_OPENSCRIPT:
03948 HandleOpenScript(hWnd, appCore);
03949 break;
03950
03951 case ID_FILE_CAPTUREIMAGE:
03952 HandleCaptureImage(hWnd);
03953 break;
03954
03955 case ID_FILE_CAPTUREMOVIE:
03956 HandleCaptureMovie(hWnd);
03957 break;
03958
03959 case ID_FILE_EXIT:
03960 SendMessage(hWnd, WM_CLOSE, 0, 0);
03961 break;
03962
03963 case ID_GOTO_URL:
03964 {
03965
03966
03967 char* urlString = reinterpret_cast<char*>(lParam);
03968 if (urlString != NULL)
03969 {
03970 appCore->flash(string("URL: ") + string(urlString));
03971 Url url(string(urlString), appCore);
03972 url.goTo();
03973 }
03974 }
03975 break;
03976
03977 case ID_TOOLS_MARK:
03978 {
03979 Simulation* sim = appCore->getSimulation();
03980 if (sim->getUniverse() != NULL)
03981 {
03982 sim->getUniverse()->markObject(sim->getSelection(),
03983 10.0f,
03984 Color(0.0f, 1.0f, 0.0f, 0.9f),
03985 Marker::Diamond,
03986 1);
03987 }
03988 }
03989 break;
03990
03991 case ID_TOOLS_UNMARK:
03992 {
03993 Simulation* sim = appCore->getSimulation();
03994 if (sim->getUniverse() != NULL)
03995 sim->getUniverse()->unmarkObject(sim->getSelection(), 1);
03996 }
03997 break;
03998
03999 default:
04000 {
04001 const FavoritesList* favorites = appCore->getFavorites();
04002 if (favorites != NULL &&
04003 LOWORD(wParam) >= ID_BOOKMARKS_FIRSTBOOKMARK &&
04004 LOWORD(wParam) - ID_BOOKMARKS_FIRSTBOOKMARK < (int) favorites->size())
04005 {
04006 int whichFavorite = LOWORD(wParam) - ID_BOOKMARKS_FIRSTBOOKMARK;
04007 appCore->activateFavorite(*(*favorites)[whichFavorite]);
04008 }
04009 else if (LOWORD(wParam) >= MENU_CHOOSE_PLANET &&
04010 LOWORD(wParam) < MENU_CHOOSE_PLANET + 1000)
04011 {
04012
04013 Selection sel = appCore->getSimulation()->getSelection();
04014 switch (sel.getType())
04015 {
04016 case Selection::Type_Star:
04017 appCore->getSimulation()->selectPlanet(LOWORD(wParam) - MENU_CHOOSE_PLANET);
04018 break;
04019
04020 case Selection::Type_Body:
04021 {
04022 PlanetarySystem* satellites = (PlanetarySystem*) sel.body()->getSatellites();
04023 appCore->getSimulation()->setSelection(Selection(satellites->getBody(LOWORD(wParam) - MENU_CHOOSE_PLANET)));
04024 break;
04025 }
04026
04027 case Selection::Type_DeepSky:
04028
04029
04030 break;
04031
04032 case Selection::Type_Location:
04033 break;
04034
04035 default:
04036 break;
04037 }
04038 }
04039 else if (LOWORD(wParam) >= MENU_CHOOSE_SURFACE &&
04040 LOWORD(wParam) < MENU_CHOOSE_SURFACE + 1000)
04041 {
04042
04043 Selection sel = appCore->getSimulation()->getSelection();
04044 if (sel.body() != NULL)
04045 {
04046 int index = (int) LOWORD(wParam) - MENU_CHOOSE_SURFACE - 1;
04047 vector<string>* surfNames = sel.body()->getAlternateSurfaceNames();
04048 if (surfNames != NULL)
04049 {
04050 string surfName;
04051 if (index >= 0 && index < (int) surfNames->size())
04052 surfName = surfNames->at(index);
04053 appCore->getSimulation()->getActiveObserver()->setDisplayedSurface(surfName);
04054 delete surfNames;
04055 }
04056 }
04057 }
04058 }
04059 break;
04060 }
04061 break;
04062
04063 case WM_CLOSE:
04064 PostQuitMessage(0);
04065 break;
04066
04067 case WM_SIZE:
04068 appCore->resize(LOWORD(lParam), HIWORD(lParam));
04069 break;
04070
04071 case WM_PAINT:
04072 if (bReady)
04073 {
04074 appCore->draw();
04075 SwapBuffers(deviceContext);
04076 ValidateRect(hWnd, NULL);
04077 }
04078 break;
04079
04080 default:
04081 return DefWindowProc( hWnd, uMsg, wParam, lParam );
04082 }
04083
04084 return 0;
04085 }