/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : Interface to manage SoftCode module loading and patching
#ifndef CRYINCLUDE_CRYCOMMON_ISOFTCODEMGR_H
#define CRYINCLUDE_CRYCOMMON_ISOFTCODEMGR_H
#pragma once
// Provides the generic interface for exchanging member values between SoftCode modules,
struct IExchangeValue
{
//
virtual ~IExchangeValue() {}
// Allocates a new IExchangeValue with the underlying type
virtual IExchangeValue* Clone() const = 0;
// Returns the size of the underlying type (to check compatibility)
virtual size_t GetSizeOf() const = 0;
//
};
template
struct ExchangeValue
: public IExchangeValue
{
ExchangeValue(T& value)
: m_value(value)
{}
virtual IExchangeValue* Clone() const { return new ExchangeValue(*this); }
virtual size_t GetSizeOf() const { return sizeof(m_value); }
T m_value;
};
template
struct ExchangeArray
: public IExchangeValue
{
ExchangeArray(T* pArr)
{
for (size_t i = 0; i < S; ++i)
{
m_array[i] = pArr[i];
}
}
virtual IExchangeValue* Clone() const { return new ExchangeArray(*this); }
virtual size_t GetSizeOf() const { return sizeof(m_array); }
T m_array[S];
};
/*
This is a non-intrusive support function for types where default construction does no initialization.
SoftCoding relies on default construction to initialize object state correctly.
For most types this works as expected but for some types (typically things like vectors or matrices)
default initialization would be too costly and is therefore not implemented.
This function allows a specialized implementation to be used for such types that will perform
initialization on the newly constructed instance. For example:
inline void DefaultInitialize(Matrix34& matrix)
{
matrix.SetIdentity();
}
*/
template
void DefaultInitialize(T& t)
{
t = T();
}
// Vector support
template
struct Vec2_tpl;
template
struct Vec3_tpl;
template
void DefaultInitialize(Vec2_tpl& vec) { vec.zero(); }
template
void DefaultInitialize(Vec3_tpl& vec) { vec.zero(); }
// Matrix support
template
struct Matrix33_tpl;
template
struct Matrix34_tpl;
template
struct Matrix44_tpl;
template
void DefaultInitialize(Matrix33_tpl& matrix) { matrix.SetIdentity(); }
template
void DefaultInitialize(Matrix34_tpl& matrix) { matrix.SetIdentity(); }
template
void DefaultInitialize(Matrix44_tpl& matrix) { matrix.SetIdentity(); }
// Quat support
template
struct Quat_tpl;
template
void DefaultInitialize(Quat_tpl& quat) { quat.SetIdentity(); }
// Interface for performing an exchange of instance data
struct IExchanger
{
//
virtual ~IExchanger() {}
// True if data is being read from instance members
virtual bool IsLoading() const = 0;
virtual size_t InstanceCount() const = 0;
virtual bool BeginInstance(void* pInstance) = 0;
virtual bool SetValue(const char* name, IExchangeValue& value) = 0;
virtual IExchangeValue* GetValue(const char* name, void* pTarget, size_t targetSize) = 0;
//
template
void Visit(const char* name, T& instance);
template
void Visit(const char* name, T (&arr)[S]);
};
template
void IExchanger::Visit(const char* name, T& value)
{
if (IsLoading())
{
IExchangeValue* pValue = GetValue(name, &value, sizeof(value));
if (pValue)
{
ExchangeValue* pTypedValue = static_cast*>(pValue);
value = pTypedValue->m_value;
}
}
else // Saving
{
// If this member is stored
if (SetValue(name, ExchangeValue(value)))
{
// Set the original value to the default state (to allow safe destruction)
DefaultInitialize(value);
}
}
}
template
void IExchanger::Visit(const char* name, T (&arr)[S])
{
if (IsLoading())
{
IExchangeValue* pValue = GetValue(name, &arr, sizeof(arr));
if (pValue)
{
ExchangeArray* pTypedArray = static_cast*>(pValue);
// TODO: Accommodate array resizing? Complex however...
for (size_t i = 0; i < S; ++i)
{
arr[i] = pTypedArray->m_array[i];
}
}
}
else // Saving
{
// If this member is stored
if (SetValue(name, ExchangeArray(arr)))
{
T defaultValue;
DefaultInitialize(defaultValue);
// Set the original value to the default value (to allow safe destruction)
for (size_t i = 0; i < S; ++i)
{
arr[i] = defaultValue;
}
}
}
}
struct InstanceTracker;
struct ITypeRegistrar
{
//
virtual ~ITypeRegistrar() {}
virtual const char* GetName() const = 0;
// Creates an instance of the type
virtual void* CreateInstance() = 0;
//
#ifdef SOFTCODE_ENABLED
// How many active instances exist of this type?
virtual size_t InstanceCount() const = 0;
// Used to remove a tracked instance from the Registrar
virtual void RemoveInstance(InstanceTracker* pTracker) = 0;
// Exchanges the instance state with the given exchanger data set
virtual bool ExchangeInstances(IExchanger& exchanger) = 0;
// Destroys all tracked instances of this type
virtual bool DestroyInstances() = 0;
// Returns true if pInstance is of this type (linear search)
virtual bool HasInstance(void* pInstance) const = 0;
#endif
};
struct ITypeLibrary
{
//
virtual ~ITypeLibrary() {}
virtual const char* GetName() = 0;
virtual void* CreateInstanceVoid(const char* typeName) = 0;
//
#ifdef SOFTCODE_ENABLED
virtual void SetOverride(ITypeLibrary* pOverrideLib) = 0;
// Fills in the supplied type list if large enough, and sets count to number of types
virtual size_t GetTypes(ITypeRegistrar** ppRegistrar, size_t& count) const = 0;
#endif
};
struct ISoftCodeListener
{
//
virtual ~ISoftCodeListener() {}
// Called when an instance is replaced to allow managing systems to fixup pointers
virtual void InstanceReplaced(void* pOldInstance, void* pNewInstance) = 0;
//
};
/// Interface for ...
struct ISoftCodeMgr
{
//
virtual ~ISoftCodeMgr() {}
// Used to register built-in libraries on first use
virtual void RegisterLibrary(ITypeLibrary* pLib) = 0;
// Loads any new SoftCode modules
virtual void LoadNewModules() = 0;
virtual void AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName) = 0;
virtual void RemoveListener(const char* libraryName, ISoftCodeListener* pListener) = 0;
// To be called regularly to poll for library updates
virtual void PollForNewModules() = 0;
// Stops thread execution until a new SoftCode instance is available
virtual void* WaitForUpdate(void* pInstance) = 0;
/// Frees this instance from memory
//virtual void Release() = 0;
//
};
#endif // CRYINCLUDE_CRYCOMMON_ISOFTCODEMGR_H