0ad/source/ps/GameSetup/Atlas.cpp
Ykkrosh cbafd43eea # Changed handling of command-line arguments.
* Added CmdLineArgs, which does the parsing then lets various pieces of
code check for whatever arguments they want.
 * Made Atlas exit out of main() cleanly, instead of calling exit()
itself.
 * Disabled the global exception-catching in unit tests, via a
entry_noSEH, so it doesn't make debugging harder.
 * Added nice printing of CStr in unit test failure messages, and added
comparison of vector vs constant array.

This was SVN commit r4688.
2006-12-09 14:39:52 +00:00

127 lines
3.5 KiB
C++

#include "precompiled.h"
#include "lib/posix.h"
#include "lib/lib.h"
#include "ps/GameSetup/CmdLineArgs.h"
#include "Atlas.h"
//----------------------------------------------------------------------------
// Atlas (map editor) integration
//----------------------------------------------------------------------------
static void* const ATLAS_SO_UNAVAILABLE = (void*)-1;
static void* atlas_so_handle = NULL;
// Calculate the correct AtlasUI DLL
// TODO Use path_util instead, get the actual path to the ps_dbg exe and append
// the library name.
// note: on Linux, lib is prepended to the SO file name and we need to add ./
// to make dlopen look in the current working directory
#if OS_UNIX
# define PREFIX "./lib"
#else
# define PREFIX ""
#endif
// since this SO exports a C++ interface, it is critical that
// compiler options are the same between app and SO; therefore,
// we need to go with the debug version in debug builds.
// note: on Windows, the extension is replaced with .dll by dlopen.
#ifndef NDEBUG
static const char* so_name = PREFIX "AtlasUI_dbg.so";
#else
static const char* so_name = PREFIX "AtlasUI.so";
#endif
// free reference to Atlas UI SO (avoids resource leak report)
void ATLAS_Shutdown()
{
// (avoid dlclose warnings)
if(atlas_so_handle != 0 && atlas_so_handle != ATLAS_SO_UNAVAILABLE)
dlclose(atlas_so_handle);
}
// return true if the Atlas UI shared object is available;
// used to disable the main menu editor button if not.
// note: this actually loads the SO, but that isn't expected to be slow.
// call ATLAS_Shutdown at exit to avoid leaking it.
static bool ATLAS_IsAvailable()
{
// first time: try to open Atlas UI shared object
// postcondition: atlas_so_handle valid or == ATLAS_SO_UNAVAILABLE.
if(atlas_so_handle == 0)
{
// we don't really care when relocations take place, but one of
// {RTLD_NOW, RTLD_LAZY} must be passed. go with the former because
// it is safer and matches the Windows load behavior.
const int flags = RTLD_LOCAL|RTLD_NOW;
atlas_so_handle = dlopen(so_name, flags);
// open failed (mostly likely SO not found)
if(!atlas_so_handle)
atlas_so_handle = ATLAS_SO_UNAVAILABLE;
}
return atlas_so_handle != ATLAS_SO_UNAVAILABLE;
}
enum AtlasRunFlags
{
// used by ATLAS_RunIfOnCmdLine; makes any error output go through
// DISPLAY_ERROR rather than a GUI dialog box (because GUI init was
// skipped to reduce load time).
ATLAS_NO_GUI = 1
};
// starts the Atlas UI.
static void ATLAS_Run(const CmdLineArgs& args, int flags = 0)
{
// first check if we can run at all
if(!ATLAS_IsAvailable())
{
if(flags & ATLAS_NO_GUI)
DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");
else
DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");// TODO: implement GUI error message
return;
}
// TODO (make nicer)
extern bool BeginAtlas(const CmdLineArgs& args, void* dll);
if (!BeginAtlas(args, atlas_so_handle))
{
debug_warn("Atlas loading failed");
return;
}
}
// starts the Atlas UI if an "-editor" switch is found on the command line.
// this is the alternative to starting the main menu and clicking on
// the editor button; it is much faster because it's called during early
// init and therefore skips GUI setup.
// notes:
// - GUI init still runs, but some GUI setup will be skipped since
// ATLAS_IsRunning() will return true.
bool ATLAS_RunIfOnCmdLine(const CmdLineArgs& args)
{
if (args.Has("editor"))
{
ATLAS_Run(args, ATLAS_NO_GUI);
return true;
}
return false;
}