1
0
forked from 0ad/0ad

host of changes to accommodate Atlas:

- input.cpp allows feeding in events from the outside (will be used by
main.cpp and Atlas msg loop)
- most of main.cpp split into ps/GameSetup.*
- main.cpp is now a "controller" that drives the game via SDL events
(Atlas is another such controller that can override main.cpp). it calls
GameSetup functions to set up and processes messages.
- add functions to import AtlasUI.dll automatically

also, the usual refactoring ;)

This was SVN commit r2622.
This commit is contained in:
janwas 2005-08-14 23:34:37 +00:00
parent c4cb65af72
commit dc027002c0
21 changed files with 1426 additions and 1446 deletions

View File

@ -490,7 +490,7 @@ Just commented out to make it more obvious it's not in use.
CVector3D rightwards = upwards.Cross(forwards);
// Click and drag to look around
if (mouseButtons[0])
if (mouse_buttons[0])
{
// Untranslate the camera, so it rotates around the correct point
CVector3D position = m_Camera.m_Orientation.GetTranslation();
@ -532,9 +532,9 @@ Just commented out to make it more obvious it's not in use.
static float height_delta = 0.0f;
if (mouseButtons[SDL_BUTTON_WHEELUP])
if (mouse_buttons[SDL_BUTTON_WHEELUP])
height_delta -= 4.0f;
else if (mouseButtons[SDL_BUTTON_WHEELDOWN])
else if (mouse_buttons[SDL_BUTTON_WHEELDOWN])
height_delta += 4.0f;
const float height_speed = 0.2f;
@ -566,8 +566,8 @@ Just commented out to make it more obvious it's not in use.
// RC - added ScEd style zoom in and out (actually moving camera, rather than fudging fov)
float dir=0;
if (mouseButtons[SDL_BUTTON_WHEELUP]) dir=-1;
else if (mouseButtons[SDL_BUTTON_WHEELDOWN]) dir=1;
if (mouse_buttons[SDL_BUTTON_WHEELUP]) dir=-1;
else if (mouse_buttons[SDL_BUTTON_WHEELDOWN]) dir=1;
float factor=dir*dir;
if (factor) {

View File

@ -6,6 +6,11 @@
#include "scripting/ScriptableObject.h"
// note: cannot forward declare "struct SDL_Event" - that triggers an
// internal error in VC7.1 at msc1.cpp(2701).
// we include the full header instead. *sigh*
#include "sdl.h"
class CGame;
class CGameAttributes;
class CWorld;
@ -97,4 +102,6 @@ public:
{ return &m_Camera; }
};
extern int game_view_handler(const SDL_Event* ev);
#endif

View File

@ -21,7 +21,7 @@ gee@pyro.nu
#define LOG_CATEGORY "gui"
extern bool keys[SDLK_LAST];
extern bool mouseButtons[5];
extern bool mouse_buttons[5];
using namespace std;
@ -562,7 +562,7 @@ void CInput::HandleMessage(const SGUIMessage &Message)
{
// Actually, first we need to re-check that the mouse button is
// really pressed (it can be released while outside the control.
if (!mouseButtons[SDL_BUTTON_LEFT])
if (!mouse_buttons[SDL_BUTTON_LEFT])
m_SelectingText = false;
else
m_iBufferPos = GetMouseHoveringTextPosition();

View File

@ -15,7 +15,7 @@
extern bool mouseButtons[5];
extern bool mouse_buttons[5];
extern int g_mouse_x, g_mouse_y;
bool HasClicked=false;
@ -124,13 +124,13 @@ void CMiniMap::Draw()
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
//Check for a click
if(mouseButtons[0]==true)
if(mouse_buttons[0]==true)
{
HasClicked=true;
}
//Check to see if left button is false (meaning it's been lifted)
if (mouseButtons[0]==false && HasClicked==true)
if (mouse_buttons[0]==false && HasClicked==true)
{

View File

@ -49,7 +49,7 @@ int in_add_handler(EventHandler handler)
// send event to each handler (newest first) until one returns true
static void dispatch_event(const SDL_Event* event)
void dispatch_event(const SDL_Event* event)
{
for(int i = handler_stack_top-1; i >= 0; i--)
{
@ -140,7 +140,20 @@ int in_playback(const char* fn)
}
void in_get_events()
void in_dispatch_event(const SDL_Event* event)
{
if(state == RECORD)
{
fwrite(&game_ticks, sizeof(u32), 1, f);
fwrite(event, sizeof(SDL_Event), 1, f);
}
dispatch_event(event);
}
void in_dispatch_recorded_events()
{
SDL_Event event;
@ -158,22 +171,6 @@ exit(0x73c07d);
}
next_event_time += time_adjust;
dispatch_event(&event);
}
// get new events
while(SDL_PollEvent(&event))
{
if(state == RECORD)
{
fwrite(&game_ticks, sizeof(u32), 1, f);
fwrite(&event, sizeof(SDL_Event), 1, f);
}
if(state == PLAYBACK)
if(event.type == SDL_KEYDOWN)
in_stop();
dispatch_event(&event);
in_dispatch_event(&event);
}
}

View File

@ -49,7 +49,10 @@ typedef int (*EventHandler)(const SDL_Event*);
// events are passed to other handlers if handler returns EV_PASS.
extern int in_add_handler(EventHandler handler);
extern void in_get_events(void);
// send event to each handler (newest first) until one returns true
extern void in_dispatch_event(const SDL_Event* event);
extern void in_dispatch_recorded_events();
extern int in_record(const char* fn);
extern int in_playback(const char* fn);

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,11 @@
#include "sdl.h"
#include "CStr.h"
// note: cannot forward declare "struct SDL_Event" - that triggers an
// internal error in VC7.1 at msc1.cpp(2701).
// we include the full header instead. *sigh*
#include "lib/sdl.h"
#ifndef CCONSOLE_H
#define CCONSOLE_H
@ -117,4 +122,6 @@ public:
extern CConsole* g_Console;
extern int conInputHandler(const SDL_Event* ev);
#endif

View File

@ -12,6 +12,10 @@
#define UNIDOUBLER_HEADER "CStr.cpp"
#include "UniDoubler.h"
#ifndef PERFORM_SELF_TEST
#define PERFORM_SELF_TEST 0
#endif
// Only include these function definitions in the first instance of CStr.cpp:
CStrW::CStrW(const CStr8 &asciStr) : std::wstring(asciStr.begin(), asciStr.end()) {}
@ -581,4 +585,37 @@ uint CStr::GetSerializedLength() const
#undef _totlower
#undef _totupper
//----------------------------------------------------------------------------
// built-in self test
//----------------------------------------------------------------------------
#if PERFORM_SELF_TEST
namespace test {
static void test1()
{
const wchar_t chr_utf16[] = { 0x12, 0xff, 0x1234, 0x3456, 0x5678, 0x7890, 0x9abc, 0xbcde, 0xfffe };
const unsigned char chr_utf8[] = { 0x12, 0xc3, 0xbf, 0xe1, 0x88, 0xb4, 0xe3, 0x91, 0x96, 0xe5, 0x99, 0xb8, 0xe7, 0xa2, 0x90, 0xe9, 0xaa, 0xbc, 0xeb, 0xb3, 0x9e, 0xef, 0xbf, 0xbe };
CStrW str_utf16 (chr_utf16, sizeof(chr_utf16)/sizeof(wchar_t));
CStr8 str_utf8 = str_utf16.ToUTF8();
debug_assert(str_utf8.length() == sizeof(chr_utf8));
debug_assert(memcmp(str_utf8.data(), chr_utf8, sizeof(chr_utf8)) == 0);
debug_assert(str_utf8.FromUTF8() == str_utf16);
}
static int run_tests()
{
test1();
return 0;
}
static int dummy = run_tests();
} // namespace test
#endif // #if PERFORM_SELF_TEST
#endif // CStr_CPP_FIRST

View File

@ -0,0 +1,115 @@
#include "precompiled.h"
#include "lib/posix.h"
#include "lib/lib.h"
#include "Atlas.h"
//----------------------------------------------------------------------------
// Atlas (map editor) integration
//----------------------------------------------------------------------------
static void* const ATLAS_SO_UNAVAILABLE = (void*)-1;
static void* atlas_so_handle;
// 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)
{
// 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
const char* so_name = "AtlasUI_d.so";
#else
const char* so_name = "AtlasUI.so";
#endif
// we don't care when relocations take place because this SO contains
// very few symbols, so RTLD_LAZY or RTLD_NOW aren't needed.
const int flags = RTLD_LOCAL;
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(int argc, char* argv[], 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;
}
void(*pStartWindow)(int argc, char* argv[]);
*(void**)&pStartWindow = dlsym(atlas_so_handle, "_StartWindow");
pStartWindow(argc, argv);
}
// 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.
// - could be merged into CFG_ParseCommandLineArgs, because that appears
// to be called early enough. it's not really worth it because this
// code is quite simple and we thus avoid startup order dependency.
void ATLAS_RunIfOnCmdLine(int argc, char* argv[])
{
for(int i = 1; i < argc; i++) // skip program name argument
{
if(!strcmp(argv[i], "-editor"))
{
// don't bother removing this param (unnecessary)
ATLAS_Run(argc, argv, ATLAS_NO_GUI);
break;
}
}
}

View File

@ -0,0 +1,8 @@
// free reference to Atlas UI SO (avoids resource leak report)
extern void ATLAS_Shutdown();
// 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.
extern void ATLAS_RunIfOnCmdLine(int argc, char* argv[]);

View File

@ -0,0 +1,186 @@
#include "precompiled.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/CConsole.h"
#include "lib/timer.h"
#include "lib/res/sound/snd.h"
#include "lib/res/file/vfs.h"
#include "Config.h"
#define LOG_CATEGORY "config"
CStr g_CursorName = "test";
CStr g_ActiveProfile = "default";
// flag to disable extended GL extensions until fix found - specifically, crashes
// using VBOs on laptop Radeon cards
bool g_NoGLVBO=false;
// flag to switch on shadows
bool g_Shadows=false;
// flag to switch off pbuffers
bool g_NoPBuffer=true;
// flag to switch on fixed frame timing (RC: I'm using this for profiling purposes)
bool g_FixedFrameTiming=false;
bool g_VSync = false;
float g_LodBias = 0.0f;
float g_Gamma = 1.0f;
bool g_EntGraph = false;
// graphics mode
int g_xres, g_yres;
int g_bpp;
int g_freq;
bool g_Quickstart=false;
//----------------------------------------------------------------------------
// config and profile
//----------------------------------------------------------------------------
static void LoadProfile( CStr profile )
{
CStr base = CStr( "profiles/" ) + profile;
g_ConfigDB.SetConfigFile(CFG_USER, true, base + "/settings/user.cfg");
g_ConfigDB.Reload(CFG_USER);
int max_history_lines = 50;
CFG_GET_USER_VAL("console.history.size", Int, max_history_lines);
g_Console->UseHistoryFile(base+"/settings/history", max_history_lines);
}
// Fill in the globals from the config files.
static void LoadGlobals()
{
CFG_GET_SYS_VAL("profile", String, g_ActiveProfile);
// Now load the profile before trying to retrieve the values of the rest of these.
LoadProfile( g_ActiveProfile );
CFG_GET_USER_VAL("xres", Int, g_xres);
CFG_GET_USER_VAL("yres", Int, g_yres);
CFG_GET_USER_VAL("vsync", Bool, g_VSync);
CFG_GET_USER_VAL("novbo", Bool, g_NoGLVBO);
CFG_GET_USER_VAL("shadows", Bool, g_Shadows);
CFG_GET_USER_VAL("lodbias", Float, g_LodBias);
float gain = -1.0f;
CFG_GET_USER_VAL("sound.mastergain", Float, gain);
if(gain > 0.0f)
WARN_ERR(snd_set_master_gain(gain));
LOG(NORMAL, LOG_CATEGORY, "g_x/yres is %dx%d", g_xres, g_yres);
LOG(NORMAL, LOG_CATEGORY, "Active profile is %s", g_ActiveProfile.c_str());
}
static void ParseCommandLineArgs(int argc, char* argv[])
{
for(int i = 1; i < argc; i++)
{
// this arg isn't an option; skip
if(argv[i][0] != '-')
continue;
char* name = argv[i]+1; // no leading '-'
// switch first letter of option name
switch(argv[i][1])
{
case 'c':
if(strcmp(name, "conf") == 0)
{
if(argc-i >= 1) // at least one arg left
{
i++;
char* arg = argv[i];
char* equ = strchr(arg, '=');
if(equ)
{
*equ = 0;
g_ConfigDB.CreateValue(CFG_COMMAND, arg)
->m_String = (equ+1);
}
}
}
break;
case 'e':
g_EntGraph = true;
break;
case 'f':
if(strncmp(name, "fixedframe", 10) == 0)
g_FixedFrameTiming=true;
break;
case 'g':
if(strncmp(name, "g=", 2) == 0)
{
g_Gamma = (float)atof(argv[i] + 3);
if(g_Gamma == 0.0f)
g_Gamma = 1.0f;
}
break;
case 'l':
if(strncmp(name, "listfiles", 9) == 0)
vfs_enable_file_listing(true);
break;
case 'n':
if(strncmp(name, "novbo", 5) == 0)
g_ConfigDB.CreateValue(CFG_COMMAND, "novbo")->m_String="true";
else if(strncmp(name, "nopbuffer", 9) == 0)
g_NoPBuffer = true;
break;
case 'q':
if(strncmp(name, "quickstart", 10) == 0)
g_Quickstart = true;
break;
case 's':
if(strncmp(name, "shadows", 7) == 0)
g_ConfigDB.CreateValue(CFG_COMMAND, "shadows")->m_String="true";
break;
case 'v':
g_ConfigDB.CreateValue(CFG_COMMAND, "vsync")->m_String="true";
break;
case 'x':
if(strncmp(name, "xres=", 6) == 0)
g_ConfigDB.CreateValue(CFG_COMMAND, "xres")->m_String=argv[i]+6;
break;
case 'y':
if(strncmp(name, "yres=", 6) == 0)
g_ConfigDB.CreateValue(CFG_COMMAND, "yres")->m_String=argv[i]+6;
break;
case 'p':
if(strncmp(name, "profile=", 8) == 0 )
g_ConfigDB.CreateValue(CFG_COMMAND, "profile")->m_String = argv[i]+9;
break;
} // switch
}
}
void CONFIG_Init(int argc, char* argv[])
{
debug_printf("CFG_Init &argc=%p &argv=%p\n", &argc, &argv);
TIMER(CONFIG_Init);
MICROLOG(L"init config");
new CConfigDB;
g_ConfigDB.SetConfigFile(CFG_SYSTEM, false, "config/system.cfg");
g_ConfigDB.Reload(CFG_SYSTEM);
g_ConfigDB.SetConfigFile(CFG_MOD, true, "config/mod.cfg");
// No point in reloading mod.cfg here - we haven't mounted mods yet
ParseCommandLineArgs(argc, argv);
// Collect information from system.cfg, the profile file,
// and any command-line overrides to fill in the globals.
LoadGlobals();
}

View File

@ -0,0 +1,27 @@
#include "CStr.h"
// flag to disable extended GL extensions until fix found - specifically, crashes
// using VBOs on laptop Radeon cards
extern bool g_NoGLVBO;
// flag to switch on shadows
extern bool g_Shadows;
// flag to switch off pbuffers
extern bool g_NoPBuffer;
// flag to switch on fixed frame timing (RC: I'm using this for profiling purposes)
extern bool g_FixedFrameTiming;
extern bool g_VSync;
extern float g_LodBias;
extern float g_Gamma;
extern bool g_EntGraph;
extern int g_xres, g_yres;
extern int g_bpp;
extern int g_freq;
extern bool g_active;
extern bool g_Quickstart;
extern CStr g_CursorName;
extern void CONFIG_Init(int argc, char* argv[]);

View File

@ -0,0 +1,847 @@
#include "precompiled.h"
#include "lib.h"
#include "lib/sdl.h"
#include "lib/ogl.h"
#include "lib/detect.h"
#include "lib/timer.h"
#include "lib/input.h"
#include "lib/res/res.h"
#include "lib/res/sound/snd.h"
#include "lib/res/graphics/tex.h"
#include "lib/res/graphics/cursor.h"
#include "ps/Profile.h"
#include "ps/ProfileViewer.h"
#include "ps/Loader.h"
#include "ps/Font.h"
#include "ps/CConsole.h"
#include "ps/Game.h"
#include "ps/Interact.h"
#include "ps/Hotkey.h"
#include "ps/ConfigDB.h"
#include "ps/CLogger.h"
#include "ps/i18n.h"
#include "ps/Overlay.h"
#include "ps/StringConvert.h"
#include "graphics/MapReader.h"
#include "graphics/Terrain.h"
#include "graphics/TextureManager.h"
#include "graphics/ObjectManager.h"
#include "graphics/SkeletonAnimManager.h"
#include "graphics/LightEnv.h"
#include "graphics/Model.h"
#include "graphics/UnitManager.h"
#include "graphics/MaterialManager.h"
#include "graphics/MeshManager.h"
#include "renderer/Renderer.h"
#include "simulation/BaseEntityCollection.h"
#include "simulation/Entity.h"
#include "simulation/EntityHandles.h"
#include "simulation/EntityManager.h"
#include "simulation/PathfindEngine.h"
#include "simulation/Scheduler.h"
#include "simulation/Projectile.h"
#include "scripting/ScriptingHost.h"
#include "scripting/GameEvents.h"
#include "scripting/JSInterface_Entity.h"
#include "scripting/JSInterface_BaseEntity.h"
#include "scripting/JSInterface_Vector3D.h"
#include "scripting/JSInterface_Camera.h"
#include "scripting/JSInterface_Selection.h"
#include "scripting/JSInterface_Console.h"
#include "scripting/JSCollection.h"
#include "scripting/DOMEvent.h"
#ifndef NO_GUI
# include "gui/scripting/JSInterface_IGUIObject.h"
# include "gui/scripting/JSInterface_GUITypes.h"
# include "gui/GUI.h"
#endif
#include "sound/CMusicPlayer.h"
#include "sound/JSI_Sound.h"
#include "Network/SessionManager.h"
#include "Network/Server.h"
#include "Network/Client.h"
#include "Atlas.h"
#include "Config.h"
#include "ps/System.h"
ERROR_GROUP(System);
ERROR_TYPE(System, SDLInitFailed);
ERROR_TYPE(System, VmodeFailed);
ERROR_TYPE(System, RequiredExtensionsMissing);
#define LOG_CATEGORY "gamesetup"
static int SetVideoMode(int w, int h, int bpp, bool fullscreen)
{
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
ulong flags = SDL_OPENGL;
if(fullscreen)
flags |= SDL_FULLSCREEN;
if(!SDL_SetVideoMode(w, h, bpp, flags))
return -1;
glViewport(0, 0, w, h);
#ifndef NO_GUI
g_GUI.UpdateResolution();
#endif
oglInit(); // required after each mode change
if(SDL_SetGamma(g_Gamma, g_Gamma, g_Gamma) < 0)
debug_warn("SDL_SetGamma failed");
return 0;
}
//----------------------------------------------------------------------------
// GUI integration
//----------------------------------------------------------------------------
void GUI_Init()
{
#ifndef NO_GUI
{TIMER(ps_gui_init);
g_GUI.Initialize();}
{TIMER(ps_gui_setup_xml);
g_GUI.LoadXMLFile("gui/test/setup.xml");}
{TIMER(ps_gui_styles_xml);
g_GUI.LoadXMLFile("gui/test/styles.xml");}
{TIMER(ps_gui_sprite1_xml);
g_GUI.LoadXMLFile("gui/test/sprite1.xml");}
// Atlas is running, we won't need these GUI pages (for now!
// what if Atlas switches to in-game mode?!)
// TODO: temporary hack until revised GUI structure is completed.
// if(ATLAS_IsRunning())
// return;
{TIMER(ps_gui_1);
g_GUI.LoadXMLFile("gui/test/1_init.xml");}
{TIMER(ps_gui_2);
g_GUI.LoadXMLFile("gui/test/2_mainmenu.xml");}
{TIMER(ps_gui_3);
g_GUI.LoadXMLFile("gui/test/3_loading.xml");}
{TIMER(ps_gui_4);
g_GUI.LoadXMLFile("gui/test/4_session.xml");}
{TIMER(ps_gui_6);
g_GUI.LoadXMLFile("gui/test/6_subwindows.xml");}
{TIMER(ps_gui_6_1);
g_GUI.LoadXMLFile("gui/test/6_1_manual.xml");}
{TIMER(ps_gui_6_2);
g_GUI.LoadXMLFile("gui/test/6_2_jukebox.xml");}
{TIMER(ps_gui_7);
g_GUI.LoadXMLFile("gui/test/7_atlas.xml");}
{TIMER(ps_gui_9);
g_GUI.LoadXMLFile("gui/test/9_global.xml");}
#endif
}
void GUI_Shutdown()
{
#ifndef NO_GUI
g_GUI.Destroy();
delete &g_GUI;
#endif
}
void GUI_ShowMainMenu()
{
}
// display progress / description in loading screen
void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
{
#ifndef NO_GUI
CStrW i18n_description = I18n::translate(pending_task);
JSString* js_desc = StringConvert::wstring_to_jsstring(g_ScriptingHost.getContext(), i18n_description);
g_ScriptingHost.SetGlobal("g_Progress", INT_TO_JSVAL(percent));
g_ScriptingHost.SetGlobal("g_LoadDescription", STRING_TO_JSVAL(js_desc));
g_GUI.SendEventToAll("progress");
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////
// RenderNoCull: render absolutely everything to a blank frame to force renderer
// to load required assets
static void RenderNoCull()
{
g_Renderer.BeginFrame();
if (g_Game)
g_Game->GetView()->RenderNoCull();
g_Renderer.FlushFrame();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
g_Renderer.EndFrame();
}
void Render()
{
MICROLOG(L"begin frame");
oglCheck();
#ifndef NO_GUI // HACK: because colour-parsing requires the GUI
CStr skystring = "61 193 255";
CFG_GET_USER_VAL("skycolor", String, skystring);
CColor skycol;
GUI<CColor>::ParseString(skystring, skycol);
g_Renderer.SetClearColor(skycol.Int());
#endif
// start new frame
g_Renderer.BeginFrame();
oglCheck();
if (g_Game && g_Game->IsGameStarted())
{
g_Game->GetView()->Render();
oglCheck();
MICROLOG(L"flush frame");
PROFILE_START( "flush frame" );
g_Renderer.FlushFrame();
PROFILE_END( "flush frame" );
glPushAttrib( GL_ENABLE_BIT );
glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D );
glDisable( GL_DEPTH_TEST );
if( g_EntGraph )
{
PROFILE( "render entity overlays" );
glColor3f( 1.0f, 0.0f, 1.0f );
MICROLOG(L"render entities");
g_EntityManager.renderAll(); // <-- collision outlines, pathing routes
}
PROFILE_START( "render selection" );
g_Mouseover.renderSelectionOutlines();
g_Selection.renderSelectionOutlines();
PROFILE_END( "render selection" );
glPopAttrib();
}
else
{
PROFILE_START( "flush frame" );
g_Renderer.FlushFrame();
PROFILE_END( "flush frame" );
}
oglCheck();
PROFILE_START( "render fonts" );
MICROLOG(L"render fonts");
// overlay mode
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PROFILE_END( "render fonts" );
oglCheck();
#ifndef NO_GUI
// Temp GUI message GeeTODO
glLoadIdentity();
MICROLOG(L"render GUI");
PROFILE_START( "render gui" );
g_GUI.Draw();
PROFILE_END( "render gui" );
#endif
oglCheck();
// Text:
// Use the GL_ALPHA texture as the alpha channel with a flat colouring
glDisable(GL_ALPHA_TEST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// Added --
glEnable(GL_TEXTURE_2D);
// -- GL
oglCheck();
{
PROFILE( "render console" );
glLoadIdentity();
MICROLOG(L"render console");
CFont font("console");
font.Bind();
g_Console->Render();
}
oglCheck();
// Profile information
PROFILE_START( "render profiling" );
RenderProfile();
PROFILE_END( "render profiling" );
oglCheck();
if (g_Game && g_Game->IsGameStarted())
{
PROFILE( "render selection overlays" );
g_Mouseover.renderOverlays();
g_Selection.renderOverlays();
}
oglCheck();
// Draw the cursor (or set the Windows cursor, on Windows)
cursor_draw(g_CursorName, g_mouse_x, g_mouse_y);
// restore
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
MICROLOG(L"end frame");
g_Renderer.EndFrame();
oglCheck();
}
static void InitScripting()
{
TIMER(InitScripting);
// Create the scripting host. This needs to be done before the GUI is created.
new ScriptingHost;
// It would be nice for onLoad code to be able to access the setTimeout() calls.
new CScheduler;
// Register the JavaScript interfaces with the runtime
CEntity::ScriptingInit();
CBaseEntity::ScriptingInit();
JSI_Sound::ScriptingInit();
CProfileNode::ScriptingInit();
#ifndef NO_GUI
JSI_IGUIObject::init();
JSI_GUITypes::init();
#endif
JSI_Vector3D::init();
EntityCollection::Init( "EntityCollection" );
SColour::ScriptingInit();
CPlayer::ScriptingInit();
PlayerCollection::Init( "PlayerCollection" );
CDamageType::ScriptingInit();
CJSComplexPropertyAccessor<CEntity>::ScriptingInit(); // <-- Doesn't really matter which we use, but we know CJSPropertyAccessor<T> is already being compiled for T = CEntity.
CScriptEvent::ScriptingInit();
CJSProgressTimer::ScriptingInit();
CProjectile::ScriptingInit();
g_ScriptingHost.DefineConstant( "ORDER_NONE", -1 );
g_ScriptingHost.DefineConstant( "ORDER_GOTO", CEntityOrder::ORDER_GOTO );
g_ScriptingHost.DefineConstant( "ORDER_PATROL", CEntityOrder::ORDER_PATROL );
g_ScriptingHost.DefineConstant( "ORDER_ATTACK", CEntityOrder::ORDER_ATTACK_MELEE );
g_ScriptingHost.DefineConstant( "ORDER_GATHER", CEntityOrder::ORDER_GATHER );
#define REG_JS_CONSTANT(_name) g_ScriptingHost.DefineConstant(#_name, _name)
REG_JS_CONSTANT(SDL_BUTTON_LEFT);
REG_JS_CONSTANT(SDL_BUTTON_MIDDLE);
REG_JS_CONSTANT(SDL_BUTTON_RIGHT);
REG_JS_CONSTANT(SDL_BUTTON_WHEELUP);
REG_JS_CONSTANT(SDL_BUTTON_WHEELDOWN);
#undef REG_JS_CONSTANT
CNetMessage::ScriptingInit();
JSI_Camera::init();
JSI_Console::init();
new CGameEvents;
}
static void InitVfs(const char* argv0)
{
TIMER(InitVfs);
// set current directory to "$game_dir/data".
// this is necessary because it is otherwise unknown,
// especially if run from a shortcut / symlink.
//
// "../data" is relative to the executable (in "$game_dir/system").
//
// rationale for data/ being root: untrusted scripts must not be
// allowed to overwrite critical game (or worse, OS) files.
// the VFS prevents any accesses to files above this directory.
int err = file_rel_chdir(argv0, "../data");
if(err < 0)
throw err;
{
vfs_init();
vfs_mount("", "mods/official", VFS_MOUNT_RECURSIVE|VFS_MOUNT_ARCHIVES|VFS_MOUNT_WATCH);
vfs_mount("screenshots/", "screenshots");
vfs_mount("profiles/", "profiles", VFS_MOUNT_RECURSIVE);
}
extern void vfs_dump_stats();
vfs_dump_stats();
// don't try vfs_display yet: SDL_Init hasn't yet redirected stdout
}
static void InitPs()
{
// console
{
TIMER(ps_console);
g_Console->UpdateScreenSize(g_xres, g_yres);
// Calculate and store the line spacing
CFont font("console");
g_Console->m_iFontHeight = font.GetLineSpacing();
// Offset by an arbitrary amount, to make it fit more nicely
g_Console->m_iFontOffset = 9;
}
// language and hotkeys
{
TIMER(ps_lang_hotkeys);
std::string lang = "english";
CFG_GET_SYS_VAL("language", String, lang);
I18n::LoadLanguage(lang.c_str());
loadHotkeys();
}
// GUI uses VFS, so this must come after VFS init.
GUI_Init();
}
static void InitInput()
{
// register input handlers
// This stack is constructed so the first added, will be the last
// one called. This is important, because each of the handlers
// has the potential to block events to go further down
// in the chain. I.e. the last one in the list added, is the
// only handler that can block all messages before they are
// processed.
in_add_handler(game_view_handler);
in_add_handler(interactInputHandler);
in_add_handler(conInputHandler);
in_add_handler(profilehandler);
in_add_handler(hotkeyInputHandler);
}
static void ShutdownPs()
{
GUI_Shutdown();
delete g_Console;
// disable the special Windows cursor, or free textures for OGL cursors
cursor_draw(0, g_mouse_x, g_mouse_y);
// close down Xerces if it was loaded
CXeromyces::Terminate();
// Unload the real language (since it depends on the scripting engine,
// which is going to be killed later) and use the English fallback messages
I18n::LoadLanguage(NULL);
}
static void InitRenderer()
{
TIMER(InitRenderer);
// create renderer
new CRenderer;
// set renderer options from command line options - NOVBO must be set before opening the renderer
g_Renderer.SetOptionBool(CRenderer::OPT_NOVBO,g_NoGLVBO);
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS,g_Shadows);
g_Renderer.SetOptionBool(CRenderer::OPT_NOPBUFFER,g_NoPBuffer);
g_Renderer.SetOptionFloat(CRenderer::OPT_LODBIAS, g_LodBias);
// create terrain related stuff
new CTextureManager;
// create the material manager
new CMaterialManager;
new CMeshManager;
// create actor related stuff
new CSkeletonAnimManager;
new CObjectManager;
new CUnitManager;
MICROLOG(L"init renderer");
g_Renderer.Open(g_xres,g_yres,g_bpp);
// Setup default lighting environment. Since the Renderer accesses the
// lighting environment through a pointer, this has to be done before
// the first Frame.
g_LightEnv.m_SunColor=RGBColor(1,1,1);
g_LightEnv.SetRotation(DEGTORAD(270));
g_LightEnv.SetElevation(DEGTORAD(45));
g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0);
g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f);
g_Renderer.SetLightEnv(&g_LightEnv);
// I haven't seen the camera affecting GUI rendering and such, but the
// viewport has to be updated according to the video mode
SViewPort vp;
vp.m_X=0;
vp.m_Y=0;
vp.m_Width=g_xres;
vp.m_Height=g_yres;
g_Renderer.SetViewport(vp);
}
static void InitSDL()
{
MICROLOG(L"init sdl");
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE) < 0)
{
LOG(ERROR, LOG_CATEGORY, "SDL library initialization failed: %s", SDL_GetError());
throw PSERROR_System_SDLInitFailed();
}
atexit(SDL_Quit);
SDL_EnableUNICODE(1);
}
void EndGame()
{
if (g_NetServer)
{
delete g_NetServer;
g_NetServer=NULL;
}
else if (g_NetClient)
{
delete g_NetClient;
g_NetClient=NULL;
}
delete g_Game;
g_Game=NULL;
}
void Shutdown()
{
MICROLOG(L"Shutdown");
ATLAS_Shutdown();
ShutdownPs(); // Must delete g_GUI before g_ScriptingHost
if (g_Game)
EndGame();
delete &g_Scheduler;
delete &g_SessionManager;
delete &g_Mouseover;
delete &g_Selection;
delete &g_Pathfinder;
// Managed by CWorld
// delete &g_EntityManager;
delete &g_GameAttributes;
delete &g_JSGameEvents;
delete &g_EntityTemplateCollection;
delete &g_ScriptingHost;
// destroy actor related stuff
delete &g_UnitMan;
delete &g_ObjMan;
delete &g_SkelAnimMan;
delete &g_MaterialManager;
delete &g_MeshManager;
// destroy terrain related stuff
delete &g_TexMan;
// destroy renderer
delete &g_Renderer;
delete &g_ConfigDB;
// Shut down the network loop
CSocketBase::Shutdown();
// Really shut down the i18n system. Any future calls
// to translate() will crash.
I18n::Shutdown();
snd_shutdown();
vfs_shutdown();
h_mgr_shutdown();
mem_shutdown();
debug_shutdown();
delete &g_Logger;
delete &g_Profiler;
}
// workaround for VC7 EBP-trashing bug, which confuses the stack trace code.
#if MSC_VERSION
# pragma optimize("", off)
#endif
void Init(int argc, char* argv[], bool setup_gfx = true)
{
debug_printf("INIT &argc=%p &argv=%p\n", &argc, &argv);
MICROLOG(L"Init");
debug_set_thread_name("main");
// If you ever want to catch a particular allocation:
//_CrtSetBreakAlloc(187);
// no longer set 24 bit (float) precision by default: for
// very long game uptimes (> 1 day; e.g. dedicated server),
// we need full precision when calculating the time.
// if there's a spot where we want to speed up divides|sqrts,
// we can temporarily change precision there.
// _control87(_PC_24, _MCW_PC);
// detects CPU clock frequency and capabilities, which are prerequisites
// for using the TSC as a timer (desirable due to its high resolution).
// do this before lengthy init so we can time those accurately.
get_cpu_info();
// Do this as soon as possible, because it chdirs
// and will mess up the error reporting if anything
// crashes before the working directory is set.
MICROLOG(L"init vfs");
const char* argv0 = argc? argv[0] : NULL;
// ScEd doesn't have a main(argc, argv), and so it has no argv. In that
// case, just pass NULL to InitVfs, which will work out the current
// directory for itself.
InitVfs(argv0);
// This must come after VFS init, which sets the current directory
// (required for finding our output log files).
new CLogger;
// Call LoadLanguage(NULL) to initialise the I18n system, but
// without loading an actual language file - translate() will
// just show the English key text, which is better than crashing
// from a null pointer when attempting to translate e.g. error messages.
// Real languages can only be loaded when the scripting system has
// been initialised.
//
// this uses LOG and must therefore come after CLogger init.
MICROLOG(L"init i18n");
I18n::LoadLanguage(NULL);
// should be done before the bulk of GUI init because it prevents
// most loads from happening (since ATLAS_IsRunning will return true).
ATLAS_RunIfOnCmdLine(argc, argv);
// Set up the console early, so that debugging
// messages can be logged to it. (The console's size
// and fonts are set later in InitPs())
g_Console = new CConsole();
if(setup_gfx)
InitSDL();
// preferred video mode = current desktop settings
// (command line params may override these)
get_cur_vmode(&g_xres, &g_yres, &g_bpp, &g_freq);
new CProfileManager; // before any script code
MICROLOG(L"init scripting");
InitScripting(); // before GUI
// g_ConfigDB, command line args, globals
CONFIG_Init(argc, argv);
// GUI is notified in SetVideoMode, so this must come before that.
#ifndef NO_GUI
new CGUI;
#endif
bool windowed = false;
CFG_GET_SYS_VAL("windowed", Bool, windowed);
if (setup_gfx)
{
MICROLOG(L"set vmode");
if(SetVideoMode(g_xres, g_yres, 32, !windowed) < 0)
{
LOG(ERROR, LOG_CATEGORY, "Could not set %dx%d graphics mode: %s", g_xres, g_yres, SDL_GetError());
throw PSERROR_System_VmodeFailed();
}
SDL_WM_SetCaption("0 A.D.", "0 A.D.");
}
oglCheck();
if(!g_Quickstart)
{
WriteSystemInfo();
vfs_display();
}
else
{
// speed up startup by disabling all sound
// (OpenAL init will be skipped).
// must be called before first snd_open.
snd_disable(true);
}
// (must come after SetVideoMode, since it calls oglInit)
const char* missing = oglHaveExtensions(0, "GL_ARB_multitexture", "GL_ARB_texture_env_combine", "GL_ARB_texture_env_dot3", 0);
if(missing)
{
wchar_t buf[500];
const wchar_t* fmt =
L"The %hs extension doesn't appear to be available on your computer. "
L"The game may still work, though - you are welcome to try at your own risk. "
L"If not or it doesn't look right, upgrade your graphics card.";
swprintf(buf, ARRAY_SIZE(buf), fmt, missing);
DISPLAY_ERROR(buf);
// TODO: i18n
}
// enable/disable VSync
// note: "GL_EXT_SWAP_CONTROL" is "historical" according to dox.
#if OS_WIN
if(oglHaveExtension("WGL_EXT_swap_control"))
wglSwapIntervalEXT(g_VSync? 1 : 0);
#endif
MICROLOG(L"init ps");
InitPs();
oglCheck();
InitRenderer();
TIMER(init_after_InitRenderer);
// This needs to be done after the renderer has loaded all its actors...
new CBaseEntityCollection;
// CEntityManager is managed by CWorld
//new CEntityManager;
new CPathfindEngine;
new CSelectedEntities;
new CMouseoverEntities;
new CSessionManager;
new CGameAttributes;
// Register a few Game/Network JS globals
g_ScriptingHost.SetGlobal("g_GameAttributes", OBJECT_TO_JSVAL(g_GameAttributes.GetScript()));
// Check for heap corruption after every allocation. Very, very slowly.
// (And it highlights the allocation just after the one you care about,
// so you need to run it again and tell it to break on the one before.)
// debug_heap_enable(DEBUG_HEAP_ALL);
InitInput();
oglCheck();
#ifndef NO_GUI
g_GUI.SendEventToAll("load");
#endif
if (setup_gfx)
{
MICROLOG(L"render blank");
// render everything to a blank frame to force renderer to load everything
RenderNoCull();
}
if (g_FixedFrameTiming) {
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
#if 0 // TOPDOWN
g_Camera.SetProjection(1.0f,10000.0f,DEGTORAD(90));
g_Camera.m_Orientation.SetIdentity();
g_Camera.m_Orientation.RotateX(DEGTORAD(90));
g_Camera.m_Orientation.Translate(CELL_SIZE*250*0.5, 250, CELL_SIZE*250*0.5);
#else // std view
g_Camera.SetProjection(1.0f,10000.0f,DEGTORAD(20));
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
g_Camera.m_Orientation.Translate(350, 350, -275);
#endif
g_Camera.UpdateFrustum();
}
}
#if MSC_VERSION
# pragma optimize("", on) // restore; see above.
#endif

