1
0
forked from 0ad/0ad

# Enabled some interoperability between different compiler versions for the game and the editor DLL

This was SVN commit r3790.
This commit is contained in:
Ykkrosh 2006-04-21 03:53:10 +00:00
parent 8bb97e63cd
commit d9b033c85f
31 changed files with 569 additions and 161 deletions

View File

@ -14,6 +14,26 @@
#include "wx/config.h"
#include "wx/debugrpt.h"
// Shared memory allocation functions
ATLASDLLIMPEXP void* ShareableMalloc(size_t n)
{
// TODO: make sure this is thread-safe everywhere. (It is in MSVC with the
// multithreaded CRT.)
return malloc(n);
}
ATLASDLLIMPEXP void ShareableFree(void* p)
{
return free(p);
}
// Define the function pointers that we'll use when calling those functions.
// (The game loads the addresses of the above functions, then does the same.)
namespace AtlasMessage
{
void* (*ShareableMallocFptr) (size_t) = &ShareableMalloc;
void (*ShareableFreeFptr) (void*) = &ShareableFree;
}
// Global variables, to remember state between DllMain and StartWindow and OnInit
wxString g_InitialWindowType;
HINSTANCE g_Module;
@ -22,20 +42,20 @@ bool g_IsLoaded = false;
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID WXUNUSED(lpReserved))
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_Module = hModule;
return TRUE;
case DLL_PROCESS_DETACH:
if (g_IsLoaded)
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_Module = hModule;
return TRUE;
case DLL_PROCESS_DETACH:
if (g_IsLoaded)
{
wxEntryCleanup();
g_IsLoaded = false;
}
break;
}
wxEntryCleanup();
g_IsLoaded = false;
}
break;
}
return TRUE;
}
@ -166,4 +186,4 @@ public:
}
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
IMPLEMENT_APP_NO_MAIN(wxDLLApp)

View File

@ -1,8 +1,8 @@
#include <wchar.h>
namespace AtlasMessage { class MessageHandler; }
namespace AtlasMessage { class MessagePasser; }
ATLASDLLIMPEXP void Atlas_SetMessageHandler(AtlasMessage::MessageHandler*);
ATLASDLLIMPEXP void Atlas_SetMessagePasser(AtlasMessage::MessagePasser*);
ATLASDLLIMPEXP void Atlas_StartWindow(wchar_t* type);
ATLASDLLIMPEXP void Atlas_GLSetCurrent(void* context);

View File

