Skip to content

Instantly share code, notes, and snippets.

@Cry-Flare
Created March 7, 2019 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cry-Flare/50280148d6ceae8e3ef961625bcb4eb5 to your computer and use it in GitHub Desktop.
Save Cry-Flare/50280148d6ceae8e3ef961625bcb4eb5 to your computer and use it in GitHub Desktop.
Example showing how to store interface offsets for use with the CRYENGINE EntityComponent system
#include <StdAfx.h>
#include "DerivedComponent.h"
#include <CryCore/StaticInstanceList.h>
void DerivedComponent::func1()
{
CryLogAlways("DerivedComponent: 1");
}
void DerivedComponent::func2()
{
CryLogAlways("DerivedComponent: 2");
}
static void RegisterDerivedComponent(Schematyc::IEnvRegistrar& registrar)
{
Schematyc::CEnvRegistrationScope scope = registrar.Scope(IEntity::GetEntityScopeGUID());
{
Schematyc::CEnvRegistrationScope componentScope = scope.Register(SCHEMATYC_MAKE_ENV_COMPONENT(DerivedComponent));
}
}
CRY_STATIC_AUTO_REGISTER_FUNCTION(&RegisterDerivedComponent);
#pragma once
#include "IDerivableComponent.h"
#include "Interface1.h"
#include "Interface2.h"
class DerivedComponent : public IDerivableComponent, public Interface1, public Interface2
{
public:
DerivedComponent()
{
StoreBases<DerivedComponent, Interface1, Interface2>();
};
virtual ~DerivedComponent() {}
static void ReflectType(Schematyc::CTypeDesc<DerivedComponent>& desc)
{
desc.SetEditorCategory("TestCat");
desc.SetLabel("DerivedComponent");
desc.SetGUID("{BE7743A4-041B-41F0-849E-15408E237C4C}"_cry_guid);
desc.AddBase<IDerivableComponent>();
desc.AddBase<Interface1>();
desc.AddBase<Interface2>();
}
virtual void func1() override;
virtual void func2() override;
};
#pragma once
#include <CrySchematyc/CoreAPI.h>
class IDerivableComponent : public IEntityComponent
{
public:
static void ReflectType(Schematyc::CTypeDesc<IDerivableComponent>& desc)
{
desc.SetGUID("{BE7743A4-041B-41F0-849E-15402E237C4A}"_cry_guid);
}
template <class Base>
Base* GetBase() const
{
uintptr_t offset;
if (GetBaseOffset<Base>(offset))
{
uintptr_t ptrBase = reinterpret_cast<uintptr_t>(this) + offset;
return reinterpret_cast<Base*>(ptrBase);
}
else
{
return nullptr;
}
}
protected:
template <class Derived, class... Bases>
void StoreBases()
{
m_baseOffsets = {StoreBase<Derived, Bases>(Schematyc::GetTypeGUID<Bases>())...};
}
private:
template <class Derived, class Base>
const std::pair<CryGUID, uintptr_t> StoreBase(CryGUID guid)
{
const uintptr_t offset = CalculateBaseOffset<Derived, Base>();
return std::pair<CryGUID, uintptr_t>(guid, offset);
}
template <class Derived, class Base>
uintptr_t CalculateBaseOffset() const
{
const uintptr_t ptrBase = reinterpret_cast<uintptr_t>(static_cast<const Base*>(reinterpret_cast<const Derived*>(this)));
const uintptr_t ptrDerived = reinterpret_cast<uintptr_t>(this);
return ptrBase - ptrDerived;
}
template <class Base>
bool GetBaseOffset(uintptr_t& out_offset) const
{
for (const std::pair<CryGUID, uintptr_t>& pair : m_baseOffsets)
{
if (pair.first == Schematyc::GetTypeGUID<Base>())
{
out_offset = pair.second;
return true;
}
}
return false;
}
protected:
std::vector<std::pair<CryGUID, uintptr_t>> m_baseOffsets;
};
#pragma once
#include <CrySchematyc/CoreAPI.h>
struct Interface1
{
virtual void func1() = 0;
static void ReflectType(Schematyc::CTypeDesc<Interface1>& desc) {
desc.SetGUID("{2AC2CF46-127E-4A81-B38E-5FE84BAFC476}"_cry_guid);
}
};
#pragma once
#include <CrySchematyc/CoreAPI.h>
struct Interface2
{
virtual void func2() = 0;
static void ReflectType(Schematyc::CTypeDesc<Interface2>& desc) {
desc.SetGUID("{2AC2CF46-127E-4A81-B38E-5FE84BAFC475}"_cry_guid);
}
};
#include "StdAfx.h"
#include "Player.h"
#include "IDerivableComponent.h"
#include "DerivedComponent.h"
#include <CryRenderer/IRenderAuxGeom.h>
void CPlayerComponent::Initialize()
{
// Add Derived Component to this entity:
DerivedComponent* pD = m_pEntity->GetOrCreateComponent<DerivedComponent>();
// Get the pointer to the IEntityComponent interface
IEntityComponent* pEntityComponent = m_pEntity->QueryComponentByInterfaceID(Schematyc::GetTypeGUID<Interface1>());
// Get the IDerivableComponent by casting from the IEntityComponent pointer
IDerivableComponent* pDerivable = reinterpret_cast<IDerivableComponent*>(pEntityComponent);
// Try to get the Interface1 from this pointer (Should be garunteed as that was what we queried earlier)
if (Interface1* pInterface1 = pDerivable->GetBase<Interface1>())
pInterface1->func1();
// We know this is the case, but this is not garunteed and will give nullptr if this interface doesnt exist in this component.
if (Interface2* pInterface2 = pDerivable->GetBase<Interface2>())
pInterface2->func2();
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment