Skip to content

Instantly share code, notes, and snippets.

@alexesDev
Last active December 17, 2015 19:09
Show Gist options
  • Select an option

  • Save alexesDev/5658641 to your computer and use it in GitHub Desktop.

Select an option

Save alexesDev/5658641 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <boost/function.hpp>
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
typedef float Real;
typedef std::string String;
#define ENTITY_MAX_COMPONENT_COUNT 10
#define ENTITY_TYPENAMES(z, n, text) BOOST_PP_COMMA_IF(n) text##n
#define ENTITY_DEFINE_COMPONENT(z, n, text) T##n text##n;
#define ENTITY_DEFINE_ENTITY_SETTER(z, n, text) component##n.text(*this);
#define ENTITY_DEFINE_COMPONENT_GETTER(z, n, text) \
template<class INNER_T> \
typename boost::enable_if<boost::is_base_of<T##n, INNER_T>, INNER_T>::type & text() \
{ \
return component##n;\
}
#define ENTITY_DECLARATION(z, n, text) \
template<BOOST_PP_REPEAT(n, ENTITY_TYPENAMES, class T)> \
class text<BOOST_PP_REPEAT(n, ENTITY_TYPENAMES, T)> : public BaseEntity \
{ \
BOOST_PP_REPEAT(n, ENTITY_DEFINE_COMPONENT, component)\
public: \
text(BaseEntity *parent) : BaseEntity(parent) \
{ \
BOOST_PP_REPEAT(n, ENTITY_DEFINE_ENTITY_SETTER, setEntity)\
} \
BOOST_PP_REPEAT(n, ENTITY_DEFINE_COMPONENT_GETTER, get) \
};
class BaseEntity
{
BaseEntity *mParent;
public:
BaseEntity(BaseEntity *parent) : mParent(parent)
{
}
const BaseEntity &getParent()
{
return *mParent;
}
};
template <typename ...Dummy>
class Entity;
BOOST_PP_REPEAT(ENTITY_MAX_COMPONENT_COUNT, ENTITY_DECLARATION, Entity)
class RenderEngine
{
};
class OgreRenderEngine : public RenderEngine
{
};
class Scene : public BaseEntity
{
RenderEngine *mRenderEngine;
public:
Scene(RenderEngine *renderEngine) : BaseEntity(nullptr), mRenderEngine(renderEngine)
{
}
void show()
{
}
void hide()
{
}
};
class Component
{
BaseEntity *mEntity;
public:
void setEntity(BaseEntity &value)
{
mEntity = &value;
}
const BaseEntity &getEntity()
{
return *mEntity;
}
};
class Transforms : public Component
{
public:
Transforms &setPosition(Real x, Real y, Real z)
{
return *this;
}
Transforms &setScale(Real x, Real y, Real z)
{
return *this;
}
Transforms &setOrientation(Real w, Real x, Real y, Real z)
{
return *this;
}
};
class MeshRenderer : public Component
{
public:
MeshRenderer &setName(const String &value)
{
return *this;
}
MeshRenderer &setMaterialName(const String &value)
{
return *this;
}
};
class Script : public Component
{
public:
Script &setName(const String &value)
{
return *this;
}
};
class Camera : public Component
{
public:
Camera &setPosition(Real x, Real y, Real z)
{
return *this;
}
Camera &lookAt(Real x, Real y, Real z)
{
return *this;
}
};
class CubeController : public Script
{
public:
CubeController() : Script()
{
setName("cube_controller.as");
}
};
class CubeEntity : public Entity<Transforms, MeshRenderer, CubeController>
{
public:
CubeEntity(BaseEntity *parent) : Entity(parent)
{
get<MeshRenderer>()
.setName("cube.mesh")
.setMaterialName("Bricks");
}
};
int main()
{
OgreRenderEngine renderEngine;
Scene scene(&renderEngine);
Entity<Camera> camera(&scene);
camera.get<Camera>()
.setPosition(50, 50, 50)
.lookAt(0, 0, 0);
for(int i = 0; i < 10; ++i)
{
CubeEntity cube(&scene);
cube.get<Transforms>()
.setPosition(i * 2, 0, 0)
.setOrientation(1, 0.5, 0, 0);
}
scene.show();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment