Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Core/GameEngine/Include/Common/GameMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@
#define allocateBlockDoNotZero(ARGLITERAL) allocateBlockDoNotZeroImplementation(ARGLITERAL MP_LOC_SUFFIX)
#define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT, ARGLITERAL MP_LOC_SUFFIX)
#define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT, ARGLITERAL MP_LOC_SUFFIX)
#define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED, ARGLITERAL MP_LOC_SUFFIX) ARGCLASS
#define newInstance(ARGCLASS) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED, __FILE__) ARGCLASS
#define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::GLUE_NOT_IMPLEMENTED, ARGLITERAL MP_LOC_SUFFIX) ARGCLASS
#define newInstance(ARGCLASS) new(ARGCLASS::GLUE_NOT_IMPLEMENTED, __FILE__) ARGCLASS

#else

Expand All @@ -210,8 +210,8 @@
#define allocateBlockDoNotZero(ARGLITERAL) allocateBlockDoNotZeroImplementation()
#define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT)
#define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT)
#define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED) ARGCLASS
#define newInstance(ARGCLASS) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED) ARGCLASS
#define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::GLUE_NOT_IMPLEMENTED) ARGCLASS
#define newInstance(ARGCLASS) new(ARGCLASS::GLUE_NOT_IMPLEMENTED) ARGCLASS

#endif

Expand Down Expand Up @@ -621,7 +621,7 @@ private: \
protected: \
virtual ~ARGCLASS(); \
public: \
enum ARGCLASS##MagicEnum { ARGCLASS##_GLUE_NOT_IMPLEMENTED = 0 }; \
enum ARGCLASS##MagicEnum { GLUE_NOT_IMPLEMENTED = 0 }; \
public: \
inline void *operator new(size_t s, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \
{ \
Expand Down Expand Up @@ -692,7 +692,7 @@ private: \
protected: \
virtual ~ARGCLASS(); \
public: \
enum ARGCLASS##MagicEnum { ARGCLASS##_GLUE_NOT_IMPLEMENTED = 0 }; \
enum ARGCLASS##MagicEnum { GLUE_NOT_IMPLEMENTED = 0 }; \
protected: \
inline void *operator new(size_t s, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \
{ \
Expand Down
66 changes: 66 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/SubsystemInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,72 @@ class SubsystemInterface

};

template <typename T>
class OverridableInterface
{
public:
virtual T* findInstance(const AsciiString& name) = 0;
virtual T* createInstance(const AsciiString& name) = 0;
virtual void onCreatedOverride(T* instance) {};

template <typename F>
static T* parseDefinition(INI* ini, F* factory, const AsciiString& name, bool initFromINI = true)
{
static_assert(requires { static_cast<SubsystemInterface*>(factory); }, "Factory must be able to reset overrides.");

T* instance = factory->findInstance(name);

if (!instance)
{
instance = factory->createInstance(name);
DEBUG_ASSERTCRASH(instance, ("Factory create function should not return a nullptr"));

if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES)
{
instance->markAsOverride();
}
}
else if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES)
{
instance = createOverride(instance);

factory->onCreatedOverride(instance);
}
else
{
DEBUG_CRASH(("[LINE: %d in '%s'] Duplicate instance of %s found!", ini->getLineNum(), ini->getFilename().str(), name.str()));

throw INI_INVALID_DATA;
}

if (initFromINI)
{
ini->initFromINI(instance, instance->getFieldParse());
}

return instance;
}

private:
static T* createOverride(T* instance)
{
// find final override of the 'parent' instance
T* child = static_cast<T*>(instance->friend_getFinalOverride());

// allocate new instance
T* overrideInstance = new(T::GLUE_NOT_IMPLEMENTED) T;

// copy data from final override to 'overrideInstance' as a set of initial default values
*overrideInstance = *child;

overrideInstance->markAsOverride();
child->setNextOverride(overrideInstance);

// return the newly created override for us to set values with etc
return overrideInstance;
}
};

//-------------------------------------------------------------------------------------------------
class SubsystemInterfaceList
{
Expand Down
Loading