2005-06-25 04:21:26 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
#include "GameLoop.h"
|
|
|
|
|
|
|
|
#include "MessagePasserImpl.h"
|
2005-06-25 04:21:26 +02:00
|
|
|
#include "Messages.h"
|
2005-06-28 01:04:34 +02:00
|
|
|
#include "handlers/MessageHandler.h"
|
2005-06-25 04:21:26 +02:00
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
#include "InputProcessor.h"
|
|
|
|
|
2005-06-25 04:21:26 +02:00
|
|
|
#include "lib/sdl.h"
|
|
|
|
#include "lib/ogl.h"
|
2005-07-03 18:25:48 +02:00
|
|
|
#include "lib/timer.h"
|
2005-06-25 04:21:26 +02:00
|
|
|
#include "ps/CLogger.h"
|
2005-06-28 01:04:34 +02:00
|
|
|
|
2005-06-25 04:21:26 +02:00
|
|
|
using namespace AtlasMessage;
|
|
|
|
|
|
|
|
extern void Render_();
|
|
|
|
|
|
|
|
extern "C" { __declspec(dllimport) int __stdcall SwapBuffers(void*); }
|
|
|
|
// HACK (and not exactly portable)
|
|
|
|
//
|
|
|
|
// (Er, actually that's what most of this file is. Oh well.)
|
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
// Loaded from DLL:
|
|
|
|
void (*Atlas_StartWindow)(wchar_t* type);
|
|
|
|
void (*Atlas_SetMessagePasser)(MessagePasser<mCommand>*, MessagePasser<mInput>*);
|
2005-07-03 18:25:48 +02:00
|
|
|
|
|
|
|
static MessagePasserImpl<mCommand> msgPasser_Command;
|
|
|
|
static MessagePasserImpl<mInput> msgPasser_Input;
|
|
|
|
|
|
|
|
static InputProcessor g_Input;
|
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
static GameLoopState state;
|
|
|
|
GameLoopState* g_GameLoop = &state;
|
|
|
|
|
2005-06-25 04:21:26 +02:00
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
static void* LaunchWindow(void*)
|
|
|
|
{
|
|
|
|
Atlas_StartWindow(L"ScenarioEditor");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
bool BeginAtlas(int argc, char* argv[], void* dll)
|
2005-06-25 04:21:26 +02:00
|
|
|
{
|
2005-08-20 17:44:50 +02:00
|
|
|
*(void**)&Atlas_StartWindow = dlsym(dll, "Atlas_StartWindow");
|
|
|
|
*(void**)&Atlas_SetMessagePasser = dlsym(dll, "Atlas_SetMessagePasser");
|
|
|
|
|
|
|
|
if (!Atlas_StartWindow || !Atlas_SetMessagePasser)
|
|
|
|
return false;
|
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
// Pass our message handler to Atlas
|
2005-07-03 18:25:48 +02:00
|
|
|
Atlas_SetMessagePasser(&msgPasser_Command, &msgPasser_Input);
|
2005-06-25 04:21:26 +02:00
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
// Create a new thread, and launch the Atlas window inside that thread
|
2005-06-25 04:21:26 +02:00
|
|
|
pthread_t gameThread;
|
|
|
|
pthread_create(&gameThread, NULL, LaunchWindow, NULL);
|
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
state.argc = argc;
|
|
|
|
state.argv = argv;
|
|
|
|
state.running = true;
|
|
|
|
state.rendering = false;
|
|
|
|
state.currentDC = NULL;
|
2005-06-25 04:21:26 +02:00
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
while (state.running)
|
2005-06-25 04:21:26 +02:00
|
|
|
{
|
2005-07-03 18:25:48 +02:00
|
|
|
bool recent_activity = false;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// (TODO: Work out why these things have to be in this order (to avoid
|
|
|
|
// jumps when starting to move, etc)
|
|
|
|
|
|
|
|
// Calculate frame length
|
2005-06-25 04:21:26 +02:00
|
|
|
{
|
2005-07-03 18:25:48 +02:00
|
|
|
const double time = get_time();
|
|
|
|
static double last_time = time;
|
|
|
|
const float length = (float)(time-last_time);
|
|
|
|
last_time = time;
|
|
|
|
assert(length >= 0.0f);
|
|
|
|
// TODO: filter out big jumps, e.g. when having done a lot of slow
|
|
|
|
// processing in the last frame
|
|
|
|
state.frameLength = length;
|
|
|
|
}
|
2005-06-28 01:04:34 +02:00
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
if (g_Input.ProcessInput(&state))
|
|
|
|
recent_activity = true;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// if (!(in interactive-tool mode))
|
|
|
|
{
|
|
|
|
mCommand* msg;
|
2005-08-20 17:44:50 +02:00
|
|
|
while ((msg = msgPasser_Command.Retrieve()) != NULL)
|
2005-06-25 04:21:26 +02:00
|
|
|
{
|
2005-07-03 18:25:48 +02:00
|
|
|
recent_activity = true;
|
|
|
|
|
|
|
|
std::string name (msg->GetType());
|
|
|
|
|
|
|
|
if (name == "CommandString")
|
|
|
|
{
|
|
|
|
// Allow some laziness: For commands that don't need any data other
|
|
|
|
// than their name, we just use CommandString (and then need to
|
|
|
|
// construct a reference to the appropriate handler for the
|
|
|
|
// given string)
|
|
|
|
name += "_";
|
|
|
|
name += static_cast<mCommandString*>(msg)->name;
|
|
|
|
// use 'static_cast' when casting messages, to make it clear
|
|
|
|
// that it's slightly dangerous - we have to just assume that
|
|
|
|
// GetType is correct, since we can't use proper RTTI
|
|
|
|
}
|
2005-08-20 17:44:50 +02:00
|
|
|
msgHandlers::const_iterator it = GetMsgHandlers().find(name);
|
|
|
|
if (it != GetMsgHandlers().end())
|
2005-07-03 18:25:48 +02:00
|
|
|
{
|
|
|
|
it->second(msg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_warn("Unrecognised message");
|
|
|
|
// TODO: CLogger might not be initialised
|
|
|
|
LOG(ERROR, "atlas", "Unrecognised message (%s)", name.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
delete msg;
|
2005-06-25 04:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
// Exit, if desired
|
2005-06-28 01:04:34 +02:00
|
|
|
if (! state.running)
|
2005-06-25 04:21:26 +02:00
|
|
|
break;
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
// Now do the same (roughly), for input events:
|
|
|
|
{
|
|
|
|
mInput* msg;
|
2005-08-20 17:44:50 +02:00
|
|
|
while ((msg = msgPasser_Input.Retrieve()) != NULL)
|
2005-07-03 18:25:48 +02:00
|
|
|
{
|
|
|
|
recent_activity = true;
|
|
|
|
|
|
|
|
std::string name (msg->GetType());
|
2005-08-20 17:44:50 +02:00
|
|
|
msgHandlers::const_iterator it = GetMsgHandlers().find(name);
|
|
|
|
if (it != GetMsgHandlers().end())
|
2005-07-03 18:25:48 +02:00
|
|
|
{
|
|
|
|
it->second(msg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug_warn("Unrecognised message");
|
|
|
|
// TODO: CLogger might not be initialised
|
|
|
|
LOG(ERROR, "atlas", "Unrecognised message (%s)", name.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
delete msg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2005-06-28 01:04:34 +02:00
|
|
|
if (state.rendering)
|
2005-06-25 04:21:26 +02:00
|
|
|
{
|
|
|
|
Render_();
|
2005-07-03 18:25:48 +02:00
|
|
|
glFinish();
|
|
|
|
SwapBuffers((void*)state.currentDC);
|
2005-06-25 04:21:26 +02:00
|
|
|
}
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
// Be nice to the processor if we're not doing anything useful, but
|
|
|
|
// nice to the user if we are
|
|
|
|
if (! recent_activity)
|
|
|
|
SDL_Delay(100);
|
|
|
|
else
|
|
|
|
SDL_Delay(0);
|
|
|
|
// Probable TODO: allow interruption of sleep by incoming messages
|
2005-06-25 04:21:26 +02:00
|
|
|
}
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
// TODO: delete all remaining messages, to avoid memory leak warnings
|
|
|
|
|
2005-06-25 04:21:26 +02:00
|
|
|
pthread_join(gameThread, NULL);
|
2005-08-20 17:44:50 +02:00
|
|
|
|
|
|
|
exit(0);
|
2005-06-25 04:21:26 +02:00
|
|
|
}
|