@ -39,7 +39,7 @@ public:
// Be careful not to send 'resize' messages to the game before we've
// told it that this canvas exists
if (! m_SuppressResize)
POST_MESSAGE(ResizeScreen(GetClientSize().GetWidth(), GetClientSize().GetHeight()));
POST_MESSAGE(ResizeScreen, (GetClientSize().GetWidth(), GetClientSize().GetHeight()));
// TODO: fix flashing
#endif // UI_ONLY
}
@ -74,14 +74,14 @@ public:
if (dir == -1) // changed modifier keys - update all currently-scrolling directions
{
if (wxGetKeyState(WXK_LEFT)) POST_MESSAGE(ScrollConstant(AtlasMessage::eScrollConstantDir::LEFT, speed));
if (wxGetKeyState(WXK_RIGHT)) POST_MESSAGE(ScrollConstant(AtlasMessage::eScrollConstantDir::RIGHT, speed));
if (wxGetKeyState(WXK_UP)) POST_MESSAGE(ScrollConstant(AtlasMessage::eScrollConstantDir::FORWARDS, speed));
if (wxGetKeyState(WXK_DOWN)) POST_MESSAGE(ScrollConstant(AtlasMessage::eScrollConstantDir::BACKWARDS, speed));
if (wxGetKeyState(WXK_LEFT)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::LEFT, speed));
if (wxGetKeyState(WXK_RIGHT)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::RIGHT, speed));
if (wxGetKeyState(WXK_UP)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::FORWARDS, speed));
if (wxGetKeyState(WXK_DOWN)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::BACKWARDS, speed));
}
else
{
POST_MESSAGE(ScrollConstant(dir, enable ? speed : 0.0f));
POST_MESSAGE(ScrollConstant, (dir, enable ? speed : 0.0f));
}
#endif // UI_ONLY
return true;
@ -130,7 +130,7 @@ public:
float speed = 16.f;
if (wxGetKeyState(WXK_SHIFT))
speed *= 4.f;
POST_MESSAGE(SmoothZoom(speed*dir));
POST_MESSAGE(SmoothZoom, (speed*dir));
}
else
evt.Skip();
@ -210,7 +210,7 @@ public:
else if (wxGetKeyState(WXK_SHIFT))
speed *= 4.f;
POST_MESSAGE(SmoothZoom(evt.GetWheelRotation() * speed / evt.GetWheelDelta()));
POST_MESSAGE(SmoothZoom, (evt.GetWheelRotation() * speed / evt.GetWheelDelta()));
}
else
{
@ -229,8 +229,8 @@ public:
switch (m_MouseState)
{
case NONE: break;
case SCROLL: POST_MESSAGE(Scroll(AtlasMessage::eScrollType::FROM, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround(AtlasMessage::eRotateAroundType::FROM, evt.GetPosition())); break;
case SCROLL: POST_MESSAGE(Scroll, (AtlasMessage::eScrollType::FROM, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround, (AtlasMessage::eRotateAroundType::FROM, evt.GetPosition())); break;
default: wxFAIL;
}
m_LastMouseState = m_MouseState;
@ -240,8 +240,8 @@ public:
switch (m_MouseState)
{
case NONE: break;
case SCROLL: POST_MESSAGE(Scroll(AtlasMessage::eScrollType::TO, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround(AtlasMessage::eRotateAroundType::TO, evt.GetPosition())); break;
case SCROLL: POST_MESSAGE(Scroll, (AtlasMessage::eScrollType::TO, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround, (AtlasMessage::eRotateAroundType::TO, evt.GetPosition())); break;
default: wxFAIL;
}
}
@ -432,17 +432,17 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
// Send setup messages to game engine:
#ifndef UI_ONLY
POST_MESSAGE(SetContext(canvas->GetContext()));
POST_MESSAGE(SetContext, (canvas->GetContext()));
POST_MESSAGE(CommandString("init"));
POST_MESSAGE(CommandString, ("init"));
canvas->InitSize();
// Start with a blank map (so that the editor can assume there's always
// a valid map loaded)
POST_MESSAGE(GenerateMap(9));
POST_MESSAGE(GenerateMap, (9));
POST_MESSAGE(CommandString("render_enable"));
POST_MESSAGE(CommandString, ("render_enable"));
#endif
// Set up a timer to make sure tool-updates happen frequently (in addition
@ -458,7 +458,7 @@ void ScenarioEditor::OnClose(wxCloseEvent&)
SetCurrentTool(_T(""));
#ifndef UI_ONLY
POST_MESSAGE(CommandString("shutdown"));
POST_MESSAGE(CommandString, ("shutdown"));
#endif
AtlasMessage::qExit().Post();
@ -510,17 +510,17 @@ void ScenarioEditor::OnRedo(wxCommandEvent&)
void ScenarioEditor::OnWireframe(wxCommandEvent& event)
{
POST_MESSAGE(RenderStyle(event.IsChecked()));
POST_MESSAGE(RenderStyle, (event.IsChecked()));
}
void ScenarioEditor::OnMessageTrace(wxCommandEvent& event)
{
POST_MESSAGE(MessageTrace(event.IsChecked()));
POST_MESSAGE(MessageTrace, (event.IsChecked()));
}
void ScenarioEditor::OnScreenshot(wxCommandEvent& WXUNUSED(event))
{
POST_MESSAGE(Screenshot(10));
POST_MESSAGE(Screenshot, (10));
}
//////////////////////////////////////////////////////////////////////////

View File

@ -25,7 +25,7 @@ static void LoadMap(void*)
SetCurrentTool(_T(""));
// TODO: clear the undo buffer, etc
POST_MESSAGE(LoadMap(map));
POST_MESSAGE(LoadMap, (map));
}
wxCHECK_RET(cwd == wxFileName::GetCwd(), _T("cwd changed"));
@ -44,13 +44,13 @@ static void SaveMap(void*)
{
// TODO: Work when the map is not in .../maps/scenarios/
std::wstring map = dlg.GetFilename().c_str();
POST_MESSAGE(SaveMap(map));
POST_MESSAGE(SaveMap, (map));
}
}
static void GenerateMap(void*)
{
POST_MESSAGE(GenerateMap(9));
POST_MESSAGE(GenerateMap, (9));
}
static void GenerateRMS(void* data)
@ -64,7 +64,7 @@ static void GenerateRMS(void* data)
wxExecute(argv, wxEXEC_SYNC);
wxFileName::SetCwd(cwd);
POST_MESSAGE(LoadMap(L"_atlasrm.pmp"));
POST_MESSAGE(LoadMap, (L"_atlasrm.pmp"));
}
//////////////////////////////////////////////////////////////////////////

View File

@ -91,7 +91,7 @@ void ObjectSidebar::OnFirstDisplay()
{
AtlasMessage::qGetObjectsList qry;
qry.Post();
p->m_Objects = qry.objects;
p->m_Objects = *qry.objects;
SetObjectFilter(0);
}

View File

@ -80,10 +80,16 @@ public:
AtlasMessage::qGetTerrainGroupPreviews qry(m_Name.c_str(), imageWidth, imageHeight);
qry.Post();
std::vector<AtlasMessage::sTerrainGroupPreview> previews = *qry.previews;
int i = 0;
for (std::vector<AtlasMessage::sTerrainGroupPreview>::iterator it = qry.previews.begin(); it != qry.previews.end(); ++it)
for (std::vector<AtlasMessage::sTerrainGroupPreview>::iterator it = previews.begin(); it != previews.end(); ++it)
{
wxImage img (imageWidth, imageHeight, it->imagedata);
unsigned char* buf = (unsigned char*)(malloc(it->imagedata.GetSize()));
// it->imagedata.GetBuffer() gives a Shareable<unsigned char>*, which
// is stored the same as a unsigned char*, so we can just copy it.
memcpy(buf, it->imagedata.GetBuffer(), it->imagedata.GetSize());
wxImage img (imageWidth, imageHeight, buf);
imglist->Add(wxBitmap(img));
wxListItem item;
@ -142,7 +148,8 @@ public:
// Get the list of terrain groups from the engine
AtlasMessage::qGetTerrainGroups qry;
qry.Post();
for (std::vector<std::wstring>::iterator it = qry.groupnames.begin(); it != qry.groupnames.end(); ++it)
std::vector<std::wstring> groupnames = *qry.groupnames;
for (std::vector<std::wstring>::iterator it = groupnames.begin(); it != groupnames.end(); ++it)
m_TerrainGroups.Add(it->c_str());
for (size_t i = 0; i < m_TerrainGroups.GetCount(); ++i)

View File

@ -27,7 +27,7 @@ public:
void OnDisable()
{
POST_MESSAGE(BrushPreview(false, Position()));
POST_MESSAGE(BrushPreview, (false, Position()));
}
@ -49,7 +49,7 @@ public:
}
else if (evt.Moving())
{
POST_MESSAGE(BrushPreview(true, Position(evt.GetPosition())));
POST_MESSAGE(BrushPreview, (true, Position(evt.GetPosition())));
return true;
}
else
@ -65,7 +65,7 @@ public:
{
void OnEnter(AlterElevation* obj)
{
POST_MESSAGE(BrushPreview(true, obj->m_Pos));
POST_MESSAGE(BrushPreview, (true, obj->m_Pos));
}
void OnLeave(AlterElevation*)
@ -84,7 +84,7 @@ public:
{
wxPoint pos = evt.GetPosition();
obj->m_Pos = Position(pos);
POST_MESSAGE(BrushPreview(true, obj->m_Pos));
POST_MESSAGE(BrushPreview, (true, obj->m_Pos));
return true;
}
else

View File

@ -40,12 +40,12 @@ int Brush::GetHeight() const
return GetWidth();
}
float* Brush::GetNewedData() const
std::vector<float> Brush::GetData() const
{
int width = GetWidth();
int height = GetHeight();
float* data = new float[width*height];
std::vector<float> data (width*height);
switch (m_Shape)
{
@ -200,7 +200,7 @@ void Brush::MakeActive()
void Brush::Send()
{
if (m_IsActive)
POST_MESSAGE(Brush(GetWidth(), GetHeight(), GetNewedData()));
POST_MESSAGE(Brush, (GetWidth(), GetHeight(), GetData()));
}

View File

@ -16,7 +16,7 @@ public:
int GetWidth() const;
int GetHeight() const;
float* GetNewedData() const; // freshly allocated via new[]
std::vector<float> GetData() const;
float GetStrength() const;

View File

@ -111,16 +111,20 @@ WorldCommand::WorldCommand(AtlasMessage::mWorldCommand* command)
WorldCommand::~WorldCommand()
{
// m_Command was allocated by POST_COMMAND
delete m_Command;
}
bool WorldCommand::Do()
{
if (m_AlreadyDone)
POST_MESSAGE(RedoCommand());
POST_MESSAGE(RedoCommand, ());
else
{
POST_MESSAGE(DoCommand(m_Command));
// The DoCommand message clones the data from m_Command, and posts that
// (passing ownership to the game), so we're free to delete m_Command
// at any time
POST_MESSAGE(DoCommand, (m_Command));
m_AlreadyDone = true;
}
return true;
@ -128,7 +132,7 @@ bool WorldCommand::Do()
bool WorldCommand::Undo()
{
POST_MESSAGE(UndoCommand());
POST_MESSAGE(UndoCommand, ());
return true;
}
@ -145,6 +149,6 @@ bool WorldCommand::Merge(AtlasWindowCommand* p)
if (! m_Command->IsMergeable())
return false;
POST_MESSAGE(MergeCommand());
POST_MESSAGE(MergeCommand, ());
return true;
}

View File

@ -26,7 +26,7 @@ public:
void OnDisable()
{
POST_MESSAGE(BrushPreview(false, Position()));
POST_MESSAGE(BrushPreview, (false, Position()));
}
@ -42,7 +42,7 @@ public:
}
else if (evt.Moving())
{
POST_MESSAGE(BrushPreview(true, Position(evt.GetPosition())));
POST_MESSAGE(BrushPreview, (true, Position(evt.GetPosition())));
return true;
}
else
@ -58,7 +58,7 @@ public:
{
void OnEnter(FlattenElevation* obj)
{
POST_MESSAGE(BrushPreview(true, obj->m_Pos));
POST_MESSAGE(BrushPreview, (true, obj->m_Pos));
}
void OnLeave(FlattenElevation*)
@ -77,7 +77,7 @@ public:
{
wxPoint pos = evt.GetPosition();
obj->m_Pos = Position(pos);
POST_MESSAGE(BrushPreview(true, obj->m_Pos));
POST_MESSAGE(BrushPreview, (true, obj->m_Pos));
return true;
}
else

View File

@ -28,7 +28,7 @@ public:
void OnDisable()
{
POST_MESSAGE(BrushPreview(false, Position()));
POST_MESSAGE(BrushPreview, (false, Position()));
}
@ -50,7 +50,7 @@ public:
}
else if (evt.Moving())
{
POST_MESSAGE(BrushPreview(true, Position(evt.GetPosition())));
POST_MESSAGE(BrushPreview, (true, Position(evt.GetPosition())));
return true;
}
else
@ -96,7 +96,7 @@ public:
void Paint(PaintTerrain* obj)
{
POST_MESSAGE(BrushPreview(true, obj->m_Pos));
POST_MESSAGE(BrushPreview, (true, obj->m_Pos));
POST_COMMAND(PaintTerrain, (obj->m_Pos, g_SelectedTexture.c_str(), GetPriority()));
}

View File

@ -30,9 +30,9 @@ public:
+ (m_ScreenPos.type1.y-m_Target.type1.y)*(m_ScreenPos.type1.y-m_Target.type1.y);
bool useTarget = (dragDistSq >= 16*16);
if (preview)
POST_MESSAGE(ObjectPreview(m_ObjectID.c_str(), 0, m_ObjPos, useTarget, m_Target, g_DefaultAngle));
POST_MESSAGE(ObjectPreview, (m_ObjectID.c_str(), 0, m_ObjPos, useTarget, m_Target, g_DefaultAngle));
else
POST_COMMAND(CreateObject,(m_ObjectID.c_str(), m_Player, m_ObjPos, useTarget, m_Target, g_DefaultAngle));
POST_COMMAND(CreateObject, (m_ObjectID.c_str(), m_Player, m_ObjPos, useTarget, m_Target, g_DefaultAngle));
}
virtual void Init(void* initData)

View File

@ -23,7 +23,7 @@ public:
void OnDisable()
{
m_Selection.clear();
POST_MESSAGE(SetSelectionPreview(m_Selection));
POST_MESSAGE(SetSelectionPreview, (m_Selection));
}
@ -46,7 +46,7 @@ public:
obj->m_dy = qry.offsety;
SET_STATE(Dragging);
}
POST_MESSAGE(SetSelectionPreview(obj->m_Selection));
POST_MESSAGE(SetSelectionPreview, (obj->m_Selection));
ScenarioEditor::GetCommandProc().FinaliseLastCommand();
return true;
}
@ -68,7 +68,7 @@ public:
for (size_t i = 0; i < obj->m_Selection.size(); ++i)
POST_COMMAND(DeleteObject, (obj->m_Selection[i]));
obj->m_Selection.clear();
POST_MESSAGE(SetSelectionPreview(obj->m_Selection));
POST_MESSAGE(SetSelectionPreview, (obj->m_Selection));
return true;
}
else