View File

@ -0,0 +1,22 @@
//----------------------------------------------------------------------------
// GUI integration
//----------------------------------------------------------------------------
extern void GUI_Init();
extern void GUI_Shutdown();
extern void GUI_ShowMainMenu();
// display progress / description in loading screen
extern void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task);
extern void Render();
extern void Shutdown();
extern void Init(int argc, char* argv[], bool setup_gfx = true);

View File

@ -9,7 +9,7 @@
extern CConsole* g_Console;
extern bool keys[SDLK_LAST];
extern bool mouseButtons[5];
extern bool mouse_buttons[5];
bool unified[5];
/* SDL-type */
@ -424,7 +424,7 @@ int hotkeyInputHandler( const SDL_Event* ev )
}
else if( *itKey < UNIFIED_SHIFT )
{
if( mouseButtons[keyCode-SDLK_LAST] != rqdState ) accept = false;
if( mouse_buttons[keyCode-SDLK_LAST] != rqdState ) accept = false;
}
else
if( unified[keyCode-UNIFIED_SHIFT] != rqdState ) accept = false;
@ -484,7 +484,7 @@ int hotkeyInputHandler( const SDL_Event* ev )
}
else if( *itKey < UNIFIED_SHIFT )
{
if( mouseButtons[keyCode-SDLK_LAST] != rqdState ) accept = false;
if( mouse_buttons[keyCode-SDLK_LAST] != rqdState ) accept = false;
}
else
if( unified[keyCode-UNIFIED_SHIFT] != rqdState ) accept = false;
@ -548,7 +548,7 @@ int hotkeyInputHandler( const SDL_Event* ev )
}
else if( *itKey < UNIFIED_SHIFT )
{
if( !mouseButtons[(*itKey)-SDLK_LAST] ) accept = false;
if( !mouse_buttons[(*itKey)-SDLK_LAST] ) accept = false;
}
else
if( !unified[(*itKey)-UNIFIED_SHIFT] ) accept = false;

