Compare commits
	
		
			4 commits
		
	
	
		
			68c49ebdfb
			...
			41575df141
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 41575df141 | |||
| 237d852ede | |||
| 879d375b7f | |||
| 8defb9a3ec | 
					 14 changed files with 199 additions and 135 deletions
				
			
		| 
						 | 
					@ -19,7 +19,7 @@ public:
 | 
				
			||||||
	template<typename Component_T>
 | 
						template<typename Component_T>
 | 
				
			||||||
	auto add(Component_T component) -> Component_T &
 | 
						auto add(Component_T component) -> Component_T &
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_registry->add(m_identifier, component);
 | 
							return m_registry->add(m_identifier, component);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template<typename Component_T>
 | 
						template<typename Component_T>
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,6 @@ public:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	memory::Ref<Registry> m_registry;
 | 
						memory::Ref<Registry> m_registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	EntityId m_identifier;
 | 
						EntityId m_identifier;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,30 +64,25 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (input.get_action(m_quit_action_key).state == State::active)
 | 
								if (input.get_action(m_quit_action_key).state == State::active)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_dbg("Quit triggered! BYE!");
 | 
					 | 
				
			||||||
				should_quit = true;
 | 
									should_quit = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (input.get_action(m_debug_action_keys[0]).state == State::active)
 | 
								if (input.get_action(m_debug_action_keys[0]).state == State::active)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_dbg("Deubg action 1");
 | 
					 | 
				
			||||||
				surface.push_request(surface::ModifyPositionRequest({ x + 5, y + 5 }));
 | 
									surface.push_request(surface::ModifyPositionRequest({ x + 5, y + 5 }));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (input.get_action(m_debug_action_keys[1]).state == State::active)
 | 
								if (input.get_action(m_debug_action_keys[1]).state == State::active)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_dbg("Deubg action 2");
 | 
					 | 
				
			||||||
				surface.push_request(surface::ModifyPositionRequest({ x - 5, y - 5 }));
 | 
									surface.push_request(surface::ModifyPositionRequest({ x - 5, y - 5 }));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (input.get_action(m_debug_action_keys[2]).state == State::active)
 | 
								if (input.get_action(m_debug_action_keys[2]).state == State::active)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_dbg("Deubg action 3");
 | 
					 | 
				
			||||||
				surface.push_request(surface::ModifyResolutionRequest({ width + 5, height + 5 }));
 | 
									surface.push_request(surface::ModifyResolutionRequest({ width + 5, height + 5 }));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (input.get_action(m_debug_action_keys[3]).state == State::active)
 | 
								if (input.get_action(m_debug_action_keys[3]).state == State::active)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_dbg("Deubg action 4");
 | 
					 | 
				
			||||||
				surface.push_request(surface::ModifyResolutionRequest({ width - 5, height - 5 }));
 | 
									surface.push_request(surface::ModifyResolutionRequest({ width - 5, height - 5 }));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -154,7 +149,7 @@ public:
 | 
				
			||||||
		m_surface_system = memory::create_ref<lt::surface::System>(m_editor_registry);
 | 
							m_surface_system = memory::create_ref<lt::surface::System>(m_editor_registry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m_window = m_editor_registry->create_entity();
 | 
							m_window = m_editor_registry->create_entity();
 | 
				
			||||||
		m_editor_registry->add<SurfaceComponent>(
 | 
							m_surface_system->create_component(
 | 
				
			||||||
		    m_window,
 | 
							    m_window,
 | 
				
			||||||
		    SurfaceComponent::CreateInfo {
 | 
							    SurfaceComponent::CreateInfo {
 | 
				
			||||||
		        .title = "Editor Window",
 | 
							        .title = "Editor Window",
 | 
				
			||||||
| 
						 | 
					@ -217,12 +212,15 @@ public:
 | 
				
			||||||
		    .surface_entity = entity,
 | 
							    .surface_entity = entity,
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// entity.add<renderer::MessengerComponent>({
 | 
							m_renderer_system->create_messenger_component(
 | 
				
			||||||
		//     .severities = renderer::MessageSeverity::all,
 | 
							    m_window,
 | 
				
			||||||
		//     .types = renderer::MessageType::all,
 | 
							    renderer::MessengerComponent::CreateInfo {
 | 
				
			||||||
		//     .callback = &renderer_callback,
 | 
							        .severities = renderer::MessageSeverity::all,
 | 
				
			||||||
		//     .user_data = this,
 | 
							        .types = renderer::MessageType::all,
 | 
				
			||||||
		// });
 | 
							        .callback = &renderer_callback,
 | 
				
			||||||
 | 
							        .user_data = this,
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_input_system()
 | 
						void setup_input_system()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <ecs/entity.hpp>
 | 
					#include <ecs/entity.hpp>
 | 
				
			||||||
#include <memory/pointer_types/null_on_move.hpp>
 | 
					#include <memory/pointer_types/null_on_move.hpp>
 | 
				
			||||||
#include <memory/scope.hpp>
 | 
					#include <memory/scope.hpp>
 | 
				
			||||||
 | 
					#include <renderer/backend/vk/context/swapchain.hpp>
 | 
				
			||||||
#include <renderer/frontend/context/context.hpp>
 | 
					#include <renderer/frontend/context/context.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace lt::renderer::vk {
 | 
					namespace lt::renderer::vk {
 | 
				
			||||||
| 
						 | 
					@ -43,7 +44,11 @@ public:
 | 
				
			||||||
	void recreate_swapchain() override
 | 
						void recreate_swapchain() override
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		m_swapchain.reset();
 | 
							m_swapchain.reset();
 | 
				
			||||||
		// m_swapchain = memory::create_scope<vk::Swapchain>(m_device, m_surface);
 | 
							m_swapchain = memory::create_scope<vk::Swapchain>(
 | 
				
			||||||
 | 
							    m_surface.get(),
 | 
				
			||||||
 | 
							    m_gpu.get(),
 | 
				
			||||||
 | 
							    m_device.get()
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,7 @@ Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
 | 
				
			||||||
	        .oldSwapchain = nullptr,
 | 
						        .oldSwapchain = nullptr,
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
						m_resolution = capabilities.currentExtent;
 | 
				
			||||||
	m_device->name(m_swapchain, "swapchain {}", idx++);
 | 
						m_device->name(m_swapchain, "swapchain {}", idx++);
 | 
				
			||||||
	m_device->wait_idle();
 | 
						m_device->wait_idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,13 +7,13 @@ Messenger::Messenger(IInstance *instance, ecs::Entity entity)
 | 
				
			||||||
    , m_entity(std::move(entity))
 | 
					    , m_entity(std::move(entity))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const auto &component = entity.get<MessengerComponent>();
 | 
						const auto &component = m_entity.get<MessengerComponent>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m_debug_messenger = m_instance->create_messenger(
 | 
						m_debug_messenger = m_instance->create_messenger(
 | 
				
			||||||
	    VkDebugUtilsMessengerCreateInfoEXT {
 | 
						    VkDebugUtilsMessengerCreateInfoEXT {
 | 
				
			||||||
	        .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
 | 
						        .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
 | 
				
			||||||
	        .messageSeverity = to_native_severity(component.severities),
 | 
						        .messageSeverity = to_native_severity(component.get_severities()),
 | 
				
			||||||
	        .messageType = to_native_type(component.types),
 | 
						        .messageType = to_native_type(component.get_types()),
 | 
				
			||||||
	        .pfnUserCallback = &native_callback,
 | 
						        .pfnUserCallback = &native_callback,
 | 
				
			||||||
	        .pUserData = this,
 | 
						        .pUserData = this,
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
| 
						 | 
					@ -43,13 +43,13 @@ Messenger::~Messenger()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto *messenger = (Messenger *)vulkan_user_data; // NOLINT
 | 
							auto *messenger = (Messenger *)vulkan_user_data; // NOLINT
 | 
				
			||||||
		auto &component = messenger->m_entity.get<MessengerComponent>();
 | 
							auto &component = messenger->m_entity.get<MessengerComponent>();
 | 
				
			||||||
		component.callback(
 | 
							component.get_callback()(
 | 
				
			||||||
		    from_native_severity(severity),
 | 
							    from_native_severity(severity),
 | 
				
			||||||
		    from_native_type(type),
 | 
							    from_native_type(type),
 | 
				
			||||||
		    {
 | 
							    {
 | 
				
			||||||
		        .message = callback_data->pMessage,
 | 
							        .message = callback_data->pMessage,
 | 
				
			||||||
		    },
 | 
							    },
 | 
				
			||||||
		    component.user_data
 | 
							    component.get_user_data()
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	catch (const std::exception &exp)
 | 
						catch (const std::exception &exp)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,6 +136,7 @@ void Renderer::replace_swapchain(ISwapchain *swapchain)
 | 
				
			||||||
	m_device->wait_idle();
 | 
						m_device->wait_idle();
 | 
				
			||||||
	m_swapchain = static_cast<Swapchain *>(swapchain);
 | 
						m_swapchain = static_cast<Swapchain *>(swapchain);
 | 
				
			||||||
	m_resolution = m_swapchain->get_resolution();
 | 
						m_resolution = m_swapchain->get_resolution();
 | 
				
			||||||
 | 
						m_pass->replace_swapchain(*swapchain);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
 | 
					void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,6 @@ namespace lt::renderer {
 | 
				
			||||||
	switch (target_api)
 | 
						switch (target_api)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	case API::Vulkan: return memory::create_scope<vk::Messenger>(instance, std::move(entity));
 | 
						case API::Vulkan: return memory::create_scope<vk::Messenger>(instance, std::move(entity));
 | 
				
			||||||
 | 
					 | 
				
			||||||
	case API::Metal:
 | 
						case API::Metal:
 | 
				
			||||||
	case API::DirectX: throw std::runtime_error { "Invalid API" };
 | 
						case API::DirectX: throw std::runtime_error { "Invalid API" };
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,10 +19,6 @@ System::System(CreateInfo info)
 | 
				
			||||||
	ensure(m_registry, "Failed to initialize renderer system: null registry");
 | 
						ensure(m_registry, "Failed to initialize renderer system: null registry");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m_renderer = IRenderer::create(m_api, *m_context, info.config.max_frames_in_flight);
 | 
						m_renderer = IRenderer::create(m_api, *m_context, info.config.max_frames_in_flight);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// WIP(Light): attach debug messenger on messenger component construction
 | 
					 | 
				
			||||||
	// m_registry->connect_on_construct<renderer::MessengerComponent>([](ecs::Registry ®istry,
 | 
					 | 
				
			||||||
	//                                                                   ecs::EntityId entity) {});
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
System::~System()
 | 
					System::~System()
 | 
				
			||||||
| 
						 | 
					@ -62,4 +58,21 @@ void System::tick(app::TickInfo tick)
 | 
				
			||||||
	m_frame_idx = (m_frame_idx + 1) % m_max_frames_in_flight;
 | 
						m_frame_idx = (m_frame_idx + 1) % m_max_frames_in_flight;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void System::create_messenger_component(ecs::EntityId entity, MessengerComponent::CreateInfo info)
 | 
				
			||||||
 | 
					try
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto &component = m_registry->add<MessengerComponent>(entity, std::move(info));
 | 
				
			||||||
 | 
						component.m_implementation = IMessenger::create(
 | 
				
			||||||
 | 
						    m_api,
 | 
				
			||||||
 | 
						    m_context->instance(),
 | 
				
			||||||
 | 
						    { m_registry, entity }
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					catch (const std::exception &exp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						log_err("Failed to create renderer::MessengerComponent:");
 | 
				
			||||||
 | 
						log_err("\twhat: {}", exp.what());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace lt::renderer
 | 
					} // namespace lt::renderer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <bitwise/operations.hpp>
 | 
					 | 
				
			||||||
#include <any>
 | 
					#include <any>
 | 
				
			||||||
 | 
					#include <bitwise/operations.hpp>
 | 
				
			||||||
 | 
					#include <memory/scope.hpp>
 | 
				
			||||||
 | 
					#include <renderer/frontend/messenger.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace lt::renderer {
 | 
					namespace lt::renderer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,18 +38,63 @@ using Callback_T = std::function<void(
 | 
				
			||||||
    MessageSeverity message_severity,
 | 
					    MessageSeverity message_severity,
 | 
				
			||||||
    MessageType message_type,
 | 
					    MessageType message_type,
 | 
				
			||||||
    MessengerCallbackData data,
 | 
					    MessengerCallbackData data,
 | 
				
			||||||
    std::any user_data
 | 
					    std::any &user_data
 | 
				
			||||||
)>;
 | 
					)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct MessengerComponent
 | 
					class MessengerComponent
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	MessageSeverity severities;
 | 
					public:
 | 
				
			||||||
 | 
						friend class System;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MessageType types;
 | 
						struct CreateInfo
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							MessageSeverity severities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Callback_T callback;
 | 
							MessageType types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::any user_data;
 | 
							Callback_T callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::any user_data;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] auto get_severities() const -> MessageSeverity
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return m_severities;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] auto get_types() const -> MessageType
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return m_types;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] auto get_callback() const -> const Callback_T &
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return m_callback;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] auto get_user_data() -> std::any &
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return m_user_data;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						MessengerComponent(CreateInfo info)
 | 
				
			||||||
 | 
						    : m_severities(info.severities)
 | 
				
			||||||
 | 
						    , m_types(info.types)
 | 
				
			||||||
 | 
						    , m_callback(std::move(info.callback))
 | 
				
			||||||
 | 
						    , m_user_data(std::move(info.user_data))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MessageSeverity m_severities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MessageType m_types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Callback_T m_callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::any m_user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memory::Scope<IMessenger> m_implementation;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace lt::renderer
 | 
					} // namespace lt::renderer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
#include <memory/reference.hpp>
 | 
					#include <memory/reference.hpp>
 | 
				
			||||||
#include <memory/scope.hpp>
 | 
					#include <memory/scope.hpp>
 | 
				
			||||||
#include <renderer/api.hpp>
 | 
					#include <renderer/api.hpp>
 | 
				
			||||||
 | 
					#include <renderer/components/messenger.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace lt::renderer {
 | 
					namespace lt::renderer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +47,8 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void tick(app::TickInfo tick) override;
 | 
						void tick(app::TickInfo tick) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void create_messenger_component(ecs::EntityId entity, MessengerComponent::CreateInfo info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
 | 
						[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return m_last_tick_result;
 | 
							return m_last_tick_result;
 | 
				
			||||||
| 
						 | 
					@ -62,8 +65,6 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memory::Scope<class IRenderer> m_renderer;
 | 
						memory::Scope<class IRenderer> m_renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::vector<memory::Scope<class IMessenger>> m_messengers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	app::TickResult m_last_tick_result {};
 | 
						app::TickResult m_last_tick_result {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t m_frame_idx {};
 | 
						uint32_t m_frame_idx {};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,12 +54,6 @@ System::System(memory::Ref<ecs::Registry> registry): m_registry(std::move(regist
 | 
				
			||||||
	    "Failed to initialize surface system: registry has surface component(s)"
 | 
						    "Failed to initialize surface system: registry has surface component(s)"
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m_registry->connect_on_construct<SurfaceComponent>(
 | 
					 | 
				
			||||||
	    [this](ecs::Registry ®istry, ecs::EntityId entity) {
 | 
					 | 
				
			||||||
		    on_surface_construct(registry, entity);
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_registry->connect_on_destruct<SurfaceComponent>(
 | 
						m_registry->connect_on_destruct<SurfaceComponent>(
 | 
				
			||||||
	    [this](ecs::Registry ®istry, ecs::EntityId entity) {
 | 
						    [this](ecs::Registry ®istry, ecs::EntityId entity) {
 | 
				
			||||||
		    on_surface_destruct(registry, entity);
 | 
							    on_surface_destruct(registry, entity);
 | 
				
			||||||
| 
						 | 
					@ -106,97 +100,99 @@ void System::on_unregister()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void System::on_surface_construct(ecs::Registry ®istry, ecs::EntityId entity)
 | 
					auto System::create_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info)
 | 
				
			||||||
 | 
					    -> std::optional<SurfaceComponent *>
 | 
				
			||||||
 | 
					try
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	try
 | 
						auto &component = m_registry->add<SurfaceComponent>(entity, info);
 | 
				
			||||||
 | 
						auto &surface = m_registry->get<SurfaceComponent>(entity);
 | 
				
			||||||
 | 
						const auto &resolution = surface.get_resolution();
 | 
				
			||||||
 | 
						const auto &position = surface.get_position();
 | 
				
			||||||
 | 
						ensure_component_sanity(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO(Light): refactor "environment" into standalone module
 | 
				
			||||||
 | 
						// NOLINTNEXTLINE(concurrency-mt-unsafe)
 | 
				
			||||||
 | 
						auto *display_env = std::getenv("DISPLAY");
 | 
				
			||||||
 | 
						ensure(display_env != nullptr, "DISPLAY env var not found!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto *display = XOpenDisplay(display_env);
 | 
				
			||||||
 | 
						ensure(display, "Failed to open XDisplay with DISPLAY: {}", display_env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto root_window = XDefaultRootWindow(display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto border_width = 0;
 | 
				
			||||||
 | 
						auto depth = int32_t { CopyFromParent };
 | 
				
			||||||
 | 
						auto window_class = CopyFromParent;
 | 
				
			||||||
 | 
						auto *visual = (Visual *)CopyFromParent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto attribute_value_mask = CWBackPixel | CWEventMask;
 | 
				
			||||||
 | 
						auto attributes = XSetWindowAttributes {
 | 
				
			||||||
 | 
							.background_pixel = 0xffafe9af,
 | 
				
			||||||
 | 
							.event_mask = all_events_mask,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef struct Hints
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto &surface = registry.get<SurfaceComponent>(entity);
 | 
							unsigned long flags;
 | 
				
			||||||
		const auto &resolution = surface.get_resolution();
 | 
							unsigned long functions;
 | 
				
			||||||
		const auto &position = surface.get_position();
 | 
							unsigned long decorations;
 | 
				
			||||||
		ensure_component_sanity(surface);
 | 
							long inputMode;
 | 
				
			||||||
 | 
							unsigned long status;
 | 
				
			||||||
 | 
						} Hints;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// TODO(Light): refactor "environment" into standalone module
 | 
						auto main_window = XCreateWindow(
 | 
				
			||||||
		// NOLINTNEXTLINE(concurrency-mt-unsafe)
 | 
						    display,
 | 
				
			||||||
		auto *display_env = std::getenv("DISPLAY");
 | 
						    root_window,
 | 
				
			||||||
		ensure(display_env != nullptr, "DISPLAY env var not found!");
 | 
						    position.x,
 | 
				
			||||||
 | 
						    position.y,
 | 
				
			||||||
 | 
						    resolution.x,
 | 
				
			||||||
 | 
						    resolution.y,
 | 
				
			||||||
 | 
						    border_width,
 | 
				
			||||||
 | 
						    depth,
 | 
				
			||||||
 | 
						    window_class,
 | 
				
			||||||
 | 
						    visual,
 | 
				
			||||||
 | 
						    attribute_value_mask,
 | 
				
			||||||
 | 
						    &attributes
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						surface.m_native_data.display = display;
 | 
				
			||||||
 | 
						surface.m_native_data.window = main_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto *display = XOpenDisplay(display_env);
 | 
						surface.m_native_data.wm_delete_message = XInternAtom(display, "WM_DELETE_WINDOW", False);
 | 
				
			||||||
		ensure(display, "Failed to open XDisplay with DISPLAY: {}", display_env);
 | 
						XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto root_window = XDefaultRootWindow(display);
 | 
						// code to remove decoration
 | 
				
			||||||
 | 
						auto hints = std::array<unsigned char, 5> { 2, 0, 0, 0, 0 };
 | 
				
			||||||
 | 
						const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto border_width = 0;
 | 
						XChangeProperty(
 | 
				
			||||||
		auto depth = int32_t { CopyFromParent };
 | 
						    display,
 | 
				
			||||||
		auto window_class = CopyFromParent;
 | 
						    surface.m_native_data.window,
 | 
				
			||||||
		auto *visual = (Visual *)CopyFromParent;
 | 
						    motif_hints,
 | 
				
			||||||
 | 
						    motif_hints,
 | 
				
			||||||
 | 
						    32,
 | 
				
			||||||
 | 
						    PropModeReplace,
 | 
				
			||||||
 | 
						    hints.data(),
 | 
				
			||||||
 | 
						    5
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto attribute_value_mask = CWBackPixel | CWEventMask;
 | 
						XMapWindow(display, main_window);
 | 
				
			||||||
		auto attributes = XSetWindowAttributes {
 | 
						XStoreName(display, main_window, surface.m_title.c_str());
 | 
				
			||||||
			.background_pixel = 0xffafe9af,
 | 
						XFlush(display);
 | 
				
			||||||
			.event_mask = all_events_mask,
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		typedef struct Hints
 | 
						if (!surface.is_visible())
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			unsigned long flags;
 | 
					 | 
				
			||||||
			unsigned long functions;
 | 
					 | 
				
			||||||
			unsigned long decorations;
 | 
					 | 
				
			||||||
			long inputMode;
 | 
					 | 
				
			||||||
			unsigned long status;
 | 
					 | 
				
			||||||
		} Hints;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		auto main_window = XCreateWindow(
 | 
					 | 
				
			||||||
		    display,
 | 
					 | 
				
			||||||
		    root_window,
 | 
					 | 
				
			||||||
		    position.x,
 | 
					 | 
				
			||||||
		    position.y,
 | 
					 | 
				
			||||||
		    resolution.x,
 | 
					 | 
				
			||||||
		    resolution.y,
 | 
					 | 
				
			||||||
		    border_width,
 | 
					 | 
				
			||||||
		    depth,
 | 
					 | 
				
			||||||
		    window_class,
 | 
					 | 
				
			||||||
		    visual,
 | 
					 | 
				
			||||||
		    attribute_value_mask,
 | 
					 | 
				
			||||||
		    &attributes
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
		surface.m_native_data.display = display;
 | 
					 | 
				
			||||||
		surface.m_native_data.window = main_window;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		surface.m_native_data.wm_delete_message = XInternAtom(display, "WM_DELETE_WINDOW", False);
 | 
					 | 
				
			||||||
		XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// code to remove decoration
 | 
					 | 
				
			||||||
		auto hints = std::array<unsigned char, 5> { 2, 0, 0, 0, 0 };
 | 
					 | 
				
			||||||
		const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		XChangeProperty(
 | 
					 | 
				
			||||||
		    display,
 | 
					 | 
				
			||||||
		    surface.m_native_data.window,
 | 
					 | 
				
			||||||
		    motif_hints,
 | 
					 | 
				
			||||||
		    motif_hints,
 | 
					 | 
				
			||||||
		    32,
 | 
					 | 
				
			||||||
		    PropModeReplace,
 | 
					 | 
				
			||||||
		    hints.data(),
 | 
					 | 
				
			||||||
		    5
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		XMapWindow(display, main_window);
 | 
					 | 
				
			||||||
		XStoreName(display, main_window, surface.m_title.c_str());
 | 
					 | 
				
			||||||
		XFlush(display);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!surface.is_visible())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			XUnmapWindow(display, main_window);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	catch (const std::exception &exp)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		log_err("Exception thrown when on_constructing surface component");
 | 
							XUnmapWindow(display, main_window);
 | 
				
			||||||
		log_err("\tentity: {}", entity);
 | 
					 | 
				
			||||||
		log_err("\twhat: {}", exp.what());
 | 
					 | 
				
			||||||
		registry.remove<SurfaceComponent>(entity);
 | 
					 | 
				
			||||||
		throw;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &component;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					catch (const std::exception &exp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						log_err("Exception thrown when on_constructing surface component");
 | 
				
			||||||
 | 
						log_err("\tentity: {}", entity);
 | 
				
			||||||
 | 
						log_err("\twhat: {}", exp.what());
 | 
				
			||||||
 | 
						m_registry->remove<SurfaceComponent>(entity);
 | 
				
			||||||
 | 
						return {};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void System::on_surface_destruct(ecs::Registry ®istry, ecs::EntityId entity)
 | 
					void System::on_surface_destruct(ecs::Registry ®istry, ecs::EntityId entity)
 | 
				
			||||||
| 
						 | 
					@ -285,7 +281,6 @@ void System::handle_events(SurfaceComponent &surface)
 | 
				
			||||||
			const auto new_height = event.xconfigure.height;
 | 
								const auto new_height = event.xconfigure.height;
 | 
				
			||||||
			if (prev_width != new_width || prev_height != new_height)
 | 
								if (prev_width != new_width || prev_height != new_height)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_dbg("resized: {} - {}", new_width, new_height);
 | 
					 | 
				
			||||||
				surface.m_resolution.x = new_width;
 | 
									surface.m_resolution.x = new_width;
 | 
				
			||||||
				surface.m_resolution.y = new_height;
 | 
									surface.m_resolution.y = new_height;
 | 
				
			||||||
				queue.emplace_back<ResizedEvent>(ResizedEvent {
 | 
									queue.emplace_back<ResizedEvent>(ResizedEvent {
 | 
				
			||||||
| 
						 | 
					@ -342,7 +337,7 @@ void System::modify_title(SurfaceComponent &surface, const ModifyTitleRequest &r
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void System::modify_resolution(SurfaceComponent &surface, const ModifyResolutionRequest &request)
 | 
					void System::modify_resolution(SurfaceComponent &surface, const ModifyResolutionRequest &request)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	surface.m_resolution = request.resolution;
 | 
						// surface.m_resolution = request.resolution;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto &[display, window, _] = surface.m_native_data;
 | 
						auto &[display, window, _] = surface.m_native_data;
 | 
				
			||||||
	const auto &[width, height] = request.resolution;
 | 
						const auto &[width, height] = request.resolution;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,10 @@ typedef struct _XDisplay Display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace lt::surface {
 | 
					namespace lt::surface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Represents a platform's surface (eg. a Window). */
 | 
					/** Represents a platform's surface (eg. a Window).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note This is a "system component"
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class SurfaceComponent
 | 
					class SurfaceComponent
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					@ -66,15 +69,6 @@ public:
 | 
				
			||||||
		bool visible;
 | 
							bool visible;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SurfaceComponent(const CreateInfo &info)
 | 
					 | 
				
			||||||
	    : m_title(info.title)
 | 
					 | 
				
			||||||
	    , m_resolution(info.resolution)
 | 
					 | 
				
			||||||
	    , m_vsync(info.vsync)
 | 
					 | 
				
			||||||
	    , m_visible(info.visible)
 | 
					 | 
				
			||||||
	    , m_native_data({})
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[[nodiscard]] auto get_title() const -> std::string_view
 | 
						[[nodiscard]] auto get_title() const -> std::string_view
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return m_title;
 | 
							return m_title;
 | 
				
			||||||
| 
						 | 
					@ -127,6 +121,15 @@ public:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
						SurfaceComponent(const CreateInfo &info)
 | 
				
			||||||
 | 
						    : m_title(info.title)
 | 
				
			||||||
 | 
						    , m_resolution(info.resolution)
 | 
				
			||||||
 | 
						    , m_vsync(info.vsync)
 | 
				
			||||||
 | 
						    , m_visible(info.visible)
 | 
				
			||||||
 | 
						    , m_native_data({})
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::string m_title;
 | 
						std::string m_title;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	math::uvec2 m_resolution;
 | 
						math::uvec2 m_resolution;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include <ecs/registry.hpp>
 | 
					#include <ecs/registry.hpp>
 | 
				
			||||||
#include <math/vec2.hpp>
 | 
					#include <math/vec2.hpp>
 | 
				
			||||||
#include <memory/reference.hpp>
 | 
					#include <memory/reference.hpp>
 | 
				
			||||||
 | 
					#include <surface/components.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace lt::surface {
 | 
					namespace lt::surface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +27,9 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void on_unregister() override;
 | 
						void on_unregister() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto create_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info)
 | 
				
			||||||
 | 
						    -> std::optional<SurfaceComponent *>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void tick(app::TickInfo tick) override;
 | 
						void tick(app::TickInfo tick) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
 | 
						[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
 | 
				
			||||||
| 
						 | 
					@ -34,8 +38,6 @@ public:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void on_surface_construct(ecs::Registry ®istry, ecs::EntityId entity);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void on_surface_destruct(ecs::Registry ®istry, ecs::EntityId entity);
 | 
						void on_surface_destruct(ecs::Registry ®istry, ecs::EntityId entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void handle_requests(struct SurfaceComponent &surface);
 | 
						void handle_requests(struct SurfaceComponent &surface);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue