컴포넌트?

컴포넌트는 디자인 패턴의 한 종류인데, 지금 개발 중인 엔진에 해당 패턴이 적용되어 있다.

엔진에서 돌아가는 시스템의 단위는 컴포넌트를 상속하여 구현하였는지에 따라 달라진다.

다음의 코드를 보면 컴포넌트의 간단한 구조를 알 수 있다.

namespace trigger
{
	class transform;
	class component;
	//런타임 중 Instancing 이 가능한 클래스는 해당 Map 에 들어있어야만 한다.
	// 등록을 위한 매크로는 REGI_CLASS 이다.
	// 생성하기 위해 만들어지는
	static std::map<std::string, trigger::transform*> CLASS_ARRAY = 
				 std::map<std::string, trigger::transform*>();

	class component
	{
	protected:
		//해당 클래스의 변수들 중 Engine이 Save, Control 할 수 있는 대상들
		std::shared_ptr<cpptoml::table> _params;
		std::shared_ptr<cpptoml::table> _tmp;
		//클래스의 이름을 hash_code 만들어 보관함
		size_t type_code;
		//클래스의 이름이 들어있음 
		std::string type_name;
		//생성된 ID - 생성시 만들어짐
		int instance_id;
		
	public:
		//World 에서 해당 객체의 Update 여부를 확인하는 용도
		bool active = true;

	public:
		component();
		//상속시 해당 생성자를 호출하여 T_CLASS 를 넘겨주면 된다.
		component( std::string type );
		
		//클래스에서 추가적으로 저장해야 할 변수가 생길 시 구현
		virtual void save();
		virtual ~component();
		size_t get_type_id();
		std::string get_type_name();
		// Save 시 사용할 TOML Table
		auto get_params()->decltype(_params);
		// 해당 객체를 업데이트 해야 할 경우 자손이 구현
		virtual void update(float delta) noexcept = 0;
	};
}

예시

아래의 코드는 위의 컴포넌트를 상속 & 구현한 transform 클래스 입니다.

#include "component.h"

static int make_hash_code();

namespace trigger
{
	class component;
	class transform;
	
	//CLASS_ARRAY 에 들어있는 값을 찾아 복사한다.
	static auto instance(std::string type) -> decltype(auto)
	{
		decltype(trigger::CLASS_ARRAY[type]) tmp = trigger::CLASS_ARRAY[type];
		return tmp;
	};

	class transform : public trigger::component
	{
	protected:
		vec3 real_position;
		vec3 real_scale;
		vec3 real_rotation;
		std::vector<trigger::component*> components;
		std::string name;

	public:
		vec3 position;
		vec3 scale;
		vec3 rotation;
		bool active;
		float time_scale = 1.0f;
	
		transform
		(
			vec3 pos = vec3(0.0f, 0.0f, 0.0f), 
			vec3 scale = vec3(1.0f, 1.0f, 1.0f), 
			vec3 rot = vec3(0.0f, 0.0f, 0.0f), 
			std::string name = "Object"
		) : trigger::component(T_CLASS)
		{
			save();
		};

		std::shared_ptr<cpptoml::table> get_component_toml(std::vector<trigger::component*> vec);
		std::string get_string_from_table(std::shared_ptr<cpptoml::table> table);

		void set_name(std::string name);
		std::string get_name();
		void set_instance_id(int code);

		virtual void save()
		{
			SAVE_TOML(components, get_component_toml(components));
			SAVE_STR(name, name);
			SAVE_STR(real_position , glm::to_string(real_position));
			SAVE_VAR(size_t, type_code);
			SAVE_STR(data, cast<char*>(this));
		}

		virtual ~transform();
		void update(float delta) noexcept;

		template<typename T>
		T* get_component();

		template<typename T>
		bool add_component();

		template<typename T>
		bool add_component(T* component);
		const int get_instance_id() const;
		auto get_components() const;
	};
};