View File

@ -15,9 +15,12 @@
#include "timer.h"
#include "Loader.h"
#include "LoaderThunks.h"
#include "graphics/MapWriter.h"
#define LOG_CATEGORY "world"
// global light settings. this is not a member of CWorld because it is
// passed to the renderer before CWorld exists.
CLightEnv g_LightEnv;
void CWorld::Initialize(CGameAttributes *pAttribs)
@ -63,3 +66,9 @@ CWorld::~CWorld()
delete &m_EntityManager;
delete &m_ProjectileManager;
}
void CWorld::RewriteMap()
{
CMapWriter::RewriteAllMaps(&m_Terrain, &m_UnitManager, &g_LightEnv);
}

View File

@ -38,6 +38,8 @@ public:
*/
void Initialize(CGameAttributes *pGameAttributes);
// provided for JS _rewritemaps function
void RewriteMap();
inline CTerrain *GetTerrain()
{ return &m_Terrain; }
@ -56,4 +58,8 @@ private:
ERROR_SUBGROUP(Game, World);
ERROR_TYPE(Game_World, MapLoadFailed);
// rationale: see definition.
class CLightEnv;
extern CLightEnv g_LightEnv;
#endif

View File

@ -641,7 +641,7 @@ JSBool _rewriteMaps( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* UN
{
REQUIRE_NO_PARAMS(_rewriteMaps);
CMapWriter::RewriteAllMaps(g_Game->GetWorld()->GetTerrain(), g_Game->GetWorld()->GetUnitManager(), &g_LightEnv);
g_Game->GetWorld()->RewriteMap();
return JS_TRUE;
}

View File

@ -4,8 +4,6 @@
#include "ScriptingHost.h"
#include "LightEnv.h" // required by g_LightEnv declaration below.
// referenced by ScriptingHost.cpp
extern JSFunctionSpec ScriptFunctionTable[];
extern JSPropertySpec ScriptGlobalTable[];
@ -18,7 +16,6 @@ extern CStr g_CursorName;
extern void StartGame();
extern void EndGame();
// .. other
extern CLightEnv g_LightEnv;
#if OS_WIN
extern int GetVRAMInfo(int&, int&);
#endif

View File

@ -85,6 +85,10 @@ public:
static void ScriptingInit();
};
// made visible to main.cpp's Frame() so that it can abort after 100 frames
// if g_FixedFrameTiming == true (allows measuring performance).
extern size_t frameCount;
extern const int ORDER_DELAY;
#endif