View File

@ -49,22 +49,20 @@ public:
};
Brush::Brush()
: m_W(0), m_H(0), m_TerrainOverlay(NULL), m_Data(NULL)
: m_W(0), m_H(0), m_TerrainOverlay(NULL)
{
}
Brush::~Brush()
{
delete m_TerrainOverlay;
delete[] m_Data;
}
void Brush::SetData(int w, int h, const float* data)
void Brush::SetData(int w, int h, const std::vector<float>& data)
{
m_W = w;
m_H = h;
delete[] m_Data;
m_Data = data;
}

View File

@ -9,7 +9,7 @@ struct Brush
Brush();
~Brush();
void SetData(int w, int h, const float* data);
void SetData(int w, int h, const std::vector<float>& data);
void SetRenderEnabled(bool enabled); // initial state is disabled
@ -27,7 +27,7 @@ struct Brush
CVector3D m_Centre;
private:
TerrainOverlay* m_TerrainOverlay; // NULL if rendering is not enabled
const float* m_Data;
std::vector<float> m_Data;
};
extern Brush g_CurrentBrush;

View File

@ -2,6 +2,8 @@
#include <list>
#include <map>
#include "SharedMemory.h"
namespace AtlasMessage
{
@ -47,7 +49,8 @@ struct DataCommand : public Command // so commands can optionally override (De|C
{
void Destruct() {};
void Construct() {};
// MergeWithSelf should update 'prev' to include the effects of 'this'
// MergeWithSelf should be overriden by commands, and implemented
// to update 'prev' to include the effects of 'this'
void MergeWithSelf(void*) { debug_warn("MergeWithSelf unimplemented in some command"); }
};
@ -57,8 +60,8 @@ struct DataCommand : public Command // so commands can optionally override (De|C
d##t* d; \
public: \
c##t(d##t* data) : d(data) { Construct(); } \
~c##t() { Destruct(); delete d; } \
static Command* Create(const void* data) { return new c##t((d##t*)data); } \
~c##t() { Destruct(); AtlasMessage::ShareableDelete(d); /* d was allocated by mDoCommand() */ } \
static Command* Create(const void* data) { return new c##t ((d##t*)data); } \
virtual void Merge(Command* prev) { MergeWithSelf((c##t*)prev); } \
virtual const char* GetType() const { return #t; }

View File

@ -4,6 +4,7 @@
#include "MessagePasserImpl.h"
#include "Messages.h"
#include "SharedMemory.h"
#include "Brushes.h"
#include "Handlers/MessageHandler.h"
@ -41,6 +42,11 @@ void (*Atlas_SetMessagePasser)(MessagePasser*);
void (*Atlas_GLSetCurrent)(void* context);
void (*Atlas_GLSwapBuffers)(void* context);
void (*Atlas_NotifyEndOfFrame)();
namespace AtlasMessage
{
void* (*ShareableMallocFptr)(size_t);
void (*ShareableFreeFptr)(void*);
}
static MessagePasserImpl msgPasser;
@ -71,6 +77,10 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
GET(Atlas_GLSwapBuffers);
GET(Atlas_NotifyEndOfFrame);
#undef GET
#define GET(x) *(void**)&x##Fptr = dlsym(dll, #x); debug_assert(x##Fptr); if (! x##Fptr) return false;
GET(ShareableMalloc);
GET(ShareableFree);
#undef GET
// Pass our message handler to Atlas
Atlas_SetMessagePasser(&msgPasser);
@ -129,7 +139,7 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
// construct a reference to the appropriate handler for the
// given string)
name += "_";
name += static_cast<mCommandString*>(msg)->name;
name += *static_cast<mCommandString*>(msg)->name;
// use 'static_cast' when casting messages, to make it clear
// that something slightly dangerous is happening - we have
// to just assume that GetName is correct, since we can't use
@ -166,7 +176,7 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
{
// For non-queries, we need to delete the object, since we
// took ownership of it.
delete msg;
AtlasMessage::ShareableDelete(msg);
}
}
}

View File

@ -8,13 +8,13 @@ namespace AtlasMessage {
MESSAGEHANDLER(Brush)
{
g_CurrentBrush.SetData(msg->width, msg->height, msg->data);
g_CurrentBrush.SetData(msg->width, msg->height, *msg->data);
}
MESSAGEHANDLER(BrushPreview)
{
g_CurrentBrush.SetRenderEnabled(msg->enable);
msg->pos.GetWorldSpace(g_CurrentBrush.m_Centre);
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre);
}
}

View File

@ -53,14 +53,14 @@ MESSAGEHANDLER(Scroll)
if (msg->type == eScrollType::FROM)
{
msg->pos.GetWorldSpace(targetPos);
msg->pos->GetWorldSpace(targetPos);
targetDistance = (targetPos - camera.GetTranslation()).GetLength();
}
else if (msg->type == eScrollType::TO)
{
CVector3D origin, dir;
float x, y;
msg->pos.GetScreenSpace(x, y);
msg->pos->GetScreenSpace(x, y);
g_Game->GetView()->GetCamera()->BuildCameraRay((int)x, (int)y, origin, dir);
dir *= targetDistance;
camera.Translate(targetPos - dir - origin);
@ -87,13 +87,13 @@ MESSAGEHANDLER(RotateAround)
if (msg->type == eRotateAroundType::FROM)
{
msg->pos.GetScreenSpace(lastX, lastY); // get mouse position
msg->pos.GetWorldSpace(focusPos); // get point on terrain under mouse
msg->pos->GetScreenSpace(lastX, lastY); // get mouse position
msg->pos->GetWorldSpace(focusPos); // get point on terrain under mouse
}
else if (msg->type == eRotateAroundType::TO)
{
float x, y;
msg->pos.GetScreenSpace(x, y); // get mouse position
msg->pos->GetScreenSpace(x, y); // get mouse position
// Rotate around X and Y axes by amounts depending on the mouse delta
float rotX = 6.f * (y-lastY) / g_Renderer.GetHeight();

View File

@ -10,7 +10,7 @@ namespace AtlasMessage {
MESSAGEHANDLER(DoCommand)
{
Command* c = NULL;
cmdHandlers::const_iterator it = GetCmdHandlers().find("c" + msg->name);
cmdHandlers::const_iterator it = GetCmdHandlers().find("c" + *msg->name);
if (it != GetCmdHandlers().end())
{
c = (it->second)(msg->data);

View File

@ -104,7 +104,7 @@ BEGIN_COMMAND(AlterElevation)
}
static CVector3D previousPosition;
d->pos.GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
d->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
previousPosition = g_CurrentBrush.m_Centre;
int x0, y0;
@ -163,7 +163,7 @@ BEGIN_COMMAND(FlattenElevation)
int amount = (int)d->amount;
static CVector3D previousPosition;
d->pos.GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
d->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
previousPosition = g_CurrentBrush.m_Centre;
int xc, yc;

View File

@ -98,14 +98,14 @@ MESSAGEHANDLER(GenerateMap)
MESSAGEHANDLER(LoadMap)
{
InitGame(msg->filename);
InitGame(*msg->filename);
StartGame();
}
MESSAGEHANDLER(SaveMap)
{
CMapWriter writer;
writer.SaveMap(CStr(L"maps/scenarios/" + msg->filename),
writer.SaveMap(CStr(L"maps/scenarios/" + *msg->filename),
g_Game->GetWorld()->GetTerrain(), g_Game->GetWorld()->GetUnitManager(),
&g_LightEnv, g_Game->GetView()->GetCamera());
}

View File

@ -25,11 +25,12 @@ namespace AtlasMessage {
static bool SortObjectsList(const sObjectsListItem& a, const sObjectsListItem& b)
{
return a.name < b.name;
return wcscmp(a.name.c_str(), b.name.c_str()) < 0;
}
QUERYHANDLER(GetObjectsList)
{
std::vector<sObjectsListItem> objects;
{
std::vector<CStrW> names;
g_EntityTemplateCollection.getBaseEntityNames(names);
@ -40,7 +41,7 @@ QUERYHANDLER(GetObjectsList)
e.id = L"(e) " + *it;
e.name = *it; //baseent->m_Tag
e.type = 0;
msg->objects.push_back(e);
objects.push_back(e);
}
}
@ -54,10 +55,11 @@ QUERYHANDLER(GetObjectsList)
e.id = L"(n) " + CStrW(*it);
e.name = CStrW(*it).AfterFirst(/*L"props/"*/ L"actors/");
e.type = 1;
msg->objects.push_back(e);
objects.push_back(e);
}
}
std::sort(msg->objects.begin(), msg->objects.end(), SortObjectsList);
std::sort(objects.begin(), objects.end(), SortObjectsList);
msg->objects = objects;
}
@ -98,7 +100,7 @@ void AtlasRenderSelection()
MESSAGEHANDLER(SetSelectionPreview)
{
g_Selection = msg->ids;
g_Selection = *msg->ids;
}
//////////////////////////////////////////////////////////////////////////
@ -152,7 +154,7 @@ static bool ParseObjectName(const CStrW& obj, bool& isEntity, CStrW& name)
MESSAGEHANDLER(ObjectPreview)
{
if (msg->id != g_PreviewUnitID)
if (*msg->id != g_PreviewUnitID)
{
// Delete old unit
if (g_PreviewUnit)
@ -164,7 +166,7 @@ MESSAGEHANDLER(ObjectPreview)
bool isEntity;
CStrW name;
if (ParseObjectName(msg->id, isEntity, name))
if (ParseObjectName(*msg->id, isEntity, name))
{
std::set<CStrW> selections; // TODO: get selections from user
@ -186,7 +188,7 @@ MESSAGEHANDLER(ObjectPreview)
}
}
g_PreviewUnitID = msg->id;
g_PreviewUnitID = *msg->id;
}
if (g_PreviewUnit)
@ -198,7 +200,7 @@ MESSAGEHANDLER(ObjectPreview)
if (msg->usetarget)
{
CVector3D target;
msg->target.GetWorldSpace(target, pos.Y);
msg->target->GetWorldSpace(target, pos.Y);
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
dir = dir.normalize();
s = dir.x;
@ -234,7 +236,7 @@ BEGIN_COMMAND(CreateObject)
if (d->usetarget)
{
CVector3D target;
d->target.GetWorldSpace(target, m_Pos.Y);
d->target->GetWorldSpace(target, m_Pos.Y);
CVector2D dir(target.X-m_Pos.X, target.Z-m_Pos.Z);
m_Angle = atan2(dir.x, dir.y);
}
@ -252,7 +254,7 @@ BEGIN_COMMAND(CreateObject)
{
bool isEntity;
CStrW name;
if (ParseObjectName(d->id, isEntity, name))
if (ParseObjectName(*d->id, isEntity, name))
{
std::set<CStrW> selections;
@ -329,7 +331,7 @@ END_COMMAND(CreateObject)
QUERYHANDLER(SelectObject)
{
float x, y;
msg->pos.GetScreenSpace(x, y);
msg->pos->GetScreenSpace(x, y);
CVector3D rayorigin, raydir;
g_Game->GetView()->GetCamera()->BuildCameraRay((int)x, (int)y, rayorigin, raydir);
@ -434,7 +436,7 @@ BEGIN_COMMAND(RotateObject)
{
CVector3D& pos = unit->GetEntity()->m_position;
CVector3D target;
d->target.GetWorldSpace(target, pos.Y);
d->target->GetWorldSpace(target, pos.Y);
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
m_AngleNew = atan2(dir.x, dir.y);
}
@ -453,7 +455,7 @@ BEGIN_COMMAND(RotateObject)
if (d->usetarget)
{
CVector3D target;
d->target.GetWorldSpace(target, pos.Y);
d->target->GetWorldSpace(target, pos.Y);
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
dir = dir.normalize();
s = dir.x;

View File

@ -20,8 +20,10 @@ namespace AtlasMessage {
QUERYHANDLER(GetTerrainGroups)
{
const CTextureManager::TerrainGroupMap &groups = g_TexMan.GetGroups();
for (CTextureManager ::TerrainGroupMap::const_iterator it = groups.begin(); it != groups.end(); ++it)
msg->groupnames.push_back(CStrW(it->first));
std::vector<std::wstring> groupnames;
for (CTextureManager::TerrainGroupMap::const_iterator it = groups.begin(); it != groups.end(); ++it)
groupnames.push_back(CStrW(it->first));
msg->groupnames = groupnames;
}
static bool CompareTerrain(const sTerrainGroupPreview& a, const sTerrainGroupPreview& b)
@ -31,13 +33,15 @@ static bool CompareTerrain(const sTerrainGroupPreview& a, const sTerrainGroupPre
QUERYHANDLER(GetTerrainGroupPreviews)
{
CTerrainGroup* group = g_TexMan.FindGroup(CStrW(msg->groupname));
std::vector<sTerrainGroupPreview> previews;
CTerrainGroup* group = g_TexMan.FindGroup(CStrW(*msg->groupname));
for (std::vector<CTextureEntry*>::const_iterator it = group->GetTerrains().begin(); it != group->GetTerrains().end(); ++it)
{
msg->previews.push_back(sTerrainGroupPreview());
msg->previews.back().name = CStrW((*it)->GetTag());
previews.push_back(sTerrainGroupPreview());
previews.back().name = CStrW((*it)->GetTag());
unsigned char* buf = (unsigned char*)malloc(msg->imagewidth*msg->imageheight*3);
std::vector<unsigned char> buf (msg->imagewidth*msg->imageheight*3);
// It's not good to shrink the entire texture to fit the small preview
// window, since it's the fine details in the texture that are
@ -72,7 +76,7 @@ QUERYHANDLER(GetTerrainGroupPreviews)
// Extract the middle section (as a representative preview),
// and copy into buf
unsigned char* texdata_ptr = texdata + (w*(h - msg->imageheight)/2 + (w - msg->imagewidth)/2) * 3;
unsigned char* buf_ptr = buf;
unsigned char* buf_ptr = &buf[0];
for (int y = 0; y < msg->imageheight; ++y)
{
memcpy(buf_ptr, texdata_ptr, msg->imagewidth*3);
@ -83,11 +87,12 @@ QUERYHANDLER(GetTerrainGroupPreviews)
delete[] texdata;
}
msg->previews.back().imagedata = buf;
previews.back().imagedata = buf;
}
// Sort the list alphabetically by name
std::sort(msg->previews.begin(), msg->previews.end(), CompareTerrain);
std::sort(previews.begin(), previews.end(), CompareTerrain);
msg->previews = previews;
}
//////////////////////////////////////////////////////////////////////////
@ -160,12 +165,12 @@ BEGIN_COMMAND(PaintTerrain)
void Do()
{
d->pos.GetWorldSpace(g_CurrentBrush.m_Centre);
d->pos->GetWorldSpace(g_CurrentBrush.m_Centre);
int x0, y0;
g_CurrentBrush.GetBottomLeft(x0, y0);
CTextureEntry* texentry = g_TexMan.FindTexture(CStrW(d->texture));
CTextureEntry* texentry = g_TexMan.FindTexture(CStrW(*d->texture));
if (! texentry)
{
debug_warn("Can't find texentry"); // TODO: nicer error handling

View File

@ -1,6 +1,8 @@
#ifndef MESSAGEPASSER_H__
#define MESSAGEPASSER_H__
#include "SharedMemory.h"
namespace AtlasMessage
{
@ -21,7 +23,7 @@ public:
extern MessagePasser* g_MessagePasser;
#define POST_MESSAGE(type) AtlasMessage::g_MessagePasser->Add(new AtlasMessage::m##type)
#define POST_MESSAGE(type, data) AtlasMessage::g_MessagePasser->Add(SHAREABLE_NEW(AtlasMessage::m##type, data))
}

View File

@ -55,7 +55,7 @@ MESSAGE(Screenshot,
MESSAGE(Brush,
((int, width)) // number of vertices
((int, height))
((float*, data)) // width*height array, allocated with new[] (handler will delete[])
((std::vector<float>, data)) // width*height array
);
MESSAGE(BrushPreview,
@ -73,9 +73,11 @@ QUERY(GetTerrainGroups,
struct sTerrainGroupPreview
{
std::wstring name;
unsigned char* imagedata; // RGB*size*size, allocated with malloc (querier should free)
Shareable<std::wstring> name;
Shareable<std::vector<unsigned char> > imagedata; // RGB*size*size
};
SHAREABLE_POD(sTerrainGroupPreview);
QUERY(GetTerrainGroupPreviews,
((std::wstring, groupname))
((int, imagewidth))
@ -89,10 +91,12 @@ QUERY(GetTerrainGroupPreviews,
struct sObjectsListItem
{
std::wstring id;
std::wstring name;
int type; // 0 = entity, 1 = actor
Shareable<std::wstring> id;
Shareable<std::wstring> name;
Shareable<int> type; // 0 = entity, 1 = actor
};
SHAREABLE_POD(sObjectsListItem);
QUERY(GetObjectsList,
, // no inputs
((std::vector<sObjectsListItem>, objects))

View File

@ -4,46 +4,17 @@
#define MESSAGESSETUP_NOTFIRST
#include "MessagePasser.h"
#include "SharedTypes.h"
#include "Shareable.h"
// Structures in this file are passed over the DLL boundary, so some
// carefulness and/or luck is required...
class wxPoint;
class CVector3D;
class CMutex;
namespace AtlasMessage
{
//////////////////////////////////////////////////////////////////////////
struct Position
{
Position() : type(0) { type0.x = type0.y = type0.z = 0.f; }
Position(float x_, float y_, float z_) : type(0) { type0.x = x_; type0.y = y_; type0.z = z_; }
Position(const wxPoint& pt); // (implementation in ScenarioEditor.cpp)
int type;
union {
struct { float x, y, z; } type0; // world-space coordinates
struct { int x, y; } type1; // screen-space coordinates, to be projected onto terrain
// type2: "same as previous" (e.g. for elevation-editing when the mouse hasn't moved)
};
// Constructs a position with the meaning "same as previous", which is handled
// in an unspecified way by various message handlers.
static Position Unchanged() { Position p; p.type = 2; return p; }
// Only for use in the game, not the UI.
// Implementations in Misc.cpp.
void GetWorldSpace(CVector3D& vec) const;
void GetWorldSpace(CVector3D& vec, float h) const;
void GetWorldSpace(CVector3D& vec, const CVector3D& prev) const;
void GetScreenSpace(float& x, float& y) const;
};
//////////////////////////////////////////////////////////////////////////
struct IMessage
{
virtual const char* GetName() const = 0;
@ -71,8 +42,9 @@ MESSAGESTRUCT(WorldCommand)
};
MESSAGESTRUCT(DoCommand)
mDoCommand(mWorldCommand* c) : name(c->GetName()), data(c->CloneData()) {}
const std::string name;
const void* data;
const Shareable<std::string> name;
const Shareable<void*> data;
// 'data' gets deallocated by ~cWhatever in the game thread
};
MESSAGESTRUCT(UndoCommand) };
MESSAGESTRUCT(RedoCommand) };
@ -112,7 +84,7 @@ const bool NOMERGE = false;
m##t(const d##t& d) : d##t(d) {} \
const char* GetName() const { return #t; } \
virtual bool IsMergeable() const { return merge; } \
void* CloneData() const { return new d##t(*this); } \
void* CloneData() const { return SHAREABLE_NEW(d##t, (*this)); } \
private: \
const m##t& operator=(const m##t&);\
};
@ -128,15 +100,15 @@ const bool NOMERGE = false;
#define B_NAME(elem) BOOST_PP_TUPLE_ELEM(2, 1, elem)
#define B_CONSTRUCTORARGS(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_TYPE(elem) BOOST_PP_CAT(B_NAME(elem),_)
#define B_CONSTRUCTORINIT(r, data, n, elem) BOOST_PP_COMMA_IF(n) B_NAME(elem)(BOOST_PP_CAT(B_NAME(elem),_))
#define B_CONSTMEMBERS(r, data, n, elem) const B_TYPE(elem) B_NAME(elem);
#define B_MEMBERS(r, data, n, elem) B_TYPE(elem) B_NAME(elem);
#define B_CONSTMEMBERS(r, data, n, elem) const Shareable< B_TYPE(elem) > B_NAME(elem);
#define B_MEMBERS(r, data, n, elem) Shareable< B_TYPE(elem) > B_NAME(elem);
/* For each message type, generate something roughly like:
struct mBlah : public IMessage {
const char* GetName() const { return "Blah"; }
mBlah(int in0_, bool in1_) : in0(in0_), in1(in1_) {}
const int in0;
const bool in1;
const Shareable<int> in0;
const Shareable<bool> in1;
}
*/

View File

@ -0,0 +1,277 @@
#ifndef SHAREABLE_H__
#define SHAREABLE_H__
/*
The Atlas UI DLL needs to share information with the game EXE. It's most
convenient if they can pass STL objects, like std::wstring and std::vector;
but that causes problems if the DLL and EXE were not compiled in exactly
the same way.
So, the Shareable<T> class is used to make things a bit safer:
Simple types (primitives, POD structs, etc) are passed as normal.
std::string is converted to an array, using a shared (and thread-safe) memory
allocation function so that it works when the DLL and EXE use different heaps.
std::vector is done the same, though its element type must be Shareable too.
This ought to protect against:
* Different heaps (msvcr71 vs msvcr80, debug vs release, etc).
* Different STL class layout.
It doesn't protect against:
* Different data type sizes/ranges.
* Different packing in our structs. (But they're very simple structs,
only storing size_t and pointer values.)
* Vtable layout - this code doesn't actually care, but the rest of Atlas does.
Usage should be fairly transparent - conversions from T to Shareable<T> are
automatic, and the opposite is automatic for primitive types.
For POD structs, use operator-> to access members (e.g. "msg->sharedstruct->value").
For more complex things (strings, vectors), use the unary operator* to get back
an STL object (e.g. "std::string s = *msg->sharedstring").
(That conversion to an STL object is potentially expensive, so
Shareable<string>.c_str() and Shareable<vector>.GetBuffer/GetSize() can be used
if that's all you need.)
The supported list of primitive types is below (SHAREABLE_PRIMITIVE).
Structs are made shareable by manually ensuring that all their members are
shareable (i.e. primitives, PODs, Shareable<string>s, etc) and writing
SHAREABLE_POD(StructName);
after their definition.
*/
#include "SharedMemory.h"
// We want to use placement new, which breaks when compiling Debug configurations
// in the game and in wx, and they both need different workarounds.
// (Duplicated in SharedMemory.h)
#ifdef new
# define SHAREABLE_USED_NOMMGR
# ifdef __WXWINDOWS__
# undef new
# else
# include "nommgr.h"
# endif
#endif
namespace AtlasMessage
{
// By default, things are not shareable
template <typename T> class Shareable
{
public:
Shareable();
enum { TypeIsShareable = 0 };
};
// Primitive types just need a very simple wrapper
#define SHAREABLE_PRIMITIVE(T) \
template<> class Shareable<T> \
{ \
T m; \
public: \
enum { TypeIsShareable = 1 }; \
Shareable() {} \
Shareable(T const& rhs) { m = rhs; } \
operator const T() const { return m; } \
const T _Unwrap() const { return m; } \
}
SHAREABLE_PRIMITIVE(unsigned char);
SHAREABLE_PRIMITIVE(int);
SHAREABLE_PRIMITIVE(bool);
SHAREABLE_PRIMITIVE(float);
SHAREABLE_PRIMITIVE(void*);
#undef SHAREABLE_PRIMITIVE
// POD types are similar to primitives, but with operator->
#define SHAREABLE_POD(T) \
template<> class Shareable<T> \
{ \
T m; \
public: \
enum { TypeIsShareable = 1 }; \
Shareable() {} \
Shareable(T const& rhs) { m = rhs; } \
const T* operator->() const { return &m; } \
operator const T() const { return m; } \
const T _Unwrap() const { return m; } \
}
// Shareable containers must have shareable contents - but it's easy to forget
// to declare them, so make sure the errors are almost readable, like:
// "use of undefined type 'REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE<T,__formal>
// with [ T=AtlasMessage::sTerrainGroupPreview, __formal=false ]"
//
// (Implementation based on boost/static_assert)
template <typename T, bool> struct REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE;
template <typename T> struct REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE<T, true>{};
template<int x> struct static_assert_test{};
#define ASSERT_TYPE_IS_SHAREABLE(T) typedef static_assert_test< \
sizeof(REQUIRE_TYPE_TO_BE_SHAREABLE_FAILURE< T, (bool)(Shareable<T>::TypeIsShareable) >)> \
static_assert_typedef_
// Shareable strings:
template<typename C> class Shareable< std::basic_string<C> >
{
typedef std::basic_string<C> wrapped_type;
const static C null = 0; // for null strings of the right type
C* buf; // null-terminated string (perhaps with embedded nulls)
size_t length; // size of buf (including null)
public:
enum { TypeIsShareable = 1 };
Shareable() : buf(NULL), length(0) {}
Shareable(const wrapped_type& rhs)
{
length = rhs.length()+1;
buf = (C*)ShareableMallocFptr(sizeof(C)*length);
memcpy(buf, rhs.c_str(), sizeof(C)*length);
}
~Shareable()
{
ShareableFreeFptr(buf);
}
Shareable<wrapped_type>& operator=(const Shareable<wrapped_type>& rhs)
{
if (&rhs == this)
return *this;
ShareableFreeFptr(buf);
length = rhs.length;
buf = (C*)ShareableMallocFptr(sizeof(C)*length);
memcpy(buf, rhs.buf, sizeof(C)*length);
return *this;
}
Shareable(const Shareable<wrapped_type>& rhs)
: buf(NULL), length(0)
{
*this = rhs;
}
const wrapped_type _Unwrap() const
{
return buf ? wrapped_type(buf, buf+length-1) : wrapped_type();
}
const wrapped_type operator*() const
{
return _Unwrap();
}
// Minor optimisation for code that just wants to access the characters,
// without constructing a new std::basic_string then calling c_str on that
const C* c_str() const
{
return buf ? buf : &null;
}
};
// Shareable vectors:
template<typename E> class Shareable<std::vector<E> >
{
ASSERT_TYPE_IS_SHAREABLE(E);
typedef std::vector<E> wrapped_type;
typedef Shareable<E> element_type;
element_type* array;
size_t size;
// Since we're allocating with malloc (roughly), but storing non-trivial
// objects, we have to allocate with placement new and call destructors
// manually. (At least the objects are usually just other Shareables, so it's
// reasonably safe to assume there's no exceptions or other confusingness.)
void Unalloc()
{
if (array == NULL)
return;
for (size_t i = 0; i < size; ++i)
array[i].~element_type();
ShareableFreeFptr(array);
array = NULL;
size = 0;
}
public:
enum { TypeIsShareable = 1 };
Shareable() : array(NULL), size(0) {}
Shareable(const wrapped_type& rhs)
{
size = rhs.size();
array = static_cast<element_type*> (ShareableMallocFptr( sizeof(element_type)*size ));
for (size_t i = 0; i < size; ++i)
new (&array[i]) element_type (rhs[i]);
}
~Shareable()
{
Unalloc();
}
Shareable<wrapped_type>& operator=(const Shareable<wrapped_type>& rhs)
{
if (&rhs == this)
return *this;
Unalloc();
size = rhs.size;
array = static_cast<element_type*> (ShareableMallocFptr( sizeof(element_type)*size ));
for (size_t i = 0; i < size; ++i)
new (&array[i]) element_type (rhs.array[i]);
return *this;
}
Shareable(const Shareable<wrapped_type>& rhs)
: array(NULL), size(0)
{
*this = rhs;
}
const wrapped_type _Unwrap() const
{
wrapped_type r;
r.reserve(size);
for (size_t i = 0; i < size; ++i)
r.push_back(array[i]._Unwrap());
return r;
}
const wrapped_type operator*() const
{
return _Unwrap();
}
// Minor optimisation for code that just wants to access the buffer,
// without constructing a new std::vector
const element_type* GetBuffer() const
{
return array;
}
size_t GetSize() const
{
return size;
}
};
}
#ifdef SHAREABLE_USED_NOMMGR
# ifdef __WXWINDOWS__ // TODO: portability to non-Windows wx
# define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
# else
# include "mmgr.h"
# endif
# undef SHAREABLE_USED_NOMMGR
#endif
#endif // SHAREABLE_H__

View File

@ -0,0 +1,64 @@
#ifndef SHAREDMEMORY_H__
#define SHAREDMEMORY_H__
// We want to use placement new, which breaks when compiling Debug configurations
// in the game and in wx, and they both need different workarounds.
// (Duplicated in Shareable.h)
#ifdef new
# define SHAREABLE_USED_NOMMGR
# ifdef __WXWINDOWS__
# undef new
# else
# include "nommgr.h"
# endif
#endif
namespace AtlasMessage
{
// Shared pointers need to be allocated and freed from the same heap.
// So, both sides of the Shareable interface should set these function pointers
// to point to the same function. (The game will have to dynamically load them
// from the DLL.)
extern void* (*ShareableMallocFptr) (size_t n);
extern void (*ShareableFreeFptr) (void* p);
// Implement shared new/delete on top of those
template<typename T> T* ShareableNew()
{
T* p = (T*)ShareableMallocFptr(sizeof(T));
new (p) T;
return p;
}
template<typename T> void ShareableDelete(T* p)
{
p->~T();
ShareableFreeFptr(p);
}
// Or maybe we want to use a non-default constructor
#define SHAREABLE_NEW(T, data) (new ( (T*)AtlasMessage::ShareableMallocFptr(sizeof(T)) ) T data)
}
#ifdef SHAREABLE_USED_NOMMGR
// # ifdef __WXWINDOWS__ // TODO: portability to non-Windows wx
// # define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
// # else
// # include "mmgr.h"
// # endif
// Actually, we don't want to redefine 'new', because it conflicts with all users
// of SHAREABLE_NEW. So just leave it undefined, and put up with the less
// informative leak messages.
# undef SHAREABLE_USED_NOMMGR
// Oh, but we don't want other game headers to include mmgr.h again.
// So let's just cheat horribly and remove the options which cause it to
// redefine new.
# undef HAVE_VC_DEBUG_ALLOC
# define HAVE_VC_DEBUG_ALLOC 0
# undef CONFIG_USE_MMGR
# define CONFIG_USE_MMGR 0
#endif
#endif // SHAREDMEMORY_H__

View File

@ -0,0 +1,40 @@
#ifndef SHAREDTYPES_H__
#define SHAREDTYPES_H__
#include "Shareable.h"
class wxPoint;
class CVector3D;
namespace AtlasMessage
{
struct Position
{
Position() : type(0) { type0.x = type0.y = type0.z = 0.f; }
Position(float x_, float y_, float z_) : type(0) { type0.x = x_; type0.y = y_; type0.z = z_; }
Position(const wxPoint& pt); // (implementation in ScenarioEditor.cpp)
int type;
union {
struct { float x, y, z; } type0; // world-space coordinates
struct { int x, y; } type1; // screen-space coordinates, to be projected onto terrain
// type2: "same as previous" (e.g. for elevation-editing when the mouse hasn't moved)
};
// Constructs a position with the meaning "same as previous", which is handled
// in an unspecified way by various message handlers.
static Position Unchanged() { Position p; p.type = 2; return p; }
// Only for use in the game, not the UI.
// Implementations in Misc.cpp.
void GetWorldSpace(CVector3D& vec) const;
void GetWorldSpace(CVector3D& vec, float h) const;
void GetWorldSpace(CVector3D& vec, const CVector3D& prev) const;
void GetScreenSpace(float& x, float& y) const;
};
SHAREABLE_POD(Position);
}
#endif // SHAREDTYPES_H__