forked from 0ad/0ad
Ykkrosh
35e91718c5
Atlas: Added ActorViewer. Moved GL canvas into separate class for shared use. Disabled message-handling callback while blocked on the game, and stopped creating dialog boxes inside the game thread in order to avoid deadlocks (hopefully). Support multiple Views (for independent sets of camera/update/render code). Recalculate territory boundaries when necessary. Changed default list of animations to match those currently used by actors. # Tidied up more code. Moved some more #includes out of .h files, to minimise unnecessary compilation. MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2 (use PI/2), MAX3, ABS (use abs)). ObjectManager: Removed some ScEd-specific things. Unit: Moved creation out of UnitManager, so units can be created without adding to the manager. Changed CStr8 to the more conventional CStr. app_hooks: Removed warning for setting multiple times. win: Restored SEH catcher. GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do what it says it does ("force renderer to load everything") since we're loading-on-demand most stuff and it doesn't seem especially useful since we'd prefer to minimise loading times (but feel free to correct me if I'm wrong). (And because it crashes when things need to be initialised in a different order, so it's easier to remove than to understand and fix it.) PatchRData, Renderer: Work sensibly when there's no game (hence no LOS manager, water, etc). LOSManager: Use entity position instead of actor position when possible. TerritoryManager: Allow delayed recalculations (so Atlas can issue lots of move+recalculate commands per frame). Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to be deleted manually. This was SVN commit r4261.
192 lines
5.1 KiB
C++
192 lines
5.1 KiB
C++
// Used by Messages.h, so that file stays relatively clean.
|
|
|
|
#ifndef MESSAGESSETUP_NOTFIRST
|
|
#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 CMutex;
|
|
|
|
namespace AtlasMessage
|
|
{
|
|
|
|
struct IMessage
|
|
{
|
|
virtual const char* GetName() const = 0;
|
|
virtual ~IMessage() {}
|
|
|
|
enum Type { Message, Query };
|
|
virtual Type GetType() const = 0;
|
|
};
|
|
|
|
|
|
#define MESSAGESTRUCT(t) \
|
|
struct m##t : public IMessage { \
|
|
virtual const char* GetName() const { return #t; } \
|
|
virtual Type GetType() const { return IMessage::Message; } \
|
|
private: \
|
|
const m##t& operator=(const m##t&); \
|
|
public:
|
|
|
|
// Messages for doing/undoing/etc world-altering commands
|
|
|
|
MESSAGESTRUCT(WorldCommand)
|
|
mWorldCommand() {}
|
|
virtual void* CloneData() const = 0;
|
|
virtual bool IsMergeable() const = 0;
|
|
};
|
|
MESSAGESTRUCT(DoCommand)
|
|
mDoCommand(mWorldCommand* c) : name(c->GetName()), data(c->CloneData()) {}
|
|
const Shareable<std::string> name;
|
|
const Shareable<void*> data;
|
|
// 'data' gets deallocated by ~cWhatever in the game thread
|
|
};
|
|
MESSAGESTRUCT(UndoCommand) };
|
|
MESSAGESTRUCT(RedoCommand) };
|
|
MESSAGESTRUCT(MergeCommand) };
|
|
|
|
|
|
struct QueryMessage : public IMessage
|
|
{
|
|
Type GetType() const { return IMessage::Query; }
|
|
void Post(); // defined in ScenarioEditor.cpp
|
|
|
|
void* m_Semaphore; // for use by MessagePasser implementations (yay encapsulation)
|
|
};
|
|
|
|
|
|
#define QUERYSTRUCT(t) \
|
|
struct q##t : public QueryMessage { \
|
|
const char* GetName() const { return #t; } \
|
|
private: \
|
|
const q##t& operator=(const q##t&); \
|
|
public:
|
|
|
|
|
|
|
|
const bool MERGE = true;
|
|
const bool NOMERGE = false;
|
|
|
|
|
|
#define COMMANDDATASTRUCT(t) \
|
|
struct d##t { \
|
|
private: \
|
|
const d##t& operator=(const d##t&); \
|
|
public:
|
|
|
|
#define COMMANDSTRUCT(t, merge) \
|
|
struct m##t : public mWorldCommand, public d##t { \
|
|
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 SHAREABLE_NEW(d##t, (*this)); } \
|
|
private: \
|
|
const m##t& operator=(const m##t&);\
|
|
};
|
|
|
|
|
|
|
|
#include <boost/preprocessor/tuple/elem.hpp>
|
|
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
|
#include <boost/preprocessor/seq/for_each_i.hpp>
|
|
#include <boost/preprocessor/comparison/equal.hpp>
|
|
|
|
#define B_TYPE(elem) BOOST_PP_TUPLE_ELEM(2, 0, elem)
|
|
#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 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 Shareable<int> in0;
|
|
const Shareable<bool> in1;
|
|
}
|
|
*/
|
|
|
|
#define MESSAGE_WITH_INPUTS(name, vals) \
|
|
MESSAGESTRUCT(name) \
|
|
m##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, vals) ) \
|
|
: BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, vals) {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, vals) \
|
|
};
|
|
|
|
#define MESSAGE_WITHOUT_INPUTS(name, vals) \
|
|
MESSAGESTRUCT(name) \
|
|
m##name() {} \
|
|
};
|
|
|
|
#define MESSAGE(name, vals) \
|
|
BOOST_PP_IIF( \
|
|
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE((~)vals), 1), \
|
|
MESSAGE_WITHOUT_INPUTS, \
|
|
MESSAGE_WITH_INPUTS) \
|
|
(name, vals)
|
|
|
|
|
|
|
|
#define COMMAND(name, merge, vals) \
|
|
COMMANDDATASTRUCT(name) \
|
|
d##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, vals) ) \
|
|
: BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, vals) {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, vals) \
|
|
}; \
|
|
COMMANDSTRUCT(name, merge);
|
|
|
|
|
|
// Need different syntax depending on whether there are some input values in the query:
|
|
|
|
#define QUERY_WITHOUT_INPUTS(name, in_vals, out_vals) \
|
|
QUERYSTRUCT(name) \
|
|
q##name() {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_MEMBERS, ~, out_vals) /* other members */ \
|
|
};
|
|
|
|
#define QUERY_WITH_INPUTS(name, in_vals, out_vals) \
|
|
QUERYSTRUCT(name) \
|
|
q##name( BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORARGS, ~, in_vals) ) \
|
|
: BOOST_PP_SEQ_FOR_EACH_I(B_CONSTRUCTORINIT, ~, in_vals) {} \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_CONSTMEMBERS, ~, in_vals) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(B_MEMBERS, ~, out_vals) \
|
|
};
|
|
|
|
#define QUERY(name, in_vals, out_vals) \
|
|
BOOST_PP_IIF( \
|
|
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE((~)in_vals), 1), \
|
|
QUERY_WITHOUT_INPUTS, \
|
|
QUERY_WITH_INPUTS) \
|
|
(name, in_vals, out_vals)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#else // MESSAGESSETUP_NOTFIRST => clean up the mess
|
|
|
|
#undef MESSAGESTRUCT
|
|
#undef QUERYSTRUCT
|
|
#undef COMMANDDATASTRUCT
|
|
#undef COMMANDSTRUCT
|
|
#undef B_TYPE
|
|
#undef B_NAME
|
|
#undef B_CONSTRUCTORARGS
|
|
#undef B_CONSTRUCTORINIT
|
|
#undef B_CONSTMEMBERS
|
|
#undef B_MEMBERS
|
|
#undef MESSAGE
|
|
#undef COMMAND
|
|
#undef QUERY_WITHOUT_INPUTS
|
|
#undef QUERY_WITH_INPUTS
|
|
#undef QUERY
|
|
|
|
}
|
|
|
|
#endif
|