Compare commits
	
		
			23 commits
		
	
	
		
			320cc66267
			...
			4941b68eab
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4941b68eab | |||
| d448726350 | |||
| 8741a769a6 | |||
| e695808f98 | |||
| 1158da1a39 | |||
| 0b03dda72f | |||
| a08b5689dd | |||
| 2358dc6824 | |||
| 061ebaddb5 | |||
| de23d7a319 | |||
| 249cecdb50 | |||
| 794b52c10b | |||
| cd7fb754d2 | |||
| cd7274cbd5 | |||
| 92b9c49f44 | |||
| 0993adf0f0 | |||
| 3a713b6af7 | |||
| 3c1193eedc | |||
| 3020f17507 | |||
| bb6485488c | |||
| 9e6300f1aa | |||
| d69315c6aa | |||
| 21e9933a42 | 
					 78 changed files with 1802 additions and 4864 deletions
				
			
		| 
						 | 
				
			
			@ -40,4 +40,3 @@ if(ENABLE_LLVM_COVERAGE)
 | 
			
		|||
endif ()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/modules)
 | 
			
		||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/glad)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ add_subdirectory(./asset_parser)
 | 
			
		|||
# add_subdirectory(./asset_manager)
 | 
			
		||||
# 
 | 
			
		||||
add_subdirectory(./camera)
 | 
			
		||||
# add_subdirectory(./input)
 | 
			
		||||
add_subdirectory(./input)
 | 
			
		||||
# add_subdirectory(./ui)
 | 
			
		||||
# 
 | 
			
		||||
add_subdirectory(./surface)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
add_library_module(ecs entity.cpp scene.cpp uuid.cpp )
 | 
			
		||||
target_link_libraries(ecs 
 | 
			
		||||
    PUBLIC logger lt_debug EnTT::EnTT  input camera math
 | 
			
		||||
    PUBLIC logger lt_debug EnTT::EnTT camera math
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,4 @@
 | 
			
		|||
add_library_module(input input.cpp)
 | 
			
		||||
target_link_libraries(input PUBLIC surface math imgui::imgui logger)
 | 
			
		||||
add_library_module(input system.cpp)
 | 
			
		||||
target_link_libraries(input PUBLIC surface math  logger)
 | 
			
		||||
 | 
			
		||||
add_test_module(input system.test.cpp)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,159 +0,0 @@
 | 
			
		|||
#include <imgui.h>
 | 
			
		||||
#include <input/input.hpp>
 | 
			
		||||
#include <logger/logger.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
Input::Input(): m_mouse_position {}, m_mouse_delta {}
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
	restart_input_state();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::receive_user_interface_events_impl(bool receive, bool toggle /* = false */)
 | 
			
		||||
{
 | 
			
		||||
	m_user_interface_events = toggle ? !m_user_interface_events : receive;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::receieve_game_events_impl(bool receive, bool toggle /*= false*/)
 | 
			
		||||
{
 | 
			
		||||
	auto prev = m_game_events;
 | 
			
		||||
	m_game_events = toggle ? !m_user_interface_events : receive;
 | 
			
		||||
 | 
			
		||||
	if (m_game_events != prev)
 | 
			
		||||
	{
 | 
			
		||||
		restart_input_state();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::restart_input_state()
 | 
			
		||||
{
 | 
			
		||||
	m_keyboad_keys.fill(false);
 | 
			
		||||
	m_mouse_buttons.fill(false);
 | 
			
		||||
 | 
			
		||||
	m_mouse_position = math::vec2(0.0f);
 | 
			
		||||
	m_mouse_delta = math::vec2(0.0f);
 | 
			
		||||
	m_mouse_wheel_delta = 0.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::on_event(const Event &inputEvent)
 | 
			
		||||
{
 | 
			
		||||
	auto &io = ImGui::GetIO();
 | 
			
		||||
	switch (inputEvent.get_event_type())
 | 
			
		||||
	{
 | 
			
		||||
		//** MOUSE_EVENTS **//
 | 
			
		||||
	case EventType::MouseMoved:
 | 
			
		||||
	{
 | 
			
		||||
		const auto &event = dynamic_cast<const MouseMovedEvent &>(inputEvent);
 | 
			
		||||
 | 
			
		||||
		if (m_game_events)
 | 
			
		||||
		{
 | 
			
		||||
			m_mouse_delta = event.get_position() - m_mouse_position;
 | 
			
		||||
			m_mouse_position = event.get_position();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			io.MousePos = ImVec2(event.get_x(), event.get_y());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	case EventType::ButtonPressed:
 | 
			
		||||
	{
 | 
			
		||||
		const auto &event = dynamic_cast<const ButtonPressedEvent &>(inputEvent);
 | 
			
		||||
 | 
			
		||||
		if (m_game_events)
 | 
			
		||||
		{
 | 
			
		||||
			m_mouse_buttons[event.get_button()] = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			io.MouseDown[event.get_button()] = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	case EventType::ButtonReleased:
 | 
			
		||||
	{
 | 
			
		||||
		const auto &event = dynamic_cast<const ButtonReleasedEvent &>(inputEvent);
 | 
			
		||||
 | 
			
		||||
		if (m_game_events)
 | 
			
		||||
		{
 | 
			
		||||
			m_mouse_buttons[event.get_button()] = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			io.MouseDown[event.get_button()] = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	case EventType::WheelScrolled:
 | 
			
		||||
	{
 | 
			
		||||
		const auto &event = dynamic_cast<const WheelScrolledEvent &>(inputEvent);
 | 
			
		||||
 | 
			
		||||
		if (m_game_events)
 | 
			
		||||
		{
 | 
			
		||||
			m_mouse_wheel_delta = event.get_offset();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			io.MouseWheel = event.get_offset();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	//** KEYBOARD_EVENTS **//
 | 
			
		||||
	case EventType::KeyPressed:
 | 
			
		||||
	{
 | 
			
		||||
		const auto &event = dynamic_cast<const KeyPressedEvent &>(inputEvent);
 | 
			
		||||
 | 
			
		||||
		if (m_game_events)
 | 
			
		||||
		{
 | 
			
		||||
			m_keyboad_keys[event.get_key()] = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			// io.AddKeyEvent(event.get_key(), true);
 | 
			
		||||
			// if (event.get_key() == Key::BackSpace)
 | 
			
		||||
			//	io.AddInputCharacter(Key::BackSpace);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	case EventType::KeyReleased:
 | 
			
		||||
	{
 | 
			
		||||
		const auto &event = dynamic_cast<const KeyReleasedEvent &>(inputEvent);
 | 
			
		||||
 | 
			
		||||
		if (m_game_events)
 | 
			
		||||
		{
 | 
			
		||||
			m_keyboad_keys[event.get_key()] = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			// io.AddKeyEvent(event.get_key(), false);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	case EventType::SetChar:
 | 
			
		||||
	{
 | 
			
		||||
		if (m_user_interface_events)
 | 
			
		||||
		{
 | 
			
		||||
			const auto &event = dynamic_cast<const SetCharEvent &>(inputEvent);
 | 
			
		||||
			io.AddInputCharacter(event.get_character());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	default: log_trc("Dropped event");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,138 @@
 | 
			
		|||
#include <input/components.hpp>
 | 
			
		||||
#include <input/system.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt::input {
 | 
			
		||||
 | 
			
		||||
template<class... Ts>
 | 
			
		||||
struct overloads: Ts...
 | 
			
		||||
{
 | 
			
		||||
	using Ts::operator()...;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
System::System(Ref<ecs::Registry> registry): m_registry(std::move(registry))
 | 
			
		||||
{
 | 
			
		||||
	ensure(m_registry, "Failed to initialize input system: null registry");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto System::tick() -> bool
 | 
			
		||||
{
 | 
			
		||||
	m_registry->view<surface::SurfaceComponent>().each([&](const entt::entity,
 | 
			
		||||
	                                                       surface::SurfaceComponent &surface) {
 | 
			
		||||
		for (const auto &event : surface.peek_events())
 | 
			
		||||
		{
 | 
			
		||||
			handle_event(event);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	m_registry->view<InputComponent>().each([&](const entt::entity, InputComponent &input) {
 | 
			
		||||
		// TODO(Light): instead of iterating over all actions each frame,
 | 
			
		||||
		// make a list of "dirty" actions to reset
 | 
			
		||||
		// and a surface_input->input_action mapping to get to action through input
 | 
			
		||||
		// instead of brute-force checking all of them.
 | 
			
		||||
		for (auto &action : input.m_actions)
 | 
			
		||||
		{
 | 
			
		||||
			auto code = action.trigger.mapped_keycode;
 | 
			
		||||
			if (code < m_keys.size() && m_keys[code])
 | 
			
		||||
			{
 | 
			
		||||
				if (action.state == InputAction::State::triggered)
 | 
			
		||||
				{
 | 
			
		||||
					action.state = InputAction::State::active;
 | 
			
		||||
				}
 | 
			
		||||
				else if (action.state == InputAction::State::inactive)
 | 
			
		||||
				{
 | 
			
		||||
					action.state = InputAction::State::triggered;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				action.state = InputAction::State::inactive;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_register()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_unregister()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::handle_event(const surface::SurfaceComponent::Event &event)
 | 
			
		||||
{
 | 
			
		||||
	const auto visitor = overloads {
 | 
			
		||||
		[this](const surface::ClosedEvent &) { on_surface_lost_focus(); },
 | 
			
		||||
		[this](const surface::LostFocusEvent &) { on_surface_lost_focus(); },
 | 
			
		||||
		[this](const surface::KeyPressedEvent &event) { on_key_press(event); },
 | 
			
		||||
		[this](const surface::KeyReleasedEvent &event) { on_key_release(event); },
 | 
			
		||||
		[this](const surface::MouseMovedEvent &event) { on_pointer_move(event); },
 | 
			
		||||
		[this](const surface::ButtonPressedEvent &event) { on_button_press(event); },
 | 
			
		||||
		[this](const surface::ButtonReleasedEvent &event) { on_button_release(event); },
 | 
			
		||||
		[this](auto) {},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	std::visit(visitor, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_surface_lost_focus()
 | 
			
		||||
{
 | 
			
		||||
	for (auto &key : m_keys)
 | 
			
		||||
	{
 | 
			
		||||
		key = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto &button : m_buttons)
 | 
			
		||||
	{
 | 
			
		||||
		button = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_key_press(const lt::surface::KeyPressedEvent &event)
 | 
			
		||||
{
 | 
			
		||||
	if (event.get_key() > m_keys.size())
 | 
			
		||||
	{
 | 
			
		||||
		log_dbg(
 | 
			
		||||
		    "Key code larger than key container size, implement platform-dependant "
 | 
			
		||||
		    "key-code-mapping!"
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_keys[event.get_key()] = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_key_release(const lt::surface::KeyReleasedEvent &event)
 | 
			
		||||
{
 | 
			
		||||
	if (event.get_key() > m_keys.size())
 | 
			
		||||
	{
 | 
			
		||||
		log_dbg(
 | 
			
		||||
		    "Key code larger than key container size, implement platform-dependant "
 | 
			
		||||
		    "key-code-mapping!"
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_keys[event.get_key()] = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_pointer_move(const lt::surface::MouseMovedEvent &event)
 | 
			
		||||
{
 | 
			
		||||
	m_pointer_position = event.get_position();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_button_press(const lt::surface::ButtonPressedEvent &event)
 | 
			
		||||
{
 | 
			
		||||
	m_buttons[event.get_button()] = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_button_release(const lt::surface::ButtonReleasedEvent &event)
 | 
			
		||||
{
 | 
			
		||||
	m_buttons[event.get_button()] = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace lt::input
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										169
									
								
								modules/input/private/system.test.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								modules/input/private/system.test.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,169 @@
 | 
			
		|||
#include <ecs/entity.hpp>
 | 
			
		||||
#include <input/components.hpp>
 | 
			
		||||
#include <input/system.hpp>
 | 
			
		||||
#include <test/test.hpp>
 | 
			
		||||
 | 
			
		||||
// NOLINTBEGIN
 | 
			
		||||
using namespace lt;
 | 
			
		||||
using input::InputComponent;
 | 
			
		||||
using input::System;
 | 
			
		||||
using std::ignore;
 | 
			
		||||
using test::Case;
 | 
			
		||||
using test::expect_eq;
 | 
			
		||||
using test::expect_false;
 | 
			
		||||
using test::expect_ne;
 | 
			
		||||
using test::expect_not_nullptr;
 | 
			
		||||
using test::expect_throw;
 | 
			
		||||
using test::Suite;
 | 
			
		||||
// NOLINTEND
 | 
			
		||||
 | 
			
		||||
class Fixture
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	[[nodiscard]] auto registry() -> Ref<ecs::Registry>
 | 
			
		||||
	{
 | 
			
		||||
		return m_registry;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto add_input_component() -> ecs::Entity
 | 
			
		||||
	{
 | 
			
		||||
		auto entity = m_registry->create_entity("");
 | 
			
		||||
		entity.add_component<InputComponent>();
 | 
			
		||||
 | 
			
		||||
		return entity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto add_surface_component() -> ecs::Entity
 | 
			
		||||
	{
 | 
			
		||||
		auto entity = m_registry->create_entity("");
 | 
			
		||||
		entity.add_component<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {});
 | 
			
		||||
 | 
			
		||||
		return entity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Ref<ecs::Registry> m_registry = create_ref<ecs::Registry>();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Suite raii = [] {
 | 
			
		||||
	Case { "happy path won't throw" } = [&] {
 | 
			
		||||
		System { Fixture {}.registry() };
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "many won't freeze/throw" } = [&] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		for (auto idx : std::views::iota(0, 10'000))
 | 
			
		||||
		{
 | 
			
		||||
			ignore = System { fixture.registry() };
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "unhappy path throws" } = [] {
 | 
			
		||||
		expect_throw([] { ignore = System { {} }; });
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Suite system_events = [] {
 | 
			
		||||
	Case { "on_register won't throw" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
 | 
			
		||||
		system.on_register();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 0);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "on_unregister won't throw" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
 | 
			
		||||
		system.on_register();
 | 
			
		||||
		system.on_unregister();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 0);
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Suite registry_events = [] {
 | 
			
		||||
	Case { "on_construct<InputComnent>" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
 | 
			
		||||
		const auto &entity = fixture.add_input_component();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 1);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "on_destrroy<InputComponent>" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = create_scope<System>(fixture.registry());
 | 
			
		||||
 | 
			
		||||
		auto entity_a = fixture.add_input_component();
 | 
			
		||||
		auto entity_b = fixture.add_input_component();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 2);
 | 
			
		||||
 | 
			
		||||
		entity_a.remove_component<InputComponent>();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 1);
 | 
			
		||||
 | 
			
		||||
		system.reset();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 1);
 | 
			
		||||
 | 
			
		||||
		entity_b.remove_component<InputComponent>();
 | 
			
		||||
		expect_eq(fixture.registry()->view<InputComponent>().size(), 0);
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Suite tick = [] {
 | 
			
		||||
	Case { "Empty tick won't throw" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
 | 
			
		||||
		expect_false(system.tick());
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "Tick triggers input action" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
 | 
			
		||||
		auto &surface = fixture.add_surface_component().get_component<surface::SurfaceComponent>();
 | 
			
		||||
		auto &input = fixture.add_input_component().get_component<InputComponent>();
 | 
			
		||||
 | 
			
		||||
		auto action_key = input.add_action(
 | 
			
		||||
		    {
 | 
			
		||||
		        .name { "test" },
 | 
			
		||||
		        .trigger = { .mapped_keycode = 69 },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
 | 
			
		||||
 | 
			
		||||
		surface.push_event(surface::KeyPressedEvent(69));
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(input.get_action(action_key).state, input::InputAction::State::triggered);
 | 
			
		||||
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
 | 
			
		||||
 | 
			
		||||
		system.tick();
 | 
			
		||||
		system.tick();
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
 | 
			
		||||
 | 
			
		||||
		surface.push_event(surface::KeyPressedEvent(69));
 | 
			
		||||
		system.tick();
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "Tick triggers" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
 | 
			
		||||
		auto &surface = fixture.add_surface_component().get_component<surface::SurfaceComponent>();
 | 
			
		||||
		auto &input = fixture.add_input_component().get_component<InputComponent>();
 | 
			
		||||
 | 
			
		||||
		auto action_key = input.add_action(
 | 
			
		||||
		    {
 | 
			
		||||
		        .name { "test" },
 | 
			
		||||
		        .trigger = { .mapped_keycode = 69 },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										57
									
								
								modules/input/public/components.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								modules/input/public/components.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace lt::input {
 | 
			
		||||
 | 
			
		||||
struct Trigger
 | 
			
		||||
{
 | 
			
		||||
	uint32_t mapped_keycode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct InputAction
 | 
			
		||||
{
 | 
			
		||||
	using Key = size_t;
 | 
			
		||||
 | 
			
		||||
	enum class State : uint8_t
 | 
			
		||||
	{
 | 
			
		||||
		inactive,
 | 
			
		||||
		active,
 | 
			
		||||
		triggered,
 | 
			
		||||
		cancelled,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	std::string name;
 | 
			
		||||
 | 
			
		||||
	State state;
 | 
			
		||||
 | 
			
		||||
	Trigger trigger;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class InputComponent
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	InputComponent() = default;
 | 
			
		||||
 | 
			
		||||
	auto add_action(InputAction action) -> size_t
 | 
			
		||||
	{
 | 
			
		||||
		m_actions.emplace_back(std::move(action));
 | 
			
		||||
		return m_actions.size() - 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto get_action(auto idx) -> const InputAction &
 | 
			
		||||
	{
 | 
			
		||||
		return m_actions[idx];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	friend class System;
 | 
			
		||||
 | 
			
		||||
	void push_event()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::vector<InputAction> m_actions;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt::input
 | 
			
		||||
							
								
								
									
										44
									
								
								modules/input/public/events.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								modules/input/public/events.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <math/vec2.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt::input {
 | 
			
		||||
 | 
			
		||||
class AnalogEvent
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	AnalogEvent(uint32_t input_code, math::uvec2 pointer_position)
 | 
			
		||||
	    : m_input_code(input_code)
 | 
			
		||||
	    , m_pointer_position(pointer_position)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_code() const -> uint32_t
 | 
			
		||||
	{
 | 
			
		||||
		return m_input_code;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_pointer_position() const -> math::uvec2
 | 
			
		||||
	{
 | 
			
		||||
		return m_pointer_position;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto to_string() const -> std::string
 | 
			
		||||
	{
 | 
			
		||||
		auto stream = std::stringstream {};
 | 
			
		||||
		const auto &[x, y] = m_pointer_position;
 | 
			
		||||
		stream << "input::AnalogEvent: " << m_input_code << " @ " << x << ", " << y;
 | 
			
		||||
		return stream.str();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	uint32_t m_input_code;
 | 
			
		||||
 | 
			
		||||
	math::uvec2 m_pointer_position;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class AxisEvent
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt::input
 | 
			
		||||
| 
						 | 
				
			
			@ -1,80 +0,0 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <math/vec2.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class Event;
 | 
			
		||||
 | 
			
		||||
class Input
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static auto instance() -> Input &
 | 
			
		||||
	{
 | 
			
		||||
		static auto instance = Input {};
 | 
			
		||||
		return instance;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void receive_user_interface_events(bool receive, bool toggle = false)
 | 
			
		||||
	{
 | 
			
		||||
		instance().receive_user_interface_events_impl(receive, toggle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void receive_game_events(bool receive, bool toggle = false)
 | 
			
		||||
	{
 | 
			
		||||
		instance().receieve_game_events_impl(receive, toggle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static auto get_keyboard_key(int code) -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return instance().m_keyboad_keys[code];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static auto get_mouse_button(int code) -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return instance().m_mouse_buttons[code];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static auto get_mouse_position(int /*code*/) -> const math::vec2 &
 | 
			
		||||
	{
 | 
			
		||||
		return instance().m_mouse_position;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void on_event(const Event &inputEvent);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto is_receiving_input_events() const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return m_user_interface_events;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto is_receiving_game_events() const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return m_game_events;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Input();
 | 
			
		||||
 | 
			
		||||
	void receive_user_interface_events_impl(bool receive, bool toggle = false);
 | 
			
		||||
 | 
			
		||||
	void receieve_game_events_impl(bool receive, bool toggle = false);
 | 
			
		||||
 | 
			
		||||
	void restart_input_state();
 | 
			
		||||
 | 
			
		||||
	std::array<bool, 348> m_keyboad_keys {};
 | 
			
		||||
 | 
			
		||||
	std::array<bool, 8> m_mouse_buttons {};
 | 
			
		||||
 | 
			
		||||
	math::vec2 m_mouse_position;
 | 
			
		||||
 | 
			
		||||
	math::vec2 m_mouse_delta;
 | 
			
		||||
 | 
			
		||||
	float m_mouse_wheel_delta {};
 | 
			
		||||
 | 
			
		||||
	bool m_user_interface_events { true };
 | 
			
		||||
 | 
			
		||||
	bool m_game_events { true };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			@ -1,63 +1,46 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <surface/system.hpp>
 | 
			
		||||
#include <app/system.hpp>
 | 
			
		||||
#include <ecs/scene.hpp>
 | 
			
		||||
#include <surface/components.hpp>
 | 
			
		||||
#include <surface/events/keyboard.hpp>
 | 
			
		||||
#include <surface/events/mouse.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt::input {
 | 
			
		||||
 | 
			
		||||
template<class... Ts>
 | 
			
		||||
struct overloads: Ts...
 | 
			
		||||
{
 | 
			
		||||
	using Ts::operator()...;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 * @note If this system is attached, it will always consume the input events f rom surface.
 | 
			
		||||
 * Therefore if you want any input detection mechanism, callbacks should be setup with this
 | 
			
		||||
 * system and not directly with surface.
 | 
			
		||||
 */
 | 
			
		||||
class System
 | 
			
		||||
class System: public app::ISystem
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	System(lt::surface::System &surface_system)
 | 
			
		||||
	{
 | 
			
		||||
		surface_system.add_event_listener([this](auto &&event) {
 | 
			
		||||
			return handle_event(std::forward<decltype(event)>(event));
 | 
			
		||||
		});
 | 
			
		||||
	};
 | 
			
		||||
	System(Ref<ecs::Registry> registry);
 | 
			
		||||
 | 
			
		||||
	auto tick() -> bool override;
 | 
			
		||||
 | 
			
		||||
	void on_register() override;
 | 
			
		||||
 | 
			
		||||
	void on_unregister() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	auto handle_event(const lt::surface::System::Event &event) -> bool
 | 
			
		||||
	{
 | 
			
		||||
		const auto visitor = overloads {
 | 
			
		||||
			[this](const lt::surface::KeyPressedEvent &event) {
 | 
			
		||||
			    m_keys[event.get_key()] = true;
 | 
			
		||||
			    return true;
 | 
			
		||||
			},
 | 
			
		||||
	void handle_event(const surface::SurfaceComponent::Event &event);
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::KeyRepeatEvent &) { return false; },
 | 
			
		||||
	void on_surface_lost_focus();
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::KeyReleasedEvent &) { return false; },
 | 
			
		||||
	void on_key_press(const lt::surface::KeyPressedEvent &event);
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::KeySetCharEvent &) { return false; },
 | 
			
		||||
	void on_key_release(const lt::surface::KeyReleasedEvent &event);
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::MouseMovedEvent &) { return false; },
 | 
			
		||||
	void on_pointer_move(const lt::surface::MouseMovedEvent &event);
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::WheelScrolledEvent &) { return false; },
 | 
			
		||||
	void on_button_press(const lt::surface::ButtonPressedEvent &event);
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::ButtonPressedEvent &) { return false; },
 | 
			
		||||
	void on_button_release(const lt::surface::ButtonReleasedEvent &event);
 | 
			
		||||
 | 
			
		||||
			[](const lt::surface::ButtonReleasedEvent &) { return false; },
 | 
			
		||||
 | 
			
		||||
			[](const auto &) { return false; },
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		return std::visit(visitor, event);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setup_callbacks(GLFWwindow *handle);
 | 
			
		||||
	Ref<ecs::Registry> m_registry;
 | 
			
		||||
 | 
			
		||||
	std::array<bool, 512> m_keys {};
 | 
			
		||||
 | 
			
		||||
	std::array<bool, 512> m_buttons {};
 | 
			
		||||
 | 
			
		||||
	math::vec2 m_pointer_position;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ template<typename T = float>
 | 
			
		|||
struct mat4_impl
 | 
			
		||||
{
 | 
			
		||||
	using Column_T = vec4_impl<T>;
 | 
			
		||||
	explicit mat4_impl(T scalar = 0)
 | 
			
		||||
	constexpr explicit mat4_impl(T scalar = 0)
 | 
			
		||||
	    : values(
 | 
			
		||||
	          {
 | 
			
		||||
	              Column_T { scalar },
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ struct mat4_impl
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// clang-format off
 | 
			
		||||
    mat4_impl(
 | 
			
		||||
    constexpr mat4_impl(
 | 
			
		||||
        const T&  x0, const T&  y0, const T&  z0, const T&  w0,
 | 
			
		||||
        const T&  x1, const T&  y1, const T&  z1, const T&  w1,
 | 
			
		||||
        const T&  x2, const T&  y2, const T&  z2, const T&  w2,
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ struct mat4_impl
 | 
			
		|||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mat4_impl(
 | 
			
		||||
	constexpr mat4_impl(
 | 
			
		||||
	    const Column_T &column_x,
 | 
			
		||||
	    const Column_T &column_y,
 | 
			
		||||
	    const Column_T &column_z,
 | 
			
		||||
| 
						 | 
				
			
			@ -53,22 +53,22 @@ struct mat4_impl
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator[](size_t idx) -> Column_T &
 | 
			
		||||
	[[nodiscard]] constexpr auto operator[](size_t idx) -> Column_T &
 | 
			
		||||
	{
 | 
			
		||||
		return values[idx];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator[](size_t idx) const -> const Column_T &
 | 
			
		||||
	[[nodiscard]] constexpr auto operator[](size_t idx) const -> const Column_T &
 | 
			
		||||
	{
 | 
			
		||||
		return values[idx];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator*(const mat4_impl<T> &other) const -> mat4_impl<T>
 | 
			
		||||
	[[nodiscard]] constexpr auto operator*(const mat4_impl<T> &other) const -> mat4_impl<T>
 | 
			
		||||
	{
 | 
			
		||||
		return mat4_impl<T> {};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator*(const vec4_impl<T> &other) const -> vec4_impl<T>
 | 
			
		||||
	[[nodiscard]] constexpr auto operator*(const vec4_impl<T> &other) const -> vec4_impl<T>
 | 
			
		||||
	{
 | 
			
		||||
		return vec4_impl<T> {};
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,18 +5,28 @@ namespace lt::math {
 | 
			
		|||
template<typename T = float>
 | 
			
		||||
struct vec2_impl
 | 
			
		||||
{
 | 
			
		||||
	vec2_impl(): x(), y()
 | 
			
		||||
	constexpr vec2_impl(): x(), y()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	explicit vec2_impl(T scalar): x(scalar), y(scalar)
 | 
			
		||||
	constexpr explicit vec2_impl(T scalar): x(scalar), y(scalar)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vec2_impl(T x, T y): x(x), y(y)
 | 
			
		||||
	constexpr vec2_impl(T x, T y): x(x), y(y)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator==(const vec2_impl<T> &other) const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return x == other.x && y == other.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator!=(const vec2_impl<T> &other) const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return !(*this == other);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator*(const vec2_impl<T> &other) const -> vec2_impl
 | 
			
		||||
	{
 | 
			
		||||
		return {
 | 
			
		||||
| 
						 | 
				
			
			@ -41,12 +51,12 @@ struct vec2_impl
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	T x; // NOLINT
 | 
			
		||||
 | 
			
		||||
	T y; // NOLINT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using vec2 = vec2_impl<float>;
 | 
			
		||||
 | 
			
		||||
using ivec2 = vec2_impl<int32_t>;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,3 +64,17 @@ using ivec2 = vec2_impl<int32_t>;
 | 
			
		|||
using uvec2 = vec2_impl<uint32_t>;
 | 
			
		||||
 | 
			
		||||
} // namespace lt::math
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct std::formatter<lt::math::vec2_impl<T>>
 | 
			
		||||
{
 | 
			
		||||
	constexpr auto parse(std::format_parse_context &context)
 | 
			
		||||
	{
 | 
			
		||||
		return context.begin();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto format(const lt::math::vec2_impl<T> &val, std::format_context &context) const
 | 
			
		||||
	{
 | 
			
		||||
		return std::format_to(context.out(), "{}, {}", val.x, val.y);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,19 +7,29 @@ namespace lt::math {
 | 
			
		|||
template<typename T = float>
 | 
			
		||||
struct vec3_impl
 | 
			
		||||
{
 | 
			
		||||
	vec3_impl(): x(), y(), z()
 | 
			
		||||
	constexpr vec3_impl(): x(), y(), z()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	explicit vec3_impl(T scalar): x(scalar), y(scalar), z(scalar)
 | 
			
		||||
	constexpr explicit vec3_impl(T scalar): x(scalar), y(scalar), z(scalar)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vec3_impl(T x, T y, T z): x(x), y(y), z(z)
 | 
			
		||||
	constexpr vec3_impl(T x, T y, T z): x(x), y(y), z(z)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator-(const vec3_impl<T> &other) const -> vec3_impl
 | 
			
		||||
	[[nodiscard]] auto operator==(const vec3_impl<T> &other) const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return x == other.x && y == other.y && z == other.z;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator!=(const vec3_impl<T> &other) const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return !(*this == other);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] constexpr auto operator-(const vec3_impl<T> &other) const -> vec3_impl
 | 
			
		||||
	{
 | 
			
		||||
		return {
 | 
			
		||||
			x - other.x,
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +38,7 @@ struct vec3_impl
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator*(const vec3_impl<T> &other) const -> vec3_impl
 | 
			
		||||
	[[nodiscard]] constexpr auto operator*(const vec3_impl<T> &other) const -> vec3_impl
 | 
			
		||||
	{
 | 
			
		||||
		return {
 | 
			
		||||
			x * other.x,
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +47,12 @@ struct vec3_impl
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	friend auto operator<<(std::ostream &stream, vec3_impl<T> value) -> std::ostream &
 | 
			
		||||
	{
 | 
			
		||||
		stream << value.x << ", " << value.y << ", " << value.z;
 | 
			
		||||
		return stream;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	T x; // NOLINT
 | 
			
		||||
 | 
			
		||||
	T y; // NOLINT
 | 
			
		||||
| 
						 | 
				
			
			@ -51,3 +67,17 @@ using ivec3 = vec3_impl<int32_t>;
 | 
			
		|||
using uvec3 = vec3_impl<uint32_t>;
 | 
			
		||||
 | 
			
		||||
} // namespace lt::math
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct std::formatter<lt::math::vec3_impl<T>>
 | 
			
		||||
{
 | 
			
		||||
	constexpr auto parse(std::format_parse_context &context)
 | 
			
		||||
	{
 | 
			
		||||
		return context.begin();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto format(const lt::math::vec3_impl<T> &val, std::format_context &context) const
 | 
			
		||||
	{
 | 
			
		||||
		return std::format_to(context.out(), "{}, {}, {}", val.x, val.y, val.z);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,19 +7,29 @@ namespace lt::math {
 | 
			
		|||
template<typename T = float>
 | 
			
		||||
struct vec4_impl
 | 
			
		||||
{
 | 
			
		||||
	vec4_impl(): x(), y(), z(), w()
 | 
			
		||||
	constexpr vec4_impl(): x(), y(), z(), w()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	explicit vec4_impl(T scalar): x(scalar), y(scalar), z(scalar), w(scalar)
 | 
			
		||||
	constexpr explicit vec4_impl(T scalar): x(scalar), y(scalar), z(scalar), w(scalar)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vec4_impl(T x, T y, T z, T w): x(x), y(y), z(z), w(w)
 | 
			
		||||
	constexpr vec4_impl(T x, T y, T z, T w): x(x), y(y), z(z), w(w)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator-(const vec4_impl<T> &other) const -> vec4_impl
 | 
			
		||||
	[[nodiscard]] auto operator==(const vec4_impl<T> &other) const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return x == other.x && y == other.y && z == other.z && w == other.w;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator!=(const vec4_impl<T> &other) const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return !(*this == other);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] constexpr auto operator-(const vec4_impl<T> &other) const -> vec4_impl
 | 
			
		||||
	{
 | 
			
		||||
		return {
 | 
			
		||||
			x - other.x,
 | 
			
		||||
| 
						 | 
				
			
			@ -29,16 +39,22 @@ struct vec4_impl
 | 
			
		|||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator[](size_t idx) -> T &
 | 
			
		||||
	[[nodiscard]] constexpr auto operator[](size_t idx) -> T &
 | 
			
		||||
	{
 | 
			
		||||
		return values[idx];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto operator[](size_t idx) const -> const T &
 | 
			
		||||
	[[nodiscard]] constexpr auto operator[](size_t idx) const -> const T &
 | 
			
		||||
	{
 | 
			
		||||
		return values[idx];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	friend auto operator<<(std::ostream &stream, vec4_impl<T> value) -> std::ostream &
 | 
			
		||||
	{
 | 
			
		||||
		stream << value.x << ", " << value.y << ", " << value.z << ", " << value.w;
 | 
			
		||||
		return stream;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// NOLINTNEXTLINE
 | 
			
		||||
	union
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -76,3 +92,17 @@ using ivec4 = vec4_impl<int32_t>;
 | 
			
		|||
using uvec4 = vec4_impl<uint32_t>;
 | 
			
		||||
 | 
			
		||||
} // namespace lt::math
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct std::formatter<lt::math::vec4_impl<T>>
 | 
			
		||||
{
 | 
			
		||||
	constexpr auto parse(std::format_parse_context &context)
 | 
			
		||||
	{
 | 
			
		||||
		return context.begin();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto format(const lt::math::vec4_impl<T> &val, std::format_context &context) const
 | 
			
		||||
	{
 | 
			
		||||
		return std::format_to(context.out(), "{}, {}, {}, {}", val.x, val.y, val.z, val.w);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,8 @@ target_link_libraries(
 | 
			
		|||
  libmirror
 | 
			
		||||
  INTERFACE
 | 
			
		||||
  app
 | 
			
		||||
  opengl::opengl
 | 
			
		||||
  time
 | 
			
		||||
  input 
 | 
			
		||||
  surface
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,4 +17,4 @@ add_test_module(libmirror
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
add_executable_module(mirror entrypoint/mirror.cpp)
 | 
			
		||||
target_link_libraries(mirror PRIVATE libmirror)
 | 
			
		||||
target_link_libraries(mirror PRIVATE libmirror input)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,100 @@
 | 
			
		|||
#include <X11/keysym.h>
 | 
			
		||||
#include <app/application.hpp>
 | 
			
		||||
#include <app/entrypoint.hpp>
 | 
			
		||||
#include <app/system.hpp>
 | 
			
		||||
#include <ecs/entity.hpp>
 | 
			
		||||
#include <input/components.hpp>
 | 
			
		||||
#include <input/system.hpp>
 | 
			
		||||
#include <math/vec2.hpp>
 | 
			
		||||
#include <surface/events/keyboard.hpp>
 | 
			
		||||
#include <surface/events/surface.hpp>
 | 
			
		||||
#include <surface/system.hpp>
 | 
			
		||||
#include <time/timer.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
template<class... Ts>
 | 
			
		||||
struct overloads: Ts...
 | 
			
		||||
class MirrorSystem: public lt::app::ISystem
 | 
			
		||||
{
 | 
			
		||||
	using Ts::operator()...;
 | 
			
		||||
public:
 | 
			
		||||
	MirrorSystem(
 | 
			
		||||
	    Ref<ecs::Registry> registry,
 | 
			
		||||
	    lt::input::InputAction::Key quit_action_key,
 | 
			
		||||
	    std::array<lt::input::InputAction::Key, 4> debug_action_keys
 | 
			
		||||
	)
 | 
			
		||||
	    : m_registry(std::move(registry))
 | 
			
		||||
	    , m_quit_action_key(quit_action_key)
 | 
			
		||||
	    , m_debug_action_keys(debug_action_keys)
 | 
			
		||||
	{
 | 
			
		||||
		using Surface = lt::surface::SurfaceComponent;
 | 
			
		||||
		using Input = lt::input::InputComponent;
 | 
			
		||||
 | 
			
		||||
		auto view = m_registry->get_entt_registry().view<Surface, Input>();
 | 
			
		||||
 | 
			
		||||
		view.each([&](Surface &surface, Input &input) {});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto tick() -> bool override
 | 
			
		||||
	{
 | 
			
		||||
		using Surface = lt::surface::SurfaceComponent;
 | 
			
		||||
		using Input = lt::input::InputComponent;
 | 
			
		||||
 | 
			
		||||
		static lt::Timer timer;
 | 
			
		||||
 | 
			
		||||
		std::this_thread::sleep_for(std::chrono::milliseconds { 10 });
 | 
			
		||||
		auto should_quit = false;
 | 
			
		||||
		auto view = m_registry->get_entt_registry().view<Surface, Input>();
 | 
			
		||||
		view.each([&](Surface &surface, Input &input) {
 | 
			
		||||
			using State = lt::input::InputAction::State;
 | 
			
		||||
			const auto &[x, y] = surface.get_position();
 | 
			
		||||
			const auto &[width, height] = surface.get_resolution();
 | 
			
		||||
 | 
			
		||||
			if (input.get_action(m_quit_action_key).state == State::active)
 | 
			
		||||
			{
 | 
			
		||||
				log_dbg("Quit triggered! BYE!");
 | 
			
		||||
				should_quit = true;
 | 
			
		||||
			}
 | 
			
		||||
			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 }));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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 }));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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 }));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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 }));
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		timer.reset();
 | 
			
		||||
		return should_quit;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void on_register() override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void on_unregister() override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Ref<ecs::Registry> m_registry;
 | 
			
		||||
 | 
			
		||||
	lt::input::InputAction::Key m_quit_action_key;
 | 
			
		||||
	std::array<lt::input::InputAction::Key, 4> m_debug_action_keys {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Mirror: public app::Application
 | 
			
		||||
| 
						 | 
				
			
			@ -20,53 +105,99 @@ public:
 | 
			
		|||
		m_editor_registry = create_ref<ecs::Registry>();
 | 
			
		||||
 | 
			
		||||
		setup_window_system();
 | 
			
		||||
		setup_input_system();
 | 
			
		||||
 | 
			
		||||
		register_systems();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		m_window_system->add_event_listener(
 | 
			
		||||
		    m_window,
 | 
			
		||||
		    [&](const surface::SurfaceComponent::Event &event) {
 | 
			
		||||
			    const auto visitor = overloads {
 | 
			
		||||
				    [&](const lt::surface::KeyPressedEvent &event) {
 | 
			
		||||
				        std::cout << "key pressed: " << event.to_string() << std::endl;
 | 
			
		||||
	void on_window_close()
 | 
			
		||||
	{
 | 
			
		||||
		log_inf("Window close requested...");
 | 
			
		||||
 | 
			
		||||
				        if (event.get_key() == 81)
 | 
			
		||||
				        {
 | 
			
		||||
					        unregister_system(m_window_system);
 | 
			
		||||
					        log_inf("Quitting...");
 | 
			
		||||
				        }
 | 
			
		||||
				        return true;
 | 
			
		||||
				    },
 | 
			
		||||
				    [](const auto &) { return false; },
 | 
			
		||||
			    };
 | 
			
		||||
 | 
			
		||||
			    return std::visit(visitor, event);
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
		unregister_system(m_input_system);
 | 
			
		||||
		unregister_system(m_surface_system);
 | 
			
		||||
		unregister_system(m_mirror_system);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setup_window_system()
 | 
			
		||||
	{
 | 
			
		||||
		using lt::input::InputComponent;
 | 
			
		||||
		using lt::surface::SurfaceComponent;
 | 
			
		||||
		m_window_system = create_ref<lt::surface::System>(m_editor_registry);
 | 
			
		||||
		m_surface_system = create_ref<lt::surface::System>(m_editor_registry);
 | 
			
		||||
 | 
			
		||||
		m_window = m_editor_registry->create_entity("Editor Window");
 | 
			
		||||
		m_window.add_component<SurfaceComponent>(SurfaceComponent::CreateInfo {
 | 
			
		||||
		    .title = "Editor Window",
 | 
			
		||||
		    .resolution = { 800u, 600u },
 | 
			
		||||
		    .resolution = { 400u, 400u },
 | 
			
		||||
		    .vsync = true,
 | 
			
		||||
		    .visible = true,
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		auto &input = m_window.add_component<InputComponent>();
 | 
			
		||||
		auto quit_action_key = input.add_action(
 | 
			
		||||
		    input::InputAction {
 | 
			
		||||
		        .name = "quit",
 | 
			
		||||
		        .trigger = input::Trigger { .mapped_keycode = XK_q },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		auto debug_action_keys = std::array<lt::input::InputAction::Key, 4> {};
 | 
			
		||||
 | 
			
		||||
		debug_action_keys[0] = input.add_action(
 | 
			
		||||
		    input::InputAction {
 | 
			
		||||
		        .name = "debug_1",
 | 
			
		||||
		        .trigger = input::Trigger { .mapped_keycode = XK_1 },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		debug_action_keys[1] = input.add_action(
 | 
			
		||||
		    input::InputAction {
 | 
			
		||||
		        .name = "debug_2",
 | 
			
		||||
		        .trigger = input::Trigger { .mapped_keycode = XK_2 },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		debug_action_keys[2] = input.add_action(
 | 
			
		||||
		    input::InputAction {
 | 
			
		||||
		        .name = "debug_3",
 | 
			
		||||
		        .trigger = input::Trigger { .mapped_keycode = XK_3 },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		debug_action_keys[3] = input.add_action(
 | 
			
		||||
		    input::InputAction {
 | 
			
		||||
		        .name = "debug_4",
 | 
			
		||||
		        .trigger = input::Trigger { .mapped_keycode = XK_4 },
 | 
			
		||||
		    }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		m_input_system = create_ref<input::System>(m_editor_registry);
 | 
			
		||||
		m_mirror_system = create_ref<MirrorSystem>(
 | 
			
		||||
		    m_editor_registry,
 | 
			
		||||
		    quit_action_key,
 | 
			
		||||
		    debug_action_keys
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setup_input_system()
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void register_systems()
 | 
			
		||||
	{
 | 
			
		||||
		register_system(m_window_system);
 | 
			
		||||
		register_system(m_surface_system);
 | 
			
		||||
		register_system(m_input_system);
 | 
			
		||||
		register_system(m_mirror_system);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Ref<ecs::Registry> m_editor_registry;
 | 
			
		||||
 | 
			
		||||
	Ref<lt::surface::System> m_window_system;
 | 
			
		||||
	Ref<lt::surface::System> m_surface_system;
 | 
			
		||||
 | 
			
		||||
	Ref<lt::input::System> m_input_system;
 | 
			
		||||
 | 
			
		||||
	Ref<MirrorSystem> m_mirror_system;
 | 
			
		||||
 | 
			
		||||
	lt::ecs::Entity m_window;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										248
									
								
								modules/renderer/.clang-tidy
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								modules/renderer/.clang-tidy
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,248 @@
 | 
			
		|||
---
 | 
			
		||||
Checks: "-*,
 | 
			
		||||
 | 
			
		||||
performance-unnecessary-value-param,
 | 
			
		||||
performance-unnecessary-copy-initialization,
 | 
			
		||||
performance-type-promotion-in-math-fn,
 | 
			
		||||
performance-trivially-destructible,
 | 
			
		||||
performance-noexcept-swap,
 | 
			
		||||
performance-noexcept-move-constructor,
 | 
			
		||||
performance-noexcept-destructor,
 | 
			
		||||
performance-no-int-to-ptr,
 | 
			
		||||
performance-no-automatic-move,
 | 
			
		||||
performance-move-constructor-init,
 | 
			
		||||
performance-move-const-arg,
 | 
			
		||||
performance-inefficient-vector-operation,
 | 
			
		||||
performance-inefficient-string-concatenation,
 | 
			
		||||
performance-inefficient-algorithm,
 | 
			
		||||
performance-implicit-conversion-in-loop,
 | 
			
		||||
performance-for-range-copy,
 | 
			
		||||
performance-faster-string-find,
 | 
			
		||||
performance-enum-size,
 | 
			
		||||
performance-avoid-endl,
 | 
			
		||||
 | 
			
		||||
readability-avoid-const-params-in-decls,
 | 
			
		||||
readability-avoid-nested-conditional-operator,
 | 
			
		||||
readability-avoid-return-with-void-value,
 | 
			
		||||
readability-avoid-unconditional-preprocessor-if,
 | 
			
		||||
readability-braces-around-statements,
 | 
			
		||||
readability-const-return-type,
 | 
			
		||||
readability-container-contains,
 | 
			
		||||
readability-container-data-pointdr,
 | 
			
		||||
readability-container-size-empty,
 | 
			
		||||
readability-delete-null-pointer,
 | 
			
		||||
readability-duplicate-include,
 | 
			
		||||
readability-else-after-return,
 | 
			
		||||
readability-inconsistent-declaration-parameter-name,
 | 
			
		||||
readability-isolate-declaration,
 | 
			
		||||
readability-make-member-function-const,
 | 
			
		||||
readability-misleading-indentation,
 | 
			
		||||
readability-misplaced-array-index,
 | 
			
		||||
readability-named-parameter,
 | 
			
		||||
readability-non-const-parameter,
 | 
			
		||||
readability-qualified-auto,
 | 
			
		||||
readability-redundant-access-specifiers,
 | 
			
		||||
readability-redundant-casting,
 | 
			
		||||
readability-redundant-control-flow,
 | 
			
		||||
readability-redundant-declaration,
 | 
			
		||||
readability-redundant-function-ptr-dereference,
 | 
			
		||||
readability-redundant-inline-specifier,
 | 
			
		||||
readability-redundant-member-init,
 | 
			
		||||
readability-redundant-preprocessor,
 | 
			
		||||
readability-redundant-smartptr-get,
 | 
			
		||||
readability-redundant-string-cstr,
 | 
			
		||||
readability-reference-to-constructed-temporary,
 | 
			
		||||
readability-simplify-boolean-expr,
 | 
			
		||||
readability-simplify-subscript-expr,
 | 
			
		||||
readability-static-accessed-through-instance,
 | 
			
		||||
readability-static-definition-in-anonymous-namespace,
 | 
			
		||||
readability-string-compare,
 | 
			
		||||
readability-suspicious-call-argument,
 | 
			
		||||
readability-uniqueptr-delete-release,
 | 
			
		||||
readability-use-anyofallof
 | 
			
		||||
readability-use-std-min-max,
 | 
			
		||||
readability-function-cognitive-complexity
 | 
			
		||||
readability-function-size
 | 
			
		||||
readability-identifier-naming
 | 
			
		||||
readability-identifier-length
 | 
			
		||||
readability-magic-numbers
 | 
			
		||||
 | 
			
		||||
modernize-avoid-bind,
 | 
			
		||||
modernize-avoid-c-arrays,
 | 
			
		||||
modernize-concat-nested-namespaces,
 | 
			
		||||
modernize-deprecated-headers,
 | 
			
		||||
modernize-deprecated-ios-base-aliases,
 | 
			
		||||
modernize-loop-convert,
 | 
			
		||||
modernize-macro-to-enum,
 | 
			
		||||
modernize-make-shared,
 | 
			
		||||
modernize-make-unique,
 | 
			
		||||
modernize-pass-by-value,
 | 
			
		||||
modernize-raw-string-literal,
 | 
			
		||||
modernize-redundant-void-arg,
 | 
			
		||||
modernize-replace-auto-ptr,
 | 
			
		||||
modernize-replace-disallow-copy-and-assign-macro,
 | 
			
		||||
modernize-replace-random-shuffle,
 | 
			
		||||
modernize-return-braced-init-list,
 | 
			
		||||
modernize-shrink-to-fit,
 | 
			
		||||
modernize-type-traits,
 | 
			
		||||
modernize-unary-static-assert,
 | 
			
		||||
modernize-use-auto,
 | 
			
		||||
modernize-use-bool-literals,
 | 
			
		||||
modernize-use-constraints,
 | 
			
		||||
modernize-use-default-member-init,
 | 
			
		||||
modernize-use-designated-initializers,
 | 
			
		||||
modernize-use-emplace,
 | 
			
		||||
modernize-use-equals-default,
 | 
			
		||||
modernize-use-equals-delete,
 | 
			
		||||
modernize-use-nodiscard,
 | 
			
		||||
modernize-use-noexcept,
 | 
			
		||||
modernize-use-nullptr,
 | 
			
		||||
modernize-use-override,
 | 
			
		||||
modernize-use-starts-ends-with,
 | 
			
		||||
modernize-use-std-numbers,
 | 
			
		||||
modernize-use-std-print,
 | 
			
		||||
modernize-use-transparent-functors,
 | 
			
		||||
modernize-use-uncaught-exceptions,
 | 
			
		||||
modernize-use-using
 | 
			
		||||
modernize-min-max-use-initializer-list,
 | 
			
		||||
 | 
			
		||||
cppcoreguidelines-avoid-capturing-lambda-coroutines,
 | 
			
		||||
cppcoreguidelines-avoid-const-or-ref-data-members,
 | 
			
		||||
cppcoreguidelines-avoid-do-while,
 | 
			
		||||
cppcoreguidelines-avoid-goto,
 | 
			
		||||
cppcoreguidelines-avoid-non-const-global-variables,
 | 
			
		||||
cppcoreguidelines-avoid-reference-coroutine-parameters,
 | 
			
		||||
cppcoreguidelines-init-variables,
 | 
			
		||||
cppcoreguidelines-interfaces-global-init,
 | 
			
		||||
cppcoreguidelines-macro-usage,
 | 
			
		||||
cppcoreguidelines-misleading-capture-default-by-value,
 | 
			
		||||
cppcoreguidelines-missing-std-forward,
 | 
			
		||||
cppcoreguidelines-narrowing-conversions,
 | 
			
		||||
cppcoreguidelines-no-malloc,
 | 
			
		||||
cppcoreguidelines-no-suspend-with-lock,
 | 
			
		||||
cppcoreguidelines-owning-memory,
 | 
			
		||||
cppcoreguidelines-prefer-member-initializer,
 | 
			
		||||
cppcoreguidelines-pro-bounds-array-to-pointer-decay,
 | 
			
		||||
cppcoreguidelines-pro-bounds-pointer-arithmetic,
 | 
			
		||||
cppcoreguidelines-pro-type-const-cast,
 | 
			
		||||
cppcoreguidelines-pro-type-cstyle-cast,
 | 
			
		||||
cppcoreguidelines-pro-type-member-init,
 | 
			
		||||
cppcoreguidelines-pro-type-reinterpret-cast,
 | 
			
		||||
cppcoreguidelines-pro-type-static-cast-downcast,
 | 
			
		||||
cppcoreguidelines-pro-type-vararg,
 | 
			
		||||
cppcoreguidelines-rvalue-reference-param-not-moved,
 | 
			
		||||
cppcoreguidelines-slicing,
 | 
			
		||||
cppcoreguidelines-special-member-functions,
 | 
			
		||||
cppcoreguidelines-virtual-class-destructor,
 | 
			
		||||
 | 
			
		||||
bugprone-argument-comment,
 | 
			
		||||
bugprone-assert-side-effect,
 | 
			
		||||
bugprone-assignment-in-if-condition,
 | 
			
		||||
bugprone-bad-signal-to-kill-thread,
 | 
			
		||||
bugprone-bool-pointer-implicit-conversion,
 | 
			
		||||
bugprone-branch-clone,
 | 
			
		||||
bugprone-casting-through-void,
 | 
			
		||||
bugprone-chained-comparison,
 | 
			
		||||
bugprone-compare-pointer-to-member-virtual-function,
 | 
			
		||||
bugprone-copy-constructor-init,
 | 
			
		||||
bugprone-crtp-constructor-accessibility,
 | 
			
		||||
bugprone-dangling-handle,
 | 
			
		||||
bugprone-empty-catch,
 | 
			
		||||
bugprone-exception-escape,
 | 
			
		||||
bugprone-fold-init-type,
 | 
			
		||||
bugprone-forward-declaration-namespace,
 | 
			
		||||
bugprone-forwarding-reference-overload,
 | 
			
		||||
bugprone-implicit-widening-of-multiplication-result,
 | 
			
		||||
bugprone-inaccurate-erase,
 | 
			
		||||
bugprone-inc-dec-in-conditions,
 | 
			
		||||
bugprone-incorrect-enable-if,
 | 
			
		||||
bugprone-incorrect-roundings,
 | 
			
		||||
bugprone-infinite-loop,
 | 
			
		||||
bugprone-integer-division,
 | 
			
		||||
bugprone-lambda-function-name,
 | 
			
		||||
bugprone-macro-parentheses,
 | 
			
		||||
bugprone-macro-repeated-side-effects,
 | 
			
		||||
bugprone-misplaced-operator-in-strlen-in-alloc,
 | 
			
		||||
bugprone-misplaced-pointer-arithmetic-in-alloc,
 | 
			
		||||
bugprone-misplaced-widening-cast,
 | 
			
		||||
bugprone-move-forwarding-reference,
 | 
			
		||||
bugprone-multi-level-implicit-pointer-conversion,
 | 
			
		||||
bugprone-multiple-new-in-one-expression,
 | 
			
		||||
bugprone-multiple-statement-macro,
 | 
			
		||||
bugprone-no-escape,
 | 
			
		||||
bugprone-non-zero-enum-to-bool-conversion,
 | 
			
		||||
bugprone-not-null-terminated-result,
 | 
			
		||||
bugprone-optional-value-conversion,
 | 
			
		||||
bugprone-parent-virtual-call,
 | 
			
		||||
bugprone-posix-return,
 | 
			
		||||
bugprone-redundant-branch-condition,
 | 
			
		||||
bugprone-reserved-identifier,
 | 
			
		||||
bugprone-return-const-ref-from-parameter,
 | 
			
		||||
bugprone-shared-ptr-array-mismatch,
 | 
			
		||||
bugprone-signal-handler,
 | 
			
		||||
bugprone-signed-char-misuse,
 | 
			
		||||
bugprone-sizeof-container,
 | 
			
		||||
bugprone-sizeof-expression,
 | 
			
		||||
bugprone-spuriously-wake-up-functions,
 | 
			
		||||
bugprone-standalone-empty,
 | 
			
		||||
bugprone-string-constructor,
 | 
			
		||||
bugprone-string-integer-assignment,
 | 
			
		||||
bugprone-string-literal-with-embedded-nul,
 | 
			
		||||
bugprone-stringview-nullptr,
 | 
			
		||||
bugprone-suspicious-enum-usage,
 | 
			
		||||
bugprone-suspicious-include,
 | 
			
		||||
bugprone-suspicious-memory-comparison,
 | 
			
		||||
bugprone-suspicious-memset-usage,
 | 
			
		||||
bugprone-suspicious-missing-comma,
 | 
			
		||||
bugprone-suspicious-realloc-usage,
 | 
			
		||||
bugprone-suspicious-semicolon,
 | 
			
		||||
bugprone-suspicious-string-compare,
 | 
			
		||||
bugprone-suspicious-stringview-data-usage,
 | 
			
		||||
bugprone-swapped-arguments,
 | 
			
		||||
bugprone-switch-missing-default-case,
 | 
			
		||||
bugprone-terminating-continue,
 | 
			
		||||
bugprone-throw-keyword-missing,
 | 
			
		||||
bugprone-too-small-loop-variable,
 | 
			
		||||
bugprone-unchecked-optional-access,
 | 
			
		||||
bugprone-undefined-memory-manipulation,
 | 
			
		||||
bugprone-undelegated-constructor,
 | 
			
		||||
bugprone-unhandled-exception-at-new,
 | 
			
		||||
bugprone-unhandled-self-assignment,
 | 
			
		||||
bugprone-unique-ptr-array-mismatch,
 | 
			
		||||
bugprone-unsafe-functions,
 | 
			
		||||
bugprone-unused-local-non-trivial-variable,
 | 
			
		||||
bugprone-unused-raii,
 | 
			
		||||
bugprone-unused-return-value,
 | 
			
		||||
bugprone-use-after-move,
 | 
			
		||||
bugprone-virtual-near-miss,
 | 
			
		||||
 | 
			
		||||
concurrency-mt-unsafe,
 | 
			
		||||
concurrency-thread-canceltype-asynchronous,
 | 
			
		||||
 | 
			
		||||
misc-use-anonymous-namespace,
 | 
			
		||||
misc-unused-using-decls,
 | 
			
		||||
misc-unused-parameters,
 | 
			
		||||
misc-unused-alias-decls,
 | 
			
		||||
misc-uniqueptr-reset-release,
 | 
			
		||||
misc-unconventional-assign-operator,
 | 
			
		||||
misc-throw-by-value-catch-by-reference,
 | 
			
		||||
misc-static-assert,
 | 
			
		||||
misc-redundant-expression,
 | 
			
		||||
misc-non-private-member-variables-in-classes,
 | 
			
		||||
misc-non-copyable-objects,
 | 
			
		||||
misc-no-recursion,
 | 
			
		||||
misc-new-delete-overloads,
 | 
			
		||||
misc-misplaced-const,
 | 
			
		||||
misc-misleading-identifier,
 | 
			
		||||
misc-misleading-bidirectional,
 | 
			
		||||
misc-header-include-cycle,
 | 
			
		||||
misc-definitions-in-headers,
 | 
			
		||||
misc-coroutine-hostile-raii,
 | 
			
		||||
misc-const-correctness,
 | 
			
		||||
 | 
			
		||||
-hicpp-signed-bitwise,
 | 
			
		||||
hicpp-no-assembler,
 | 
			
		||||
hicpp-multiway-paths-covered,
 | 
			
		||||
hicpp-ignored-remove-result,
 | 
			
		||||
hicpp-exception-baseclass,
 | 
			
		||||
"
 | 
			
		||||
| 
						 | 
				
			
			@ -27,10 +27,7 @@ target_link_libraries(
 | 
			
		|||
  renderer
 | 
			
		||||
  PUBLIC camera
 | 
			
		||||
  PUBLIC input
 | 
			
		||||
  PUBLIC glad
 | 
			
		||||
  PUBLIC logger
 | 
			
		||||
  PUBLIC opengl::opengl
 | 
			
		||||
  PUBLIC glfw
 | 
			
		||||
  PUBLIC imgui
 | 
			
		||||
  PUBLIC asset_parser
 | 
			
		||||
  PUBLIC yaml-cpp::yaml-cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								modules/renderer/private/backend.test.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								modules/renderer/private/backend.test.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
#include <ranges>
 | 
			
		||||
#include <renderer/system.hpp>
 | 
			
		||||
#include <test/test.hpp>
 | 
			
		||||
 | 
			
		||||
using namespace lt;
 | 
			
		||||
#include <renderer/backend.hpp>
 | 
			
		||||
 | 
			
		||||
using lt::test::Case;
 | 
			
		||||
using lt::test::Suite;
 | 
			
		||||
 | 
			
		||||
Suite raii = [] {
 | 
			
		||||
	Case { "happy path won't throw" } = [] {
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -7,15 +7,9 @@
 | 
			
		|||
#include <renderer/renderer.hpp>       // required for forward declaratio>
 | 
			
		||||
#include <ui/ui.hpp>                   // required for forward declaratio>
 | 
			
		||||
 | 
			
		||||
#define GLFW_EXPOSE_NATIVE_WIN32
 | 
			
		||||
#include <glfw/glfw3.h>
 | 
			
		||||
#include <glfw/glfw3native.h>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
dxGraphicsContext::dxGraphicsContext(GLFWwindow *windowHandle)
 | 
			
		||||
    : m_window_handle(windowHandle)
 | 
			
		||||
    , m_debug_interface(nullptr)
 | 
			
		||||
dxGraphicsContext::dxGraphicsContext(): m_window_handle(windowHandle), m_debug_interface(nullptr)
 | 
			
		||||
{
 | 
			
		||||
	// set 'GraphicsAPI';
 | 
			
		||||
	m_graphics_api = GraphicsAPI::DirectX;
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +22,7 @@ dxGraphicsContext::dxGraphicsContext(GLFWwindow *windowHandle)
 | 
			
		|||
	setup_debug_interface();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dxGraphicsContext::setup_device_and_swap_chain(GLFWwindow *windowHandle)
 | 
			
		||||
void dxGraphicsContext::setup_device_and_swap_chain()
 | 
			
		||||
{
 | 
			
		||||
	auto context = std::static_pointer_cast<dxSharedContext>(m_shared_context);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +46,7 @@ void dxGraphicsContext::setup_device_and_swap_chain(GLFWwindow *windowHandle)
 | 
			
		|||
	sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 | 
			
		||||
	sd.BufferCount = 1u;
 | 
			
		||||
 | 
			
		||||
	// #todo: don't handle Windows's window with glfw, create it yourself
 | 
			
		||||
	sd.OutputWindow = static_cast<HWND>(glfwGetWin32Window(windowHandle));
 | 
			
		||||
	sd.OutputWindow = {}; // ...
 | 
			
		||||
	sd.Windowed = true;
 | 
			
		||||
 | 
			
		||||
	sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,23 +4,19 @@
 | 
			
		|||
#include <renderer/graphics_context.hpp>
 | 
			
		||||
#include <wrl.h>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class dxGraphicsContext: public GraphicsContext
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	dxGraphicsContext(GLFWwindow *windowHandle);
 | 
			
		||||
	dxGraphicsContext();
 | 
			
		||||
 | 
			
		||||
	virtual void log_debug_data() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLFWwindow *m_window_handle;
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID3D11Debug> m_debug_interface;
 | 
			
		||||
 | 
			
		||||
	void setup_device_and_swap_chain(GLFWwindow *windowHandle);
 | 
			
		||||
	void setup_device_and_swap_chain();
 | 
			
		||||
 | 
			
		||||
	void setup_render_targets();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,66 +0,0 @@
 | 
			
		|||
#include <input/key_codes.hpp>
 | 
			
		||||
#include <renderer/dx/shared_context.hpp>
 | 
			
		||||
#include <renderer/dx/user_interface.hpp>
 | 
			
		||||
 | 
			
		||||
#define GLFW_EXPOSE_NATIVE_WIN32
 | 
			
		||||
#include <backends/imgui_impl_dx11.h>
 | 
			
		||||
#include <backends/imgui_impl_win32.h>
 | 
			
		||||
#include <glfw/glfw3.h>
 | 
			
		||||
#include <glfw/glfw3native.h>
 | 
			
		||||
#include <imgui.h>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
void dxUserInterface::platform_implementation(
 | 
			
		||||
    GLFWwindow *windowHandle,
 | 
			
		||||
    Ref<SharedContext> sharedContext
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
	auto &io = ImGui::GetIO();
 | 
			
		||||
	auto context = std::dynamic_pointer_cast<dxSharedContext>(sharedContext);
 | 
			
		||||
 | 
			
		||||
	ImGui_ImplWin32_Init(glfwGetWin32Window(windowHandle));
 | 
			
		||||
	ImGui_ImplDX11_Init(context->get_device().Get(), context->get_device_context().Get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dxUserInterface::~dxUserInterface()
 | 
			
		||||
{
 | 
			
		||||
	// #todo: handle this in a better way
 | 
			
		||||
	auto &io = ImGui::GetIO();
 | 
			
		||||
 | 
			
		||||
	if (io.IniFilename == "default_gui_layout.ini")
 | 
			
		||||
		io.IniFilename = "user_gui_layout.ini";
 | 
			
		||||
 | 
			
		||||
	ImGui_ImplDX11_Shutdown();
 | 
			
		||||
	ImGui_ImplWin32_Shutdown();
 | 
			
		||||
	ImGui::DestroyContext();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dxUserInterface::begin()
 | 
			
		||||
{
 | 
			
		||||
	ImGui_ImplDX11_NewFrame();
 | 
			
		||||
	ImGui_ImplWin32_NewFrame();
 | 
			
		||||
	ImGui::NewFrame();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dxUserInterface::end()
 | 
			
		||||
{
 | 
			
		||||
	ImGui::Render();
 | 
			
		||||
	ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
 | 
			
		||||
 | 
			
		||||
	ImGui::UpdatePlatformWindows();
 | 
			
		||||
	ImGui::RenderPlatformWindowsDefault();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dxUserInterface::log_debug_data()
 | 
			
		||||
{
 | 
			
		||||
	// #todo: improve
 | 
			
		||||
	log_inf("________________________________________");
 | 
			
		||||
	log_inf("UserInterface::");
 | 
			
		||||
	log_inf("       API    : ImGui");
 | 
			
		||||
	log_inf("       Version: {}", ImGui::GetVersion());
 | 
			
		||||
	log_inf("  GraphicsAPI : DirectX");
 | 
			
		||||
	log_inf("________________________________________");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			@ -4,8 +4,6 @@
 | 
			
		|||
#include <ui/ui.hpp>
 | 
			
		||||
#include <wrl.h>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class dxSharedContext;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,10 +15,7 @@ public:
 | 
			
		|||
 | 
			
		||||
	~dxUserInterface();
 | 
			
		||||
 | 
			
		||||
	void platform_implementation(
 | 
			
		||||
	    GLFWwindow *windowHandle,
 | 
			
		||||
	    Ref<SharedContext> sharedContext
 | 
			
		||||
	) override;
 | 
			
		||||
	void platform_implementation(Ref<SharedContext> sharedContext) override;
 | 
			
		||||
 | 
			
		||||
	void begin() override;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
#include <glad/gl.h>
 | 
			
		||||
#include <renderer/gl/blender.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
#include <cstddef>
 | 
			
		||||
#include <glad/gl.h>
 | 
			
		||||
#include <logger/logger.hpp>
 | 
			
		||||
#include <renderer/gl/buffers.hpp>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
#include <glad/gl.h>
 | 
			
		||||
#include <renderer/gl/framebuffers.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
#include <glad/gl.h>
 | 
			
		||||
#include <input/events/window.hpp>
 | 
			
		||||
#include <renderer/blender.hpp> // required for forward declaratio>
 | 
			
		||||
#include <renderer/buffers.hpp> // required for forward declaratio>
 | 
			
		||||
| 
						 | 
				
			
			@ -6,18 +5,11 @@
 | 
			
		|||
#include <renderer/render_command.hpp> // required for forward declaratio>
 | 
			
		||||
#include <renderer/renderer.hpp>       // required for forward declaratio>
 | 
			
		||||
 | 
			
		||||
#ifndef STOP_FUCKING_ORDERING_THESE_THE_WRONG_WAY_CLANG_FORMAT____
 | 
			
		||||
	#include <GLFW/glfw3.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
glGraphicsContext::glGraphicsContext(GLFWwindow *windowHandle): m_window_handle(windowHandle)
 | 
			
		||||
glGraphicsContext::glGraphicsContext()
 | 
			
		||||
{
 | 
			
		||||
	m_graphics_api = GraphicsAPI::OpenGL;
 | 
			
		||||
	glfwMakeContextCurrent(windowHandle);
 | 
			
		||||
	ensure(gladLoadGL(glfwGetProcAddress), "Failed to initialize opengl (glad)");
 | 
			
		||||
 | 
			
		||||
	set_debug_message_callback();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,20 +3,16 @@
 | 
			
		|||
 | 
			
		||||
#include <renderer/graphics_context.hpp>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class glGraphicsContext: public GraphicsContext
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	glGraphicsContext(GLFWwindow *windowHandle);
 | 
			
		||||
	glGraphicsContext();
 | 
			
		||||
 | 
			
		||||
	void log_debug_data() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLFWwindow *m_window_handle;
 | 
			
		||||
 | 
			
		||||
	void set_debug_message_callback();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,13 @@
 | 
			
		|||
#include <glad/gl.h>
 | 
			
		||||
#include <renderer/gl/render_command.hpp>
 | 
			
		||||
#ifndef DONT_FUCKING_ORDER_THESSE_PLEASE_FOR_THE_LOVE_OF_GOD_CLANG_FORMAT
 | 
			
		||||
	#include <GLFW/glfw3.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
glRenderCommand::glRenderCommand(GLFWwindow *windowHandle): m_window_handle(windowHandle)
 | 
			
		||||
glRenderCommand::glRenderCommand(): m_window_handle(windowHandle)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void glRenderCommand::swap_buffers()
 | 
			
		||||
{
 | 
			
		||||
	glfwSwapBuffers(m_window_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void glRenderCommand::clear_back_buffer(const math::vec4 &clearColor)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,14 +3,12 @@
 | 
			
		|||
#include <math/vec4.hpp>
 | 
			
		||||
#include <renderer/render_command.hpp>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class glRenderCommand: public RenderCommand
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	glRenderCommand(GLFWwindow *windowHandle);
 | 
			
		||||
	glRenderCommand();
 | 
			
		||||
 | 
			
		||||
	void swap_buffers() override;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,9 +26,6 @@ public:
 | 
			
		|||
	    unsigned int width,
 | 
			
		||||
	    unsigned int height
 | 
			
		||||
	) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLFWwindow *m_window_handle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,4 @@
 | 
			
		|||
#include <asset_parser/assets/text.hpp>
 | 
			
		||||
#include <glad/gl.h>
 | 
			
		||||
#include <renderer/gl/shader.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
#include <asset_parser/assets/texture.hpp>
 | 
			
		||||
#include <glad/gl.h>
 | 
			
		||||
#include <lt_debug/assertions.hpp>
 | 
			
		||||
#include <renderer/gl/texture.hpp>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,8 +3,6 @@
 | 
			
		|||
 | 
			
		||||
#include <ui/ui.hpp>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class glUserInterface: public UserInterface
 | 
			
		||||
| 
						 | 
				
			
			@ -14,19 +12,13 @@ public:
 | 
			
		|||
 | 
			
		||||
	~glUserInterface() override;
 | 
			
		||||
 | 
			
		||||
	void platform_implementation(
 | 
			
		||||
	    GLFWwindow *windowHandle,
 | 
			
		||||
	    Ref<SharedContext> sharedContext
 | 
			
		||||
	) override;
 | 
			
		||||
	void platform_implementation(Ref<SharedContext> sharedContext) override;
 | 
			
		||||
 | 
			
		||||
	void begin() override;
 | 
			
		||||
 | 
			
		||||
	void end() override;
 | 
			
		||||
 | 
			
		||||
	void log_debug_data() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLFWwindow *m_window_handle {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
#include <glad/gl.h>
 | 
			
		||||
#include <lt_debug/assertions.hpp>
 | 
			
		||||
#include <renderer/gl/buffers.hpp>
 | 
			
		||||
#include <renderer/gl/vertex_layout.hpp>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ GraphicsContext *GraphicsContext::s_context = nullptr;
 | 
			
		|||
 | 
			
		||||
GraphicsContext::~GraphicsContext() = default;
 | 
			
		||||
 | 
			
		||||
auto GraphicsContext::create(GraphicsAPI api, GLFWwindow *window_handle) -> Scope<GraphicsContext>
 | 
			
		||||
auto GraphicsContext::create(GraphicsAPI api) -> Scope<GraphicsContext>
 | 
			
		||||
{
 | 
			
		||||
	delete s_context;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,12 +11,11 @@
 | 
			
		|||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
auto RenderCommand::create(GLFWwindow *windowHandle, const Ref<SharedContext> & /*sharedContext*/)
 | 
			
		||||
    -> Scope<RenderCommand>
 | 
			
		||||
auto RenderCommand::create(const Ref<SharedContext> & /*sharedContext*/) -> Scope<RenderCommand>
 | 
			
		||||
{
 | 
			
		||||
	switch (GraphicsContext::get_graphics_api())
 | 
			
		||||
	{
 | 
			
		||||
	case GraphicsAPI::OpenGL: return create_scope<glRenderCommand>(windowHandle);
 | 
			
		||||
	case GraphicsAPI::OpenGL: return create_scope<glRenderCommand>();
 | 
			
		||||
 | 
			
		||||
	case GraphicsAPI::DirectX:
 | 
			
		||||
		lt_win(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,11 +16,7 @@ namespace lt {
 | 
			
		|||
 | 
			
		||||
Renderer *Renderer::s_context = nullptr;
 | 
			
		||||
 | 
			
		||||
Renderer::Renderer(
 | 
			
		||||
    GLFWwindow *window_handle,
 | 
			
		||||
    const Ref<SharedContext> &shared_context,
 | 
			
		||||
    CreateInfo create_info
 | 
			
		||||
)
 | 
			
		||||
Renderer::Renderer(const Ref<SharedContext> &shared_context, CreateInfo create_info)
 | 
			
		||||
    : m_quad_renderer(
 | 
			
		||||
          create_scope<QuadRendererProgram>(
 | 
			
		||||
              LT_MAX_QUAD_RENDERER_VERTICES,
 | 
			
		||||
| 
						 | 
				
			
			@ -66,15 +62,9 @@ Renderer::~Renderer() // NOLINT
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Renderer::create(
 | 
			
		||||
    GLFWwindow *windowHandle,
 | 
			
		||||
    Ref<SharedContext> sharedContext,
 | 
			
		||||
    CreateInfo create_info
 | 
			
		||||
) -> Scope<Renderer>
 | 
			
		||||
auto Renderer::create(Ref<SharedContext> sharedContext, CreateInfo create_info) -> Scope<Renderer>
 | 
			
		||||
{
 | 
			
		||||
	return make_scope<Renderer>(
 | 
			
		||||
	    new Renderer(windowHandle, std::move(sharedContext), std::move(create_info))
 | 
			
		||||
	);
 | 
			
		||||
	return make_scope<Renderer>(new Renderer(std::move(sharedContext), std::move(create_info)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Renderer::on_window_resize(const WindowResizedEvent &event)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,6 @@ namespace lt::renderer {
 | 
			
		|||
System::System(InitRequirements requirements): m_registry(std::move(requirements.registry))
 | 
			
		||||
{
 | 
			
		||||
	ensure(m_registry, "null registry");
 | 
			
		||||
	ensure(requirements.glfw_window_handle, "null glfw handle");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
System::~System() = default;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,11 +13,8 @@ Suite raii = [] {
 | 
			
		|||
	using lt::test::expect_throw;
 | 
			
		||||
	using renderer::System;
 | 
			
		||||
 | 
			
		||||
	auto *window = static_cast<GLFWwindow *>(lt::Window::create([](auto &&PH1) {})->get_handle());
 | 
			
		||||
 | 
			
		||||
	Case { "happy" } = [=] {
 | 
			
		||||
		std::ignore = System { {
 | 
			
		||||
			.glfw_window_handle = window,
 | 
			
		||||
			.registry = create_ref<ecs::Registry>(),
 | 
			
		||||
		} };
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			@ -25,14 +22,12 @@ Suite raii = [] {
 | 
			
		|||
	Case { "unhappy" } = [=] {
 | 
			
		||||
		expect_throw([=] {
 | 
			
		||||
			std::ignore = System { {
 | 
			
		||||
				.glfw_window_handle = window,
 | 
			
		||||
				.registry = {},
 | 
			
		||||
			} };
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		expect_throw([=] {
 | 
			
		||||
			std::ignore = System { {
 | 
			
		||||
				.glfw_window_handle = {},
 | 
			
		||||
				.registry = create_ref<ecs::Registry>(),
 | 
			
		||||
			} };
 | 
			
		||||
		});
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +37,6 @@ Suite raii = [] {
 | 
			
		|||
		for (auto idx : std::views::iota(0, 100'001))
 | 
			
		||||
		{
 | 
			
		||||
			std::ignore = System { {
 | 
			
		||||
				.glfw_window_handle = window,
 | 
			
		||||
				.registry = create_ref<ecs::Registry>(),
 | 
			
		||||
			} };
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,5 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class SharedContext;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,12 +17,7 @@ enum class GraphicsAPI
 | 
			
		|||
class GraphicsContext
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static auto create(
 | 
			
		||||
	    GraphicsAPI api,
 | 
			
		||||
	    GLFWwindow *window_handle
 | 
			
		||||
 | 
			
		||||
	) -> Scope<GraphicsContext>;
 | 
			
		||||
 | 
			
		||||
	static auto create(GraphicsAPI api) -> Scope<GraphicsContext>;
 | 
			
		||||
	GraphicsContext(const GraphicsContext &) = delete;
 | 
			
		||||
 | 
			
		||||
	GraphicsContext &operator=(const GraphicsContext &) = delete;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,6 @@
 | 
			
		|||
 | 
			
		||||
#include <math/vec4.hpp>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class SharedContext;
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +9,7 @@ class SharedContext;
 | 
			
		|||
class RenderCommand
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static auto create(GLFWwindow *windowHandle, const Ref<SharedContext> &sharedContext)
 | 
			
		||||
	    -> Scope<RenderCommand>;
 | 
			
		||||
	static auto create(const Ref<SharedContext> &sharedContext) -> Scope<RenderCommand>;
 | 
			
		||||
 | 
			
		||||
	RenderCommand(const RenderCommand &) = delete;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,8 +13,6 @@
 | 
			
		|||
#define LT_MAX_TEXTURE_RENDERER_VERTICES        (1028u * 4u)
 | 
			
		||||
#define LT_MAX_TINTED_TEXTURE_RENDERER_VERTICES (1028u * 4u)
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class ConstantBuffer;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,11 +40,7 @@ public:
 | 
			
		|||
		Ref<Shader> tinted_texture_renderer_shader;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static auto create(
 | 
			
		||||
	    GLFWwindow *windowHandle,
 | 
			
		||||
	    Ref<SharedContext> sharedContext,
 | 
			
		||||
	    CreateInfo create_info
 | 
			
		||||
	) -> Scope<Renderer>;
 | 
			
		||||
	static auto create(Ref<SharedContext> sharedContext, CreateInfo create_info) -> Scope<Renderer>;
 | 
			
		||||
 | 
			
		||||
	static void draw_quad(
 | 
			
		||||
	    const math::vec3 &position,
 | 
			
		||||
| 
						 | 
				
			
			@ -134,11 +128,7 @@ private:
 | 
			
		|||
 | 
			
		||||
	bool m_should_clear_backbuffer { false };
 | 
			
		||||
 | 
			
		||||
	Renderer(
 | 
			
		||||
	    GLFWwindow *window_handle,
 | 
			
		||||
	    const Ref<SharedContext> &shared_context,
 | 
			
		||||
	    CreateInfo create_info
 | 
			
		||||
	);
 | 
			
		||||
	Renderer(const Ref<SharedContext> &shared_context, CreateInfo create_info);
 | 
			
		||||
 | 
			
		||||
	void draw_quad_impl(
 | 
			
		||||
	    const math::vec3 &position,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,8 +3,6 @@
 | 
			
		|||
#include <base/base.hpp>
 | 
			
		||||
#include <ecs/scene.hpp>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt::renderer {
 | 
			
		||||
 | 
			
		||||
/** The system for putting gore on your display
 | 
			
		||||
| 
						 | 
				
			
			@ -28,8 +26,6 @@ public:
 | 
			
		|||
	/** The requirements for this system to initialize. */
 | 
			
		||||
	struct InitRequirements
 | 
			
		||||
	{
 | 
			
		||||
		GLFWwindow *glfw_window_handle;
 | 
			
		||||
 | 
			
		||||
		Ref<ecs::Registry> registry;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@
 | 
			
		|||
namespace Assets {
 | 
			
		||||
 | 
			
		||||
class TextureAsset;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,16 @@
 | 
			
		|||
if (NOT WIN32)
 | 
			
		||||
    add_library_module(surface linux/system.cpp)
 | 
			
		||||
    target_link_libraries(surface PRIVATE X11)
 | 
			
		||||
 | 
			
		||||
else(WIN32)
 | 
			
		||||
    add_library_module(surface windows/system.cpp)
 | 
			
		||||
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
target_link_libraries(surface PUBLIC 
 | 
			
		||||
    ecs
 | 
			
		||||
    app
 | 
			
		||||
    PRIVATE
 | 
			
		||||
    glfw
 | 
			
		||||
    logger 
 | 
			
		||||
    lt_debug
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,143 +1,42 @@
 | 
			
		|||
#define GLFW_EXPOSE_NATIVE_X11
 | 
			
		||||
#include <GLFW/glfw3.h>
 | 
			
		||||
#include <GLFW/glfw3native.h>
 | 
			
		||||
#include <ecs/components.hpp>
 | 
			
		||||
#include <surface/components.hpp>
 | 
			
		||||
#include <surface/events/mouse.hpp>
 | 
			
		||||
#include <surface/requests/surface.hpp>
 | 
			
		||||
#include <surface/system.hpp>
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
#include <X11/Xutil.h>
 | 
			
		||||
#include <X11/keysym.h>
 | 
			
		||||
#include <X11/keysymdef.h>
 | 
			
		||||
 | 
			
		||||
namespace lt::surface {
 | 
			
		||||
 | 
			
		||||
// This class is to ensure glfwInit/glfwTerminate is called only once and exactly when needed during
 | 
			
		||||
// entire application runtime
 | 
			
		||||
class GlfwSingleton
 | 
			
		||||
template<class... Ts>
 | 
			
		||||
struct overloads: Ts...
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	[[nodiscard]] static auto get() -> GlfwSingleton &
 | 
			
		||||
	{
 | 
			
		||||
		static auto instance = GlfwSingleton {};
 | 
			
		||||
		return instance;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GlfwSingleton(GlfwSingleton &&) = delete;
 | 
			
		||||
 | 
			
		||||
	GlfwSingleton(const GlfwSingleton &) = delete;
 | 
			
		||||
 | 
			
		||||
	auto operator=(GlfwSingleton &&) -> GlfwSingleton & = delete;
 | 
			
		||||
 | 
			
		||||
	auto operator=(const GlfwSingleton &) -> GlfwSingleton & = delete;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GlfwSingleton()
 | 
			
		||||
	{
 | 
			
		||||
		log_inf("Initializing glfw...");
 | 
			
		||||
		ensure(glfwInit(), "Failed to initialize 'glfw'");
 | 
			
		||||
		log_inf("...Finished");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~GlfwSingleton()
 | 
			
		||||
	{
 | 
			
		||||
		log_inf("Terminating glfw...");
 | 
			
		||||
		glfwTerminate();
 | 
			
		||||
		log_inf("...Finished");
 | 
			
		||||
	}
 | 
			
		||||
	using Ts::operator()...;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void glfw_error_callbac(int32_t code, const char *description)
 | 
			
		||||
{
 | 
			
		||||
	log_err("GLFW ERROR: {} -> {}", code, description);
 | 
			
		||||
}
 | 
			
		||||
void ensure_component_sanity(const SurfaceComponent &component);
 | 
			
		||||
 | 
			
		||||
void handle_event(GLFWwindow *window, const SurfaceComponent::Event &event)
 | 
			
		||||
{
 | 
			
		||||
	auto &callbacks = *static_cast<std::vector<SurfaceComponent::EventCallback> *>(
 | 
			
		||||
	    glfwGetWindowUserPointer(window)
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	for (auto &callback : callbacks)
 | 
			
		||||
	{
 | 
			
		||||
		if (callback(event))
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bind_glfw_events(GLFWwindow *handle)
 | 
			
		||||
{
 | 
			
		||||
	glfwSetWindowPosCallback(handle, [](GLFWwindow *window, int xpos, int ypos) {
 | 
			
		||||
		handle_event(window, MovedEvent { xpos, ypos });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowSizeCallback(handle, [](GLFWwindow *window, int width, int height) {
 | 
			
		||||
		handle_event(
 | 
			
		||||
		    window,
 | 
			
		||||
		    ResizedEvent { static_cast<uint32_t>(width), static_cast<uint32_t>(height) }
 | 
			
		||||
		);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowCloseCallback(handle, [](GLFWwindow *window) {
 | 
			
		||||
		handle_event(window, ClosedEvent {});
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowFocusCallback(handle, [](GLFWwindow *window, int focus) {
 | 
			
		||||
		if (focus == GLFW_TRUE)
 | 
			
		||||
		{
 | 
			
		||||
			handle_event(window, GainFocusEvent {});
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			handle_event(window, LostFocusEvent {});
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetCursorPosCallback(handle, [](GLFWwindow *window, double xpos, double ypos) {
 | 
			
		||||
		handle_event(
 | 
			
		||||
		    window,
 | 
			
		||||
		    MouseMovedEvent { static_cast<float>(xpos), static_cast<float>(ypos) }
 | 
			
		||||
		);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetMouseButtonCallback(
 | 
			
		||||
	    handle,
 | 
			
		||||
	    [](GLFWwindow *window, int button, int action, int /*mods*/) {
 | 
			
		||||
		    if (action == GLFW_PRESS)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, ButtonPressedEvent { button });
 | 
			
		||||
		    }
 | 
			
		||||
		    else if (action == GLFW_RELEASE)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, ButtonReleasedEvent { button });
 | 
			
		||||
		    }
 | 
			
		||||
	    }
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	glfwSetScrollCallback(handle, [](GLFWwindow *window, double /*xoffset*/, double yoffset) {
 | 
			
		||||
		handle_event(window, WheelScrolledEvent { static_cast<float>(yoffset) });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetKeyCallback(
 | 
			
		||||
	    handle,
 | 
			
		||||
	    [](GLFWwindow *window, int key, int /*scancode*/, int action, int /*mods*/) {
 | 
			
		||||
		    if (action == GLFW_PRESS)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, KeyPressedEvent { key });
 | 
			
		||||
		    }
 | 
			
		||||
		    else if (action == GLFW_RELEASE)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, KeyReleasedEvent { key });
 | 
			
		||||
		    }
 | 
			
		||||
	    }
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	glfwSetCharCallback(handle, [](GLFWwindow *window, unsigned int character) {
 | 
			
		||||
		handle_event(window, KeySetCharEvent { character });
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
constexpr auto all_events_mask = KeyPressMask |         //
 | 
			
		||||
                                 KeyReleaseMask |       //
 | 
			
		||||
                                 ButtonPressMask |      //
 | 
			
		||||
                                 ButtonReleaseMask |    //
 | 
			
		||||
                                 EnterWindowMask |      //
 | 
			
		||||
                                 LeaveWindowMask |      //
 | 
			
		||||
                                 PointerMotionMask |    //
 | 
			
		||||
                                 KeymapStateMask |      //
 | 
			
		||||
                                 ExposureMask |         //
 | 
			
		||||
                                 VisibilityChangeMask | //
 | 
			
		||||
                                 StructureNotifyMask |  //
 | 
			
		||||
                                 FocusChangeMask |      //
 | 
			
		||||
                                 ColormapChangeMask |   //
 | 
			
		||||
                                 OwnerGrabButtonMask;
 | 
			
		||||
 | 
			
		||||
System::System(Ref<ecs::Registry> registry): m_registry(std::move(registry))
 | 
			
		||||
{
 | 
			
		||||
	glfwSetErrorCallback(&glfw_error_callbac);
 | 
			
		||||
 | 
			
		||||
	// will call `glfwInit()` only the first time
 | 
			
		||||
	auto &glfw_instance = GlfwSingleton::get();
 | 
			
		||||
	ensure(m_registry, "Failed to initialize surface system: null registry");
 | 
			
		||||
 | 
			
		||||
	ensure(
 | 
			
		||||
| 
						 | 
				
			
			@ -178,29 +77,94 @@ System::~System()
 | 
			
		|||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_register()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_unregister()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_surface_construct(entt::registry ®istry, entt::entity entity)
 | 
			
		||||
{
 | 
			
		||||
	try
 | 
			
		||||
	{
 | 
			
		||||
		auto &surface = registry.get<SurfaceComponent>(entity);
 | 
			
		||||
		const auto &resolution = surface.get_resolution();
 | 
			
		||||
		const auto &position = surface.get_position();
 | 
			
		||||
		ensure_component_sanity(surface);
 | 
			
		||||
 | 
			
		||||
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
 | 
			
		||||
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
 | 
			
		||||
		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 | 
			
		||||
		// 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!");
 | 
			
		||||
 | 
			
		||||
		surface.m_glfw_handle = glfwCreateWindow(
 | 
			
		||||
		    static_cast<int>(surface.get_resolution().x),
 | 
			
		||||
		    static_cast<int>(surface.get_resolution().y),
 | 
			
		||||
		    surface.get_title().begin(),
 | 
			
		||||
		    nullptr,
 | 
			
		||||
		    nullptr
 | 
			
		||||
		auto *display = XOpenDisplay(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
 | 
			
		||||
		{
 | 
			
		||||
			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
 | 
			
		||||
		);
 | 
			
		||||
		ensure(surface.m_glfw_handle, "Failed to create 'GLFWwindow'");
 | 
			
		||||
		surface.m_native_data.display = display;
 | 
			
		||||
		surface.m_native_data.window = main_window;
 | 
			
		||||
 | 
			
		||||
		glfwSetWindowUserPointer(surface.m_glfw_handle, &surface.m_event_callbacks);
 | 
			
		||||
		surface.m_native_handle = glfwGetX11Window(surface.m_glfw_handle);
 | 
			
		||||
		bind_glfw_events(surface.m_glfw_handle);
 | 
			
		||||
		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
 | 
			
		||||
		long hints[5] = { 2, 0, 0, 0, 0 };
 | 
			
		||||
		Atom motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
 | 
			
		||||
 | 
			
		||||
		XChangeProperty(
 | 
			
		||||
		    display,
 | 
			
		||||
		    surface.m_native_data.window,
 | 
			
		||||
		    motif_hints,
 | 
			
		||||
		    motif_hints,
 | 
			
		||||
		    32,
 | 
			
		||||
		    PropModeReplace,
 | 
			
		||||
		    (unsigned char *)&hints,
 | 
			
		||||
		    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 (...)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -212,82 +176,213 @@ void System::on_surface_construct(entt::registry ®istry, entt::entity entity)
 | 
			
		|||
void System::on_surface_update(entt::registry ®istry, entt::entity entity)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = registry.get<SurfaceComponent>(entity);
 | 
			
		||||
	glfwSetWindowUserPointer(surface.m_glfw_handle, &surface.m_event_callbacks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_surface_destroy(entt::registry ®istry, entt::entity entity)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = registry.get<SurfaceComponent>(entity);
 | 
			
		||||
 | 
			
		||||
	if (surface.m_glfw_handle)
 | 
			
		||||
	const auto &[display, window, _] = registry.get<SurfaceComponent>(entity).get_native_data();
 | 
			
		||||
	if (!display)
 | 
			
		||||
	{
 | 
			
		||||
		glfwDestroyWindow(surface.m_glfw_handle);
 | 
			
		||||
		log_wrn("Surface component destroyed with null display");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	XDestroyWindow(display, window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::handle_events(SurfaceComponent &surface)
 | 
			
		||||
{
 | 
			
		||||
	auto &queue = surface.m_event_queue;
 | 
			
		||||
	queue.clear();
 | 
			
		||||
 | 
			
		||||
	auto event = XEvent {};
 | 
			
		||||
	auto &[display, window, wm_delete_message] = surface.m_native_data;
 | 
			
		||||
 | 
			
		||||
	XFlush(display);
 | 
			
		||||
	while (XEventsQueued(display, QueuedAlready) != 0)
 | 
			
		||||
	{
 | 
			
		||||
		XNextEvent(surface.m_native_data.display, &event);
 | 
			
		||||
 | 
			
		||||
		switch (event.type)
 | 
			
		||||
		{
 | 
			
		||||
		case KeyPress:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<KeyPressedEvent>(
 | 
			
		||||
			    static_cast<uint32_t>(XLookupKeysym(&event.xkey, 0))
 | 
			
		||||
			);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case KeyRelease:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<KeyReleasedEvent>(
 | 
			
		||||
			    static_cast<uint32_t>(XLookupKeysym(&event.xkey, 0))
 | 
			
		||||
			);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case ButtonPress:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<ButtonPressedEvent>(static_cast<int>(event.xbutton.button));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case ButtonRelease:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<ButtonReleasedEvent>(static_cast<int>(event.xbutton.button));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case FocusIn:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<GainFocusEvent>({});
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case FocusOut:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<LostFocusEvent>({});
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case ClientMessage:
 | 
			
		||||
		{
 | 
			
		||||
			if (event.xclient.data.l[0] == wm_delete_message)
 | 
			
		||||
			{
 | 
			
		||||
				queue.emplace_back<ClosedEvent>({});
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case MotionNotify:
 | 
			
		||||
		{
 | 
			
		||||
			queue.emplace_back<MouseMovedEvent>(MouseMovedEvent {
 | 
			
		||||
			    static_cast<float>(event.xmotion.x),
 | 
			
		||||
			    static_cast<float>(event.xmotion.y),
 | 
			
		||||
			});
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case ConfigureNotify:
 | 
			
		||||
		{
 | 
			
		||||
			const auto [prev_width, prev_height] = surface.get_resolution();
 | 
			
		||||
			const auto new_width = event.xconfigure.width;
 | 
			
		||||
			const auto new_height = event.xconfigure.height;
 | 
			
		||||
			if (prev_width != new_width || prev_height != new_height)
 | 
			
		||||
			{
 | 
			
		||||
				surface.m_resolution.x = new_width;
 | 
			
		||||
				surface.m_resolution.y = new_height;
 | 
			
		||||
				queue.emplace_back<ResizedEvent>(ResizedEvent {
 | 
			
		||||
				    static_cast<uint32_t>(new_width),
 | 
			
		||||
				    static_cast<uint32_t>(new_height),
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			const auto [prev_x, prev_y] = surface.get_position();
 | 
			
		||||
			const auto new_x = event.xconfigure.x;
 | 
			
		||||
			const auto new_y = event.xconfigure.y;
 | 
			
		||||
			if (prev_x != new_x || prev_y != new_y)
 | 
			
		||||
			{
 | 
			
		||||
				surface.m_position.x = new_x;
 | 
			
		||||
				surface.m_position.y = new_y;
 | 
			
		||||
				queue.emplace_back<MovedEvent>(MovedEvent {
 | 
			
		||||
				    new_x,
 | 
			
		||||
				    new_y,
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case Expose: break;
 | 
			
		||||
		case GraphicsExpose: break;
 | 
			
		||||
		case NoExpose: break;
 | 
			
		||||
		case CirculateRequest: break;
 | 
			
		||||
		case ConfigureRequest: break;
 | 
			
		||||
		case MapRequest: break;
 | 
			
		||||
		case ResizeRequest: break;
 | 
			
		||||
		case CirculateNotify: break;
 | 
			
		||||
		case CreateNotify: break;
 | 
			
		||||
		case DestroyNotify: break;
 | 
			
		||||
		case GravityNotify: break;
 | 
			
		||||
		case MapNotify: break;
 | 
			
		||||
		case MappingNotify: break;
 | 
			
		||||
		case ReparentNotify: break;
 | 
			
		||||
		case UnmapNotify: break;
 | 
			
		||||
		case VisibilityNotify: break;
 | 
			
		||||
		case ColormapNotify: break;
 | 
			
		||||
		case PropertyNotify: break;
 | 
			
		||||
		case SelectionClear: break;
 | 
			
		||||
		case SelectionNotify: break;
 | 
			
		||||
		case SelectionRequest: break;
 | 
			
		||||
		default: log_inf("Unknown X Event");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_title(ecs::Entity entity, std::string_view new_title)
 | 
			
		||||
void System::handle_requests(SurfaceComponent &surface)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = entity.get_component<SurfaceComponent>();
 | 
			
		||||
	const auto visitor = overloads {
 | 
			
		||||
		[&](const ModifyTitleRequest &request) { modify_title(surface, request); },
 | 
			
		||||
		[&](const ModifyResolutionRequest &request) { modify_resolution(surface, request); },
 | 
			
		||||
		[&](const ModifyPositionRequest &request) { modify_position(surface, request); },
 | 
			
		||||
		[&](const ModifyVisibilityRequest &request) { modify_visiblity(surface, request); },
 | 
			
		||||
		[&](const auto &) { log_err("Unknown surface request"); },
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	surface.m_title = new_title;
 | 
			
		||||
	glfwSetWindowTitle(surface.m_glfw_handle, surface.m_title.c_str());
 | 
			
		||||
	for (const auto &request : surface.peek_requests())
 | 
			
		||||
	{
 | 
			
		||||
		std::visit(visitor, request);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	surface.m_requests.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::modify_title(SurfaceComponent &surface, const ModifyTitleRequest &request)
 | 
			
		||||
{
 | 
			
		||||
	surface.m_title = request.title;
 | 
			
		||||
 | 
			
		||||
	const auto &[display, window, _] = surface.get_native_data();
 | 
			
		||||
	XStoreName(display, window, request.title.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::modify_resolution(SurfaceComponent &surface, const ModifyResolutionRequest &request)
 | 
			
		||||
{
 | 
			
		||||
	surface.m_resolution = request.resolution;
 | 
			
		||||
 | 
			
		||||
	const auto &[display, window, _] = surface.get_native_data();
 | 
			
		||||
	const auto &[width, height] = request.resolution;
 | 
			
		||||
	XResizeWindow(display, window, width, height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::modify_position(SurfaceComponent &surface, const ModifyPositionRequest &request)
 | 
			
		||||
{
 | 
			
		||||
	surface.m_position = request.position;
 | 
			
		||||
 | 
			
		||||
	const auto &[display, window, _] = surface.get_native_data();
 | 
			
		||||
	const auto &[x, y] = request.position;
 | 
			
		||||
	XMoveWindow(display, window, static_cast<int>(x), static_cast<int>(y));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::modify_visiblity(SurfaceComponent &surface, const ModifyVisibilityRequest &request)
 | 
			
		||||
{
 | 
			
		||||
	const auto &[display, window, _] = surface.get_native_data();
 | 
			
		||||
	surface.m_visible = request.visible;
 | 
			
		||||
 | 
			
		||||
	if (request.visible)
 | 
			
		||||
	{
 | 
			
		||||
		XMapWindow(display, window);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		XUnmapWindow(display, window);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto System::tick() -> bool
 | 
			
		||||
{
 | 
			
		||||
	m_registry->view<SurfaceComponent>().each([](SurfaceComponent &surface) {
 | 
			
		||||
		glfwSwapBuffers(surface.m_glfw_handle);
 | 
			
		||||
	m_registry->view<SurfaceComponent>().each([this](SurfaceComponent &surface) {
 | 
			
		||||
		handle_requests(surface);
 | 
			
		||||
 | 
			
		||||
		handle_events(surface);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwPollEvents();
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_size(ecs::Entity surface_entity, const math::uvec2 &new_size)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_resolution = new_size;
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowSize(
 | 
			
		||||
	    surface.m_glfw_handle,
 | 
			
		||||
	    static_cast<int>(new_size.x),
 | 
			
		||||
	    static_cast<int>(new_size.y)
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_v_sync(ecs::Entity surface_entity, bool vsync)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_vsync = vsync;
 | 
			
		||||
 | 
			
		||||
	glfwSwapInterval(vsync);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_visibility(ecs::Entity surface_entity, bool visible)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_visible = visible;
 | 
			
		||||
 | 
			
		||||
	if (visible)
 | 
			
		||||
	{
 | 
			
		||||
		glfwShowWindow(surface.m_glfw_handle);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		glfwHideWindow(surface.m_glfw_handle);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::add_event_listener(
 | 
			
		||||
    ecs::Entity surface_entity,
 | 
			
		||||
    SurfaceComponent::EventCallback callback
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_event_callbacks.emplace_back(std::move(callback));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::ensure_component_sanity(const SurfaceComponent &component)
 | 
			
		||||
void ensure_component_sanity(const SurfaceComponent &component)
 | 
			
		||||
{
 | 
			
		||||
	auto [width, height] = component.get_resolution();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,13 @@
 | 
			
		|||
#include <ecs/entity.hpp>
 | 
			
		||||
#include <ecs/scene.hpp>
 | 
			
		||||
#include <surface/components.hpp>
 | 
			
		||||
#include <surface/system.hpp>
 | 
			
		||||
#include <test/fuzz.hpp>
 | 
			
		||||
#include <test/test.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt::surface {
 | 
			
		||||
 | 
			
		||||
enum class Action : uint8_t
 | 
			
		||||
enum class FuzzAction : uint8_t
 | 
			
		||||
{
 | 
			
		||||
	create_entity,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +15,22 @@ enum class Action : uint8_t
 | 
			
		|||
 | 
			
		||||
	destroy_surface_component,
 | 
			
		||||
 | 
			
		||||
	tick,
 | 
			
		||||
	push_request,
 | 
			
		||||
 | 
			
		||||
	push_event,
 | 
			
		||||
 | 
			
		||||
	tick_system,
 | 
			
		||||
 | 
			
		||||
	count,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class EventType : uint8_t
 | 
			
		||||
{
 | 
			
		||||
	Closed,
 | 
			
		||||
	Moved,
 | 
			
		||||
	Resized,
 | 
			
		||||
	LostFocus,
 | 
			
		||||
	GainFocus,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void create_surface_component(test::FuzzDataProvider &provider, ecs::Registry ®istry)
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +72,14 @@ void remove_surface_component(ecs::Registry ®istry)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void push_request(ecs::Registry ®istry)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void push_event(ecs::Registry ®istry)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void check_invariants()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -67,9 +92,14 @@ test::FuzzHarness harness = [](const uint8_t *data, size_t size) {
 | 
			
		|||
 | 
			
		||||
	while (auto action = provider.consume<uint8_t>())
 | 
			
		||||
	{
 | 
			
		||||
		switch (static_cast<Action>(action.value()))
 | 
			
		||||
		if (*action > std::to_underlying(FuzzAction::count))
 | 
			
		||||
		{
 | 
			
		||||
		case Action::create_entity:
 | 
			
		||||
			*action = *action % std::to_underlying(FuzzAction::count);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch (static_cast<FuzzAction>(action.value()))
 | 
			
		||||
		{
 | 
			
		||||
		case FuzzAction::create_entity:
 | 
			
		||||
		{
 | 
			
		||||
			const auto length = std::min(provider.consume<uint32_t>().value_or(16), 255u);
 | 
			
		||||
			const auto tag = provider.consume_string(length).value_or("");
 | 
			
		||||
| 
						 | 
				
			
			@ -77,17 +107,36 @@ test::FuzzHarness harness = [](const uint8_t *data, size_t size) {
 | 
			
		|||
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case Action::create_surface_component:
 | 
			
		||||
		case FuzzAction::create_surface_component:
 | 
			
		||||
		{
 | 
			
		||||
			create_surface_component(provider, *registry);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case Action::destroy_surface_component:
 | 
			
		||||
		case FuzzAction::destroy_surface_component:
 | 
			
		||||
		{
 | 
			
		||||
			remove_surface_component(*registry);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case Action::tick:
 | 
			
		||||
		case FuzzAction::push_event:
 | 
			
		||||
		{
 | 
			
		||||
			const auto view = registry->get_entt_registry().view<SurfaceComponent>();
 | 
			
		||||
 | 
			
		||||
			if (!view->empty())
 | 
			
		||||
			{
 | 
			
		||||
				view.each([&](auto entity, SurfaceComponent &surface) {
 | 
			
		||||
					provider.consume<uint8_t>().value_or(0);
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				registry->get_entt_registry().remove<SurfaceComponent>(*view.begin());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case FuzzAction::push_request:
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case FuzzAction::tick_system:
 | 
			
		||||
		{
 | 
			
		||||
			system.tick();
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
#include <ecs/entity.hpp>
 | 
			
		||||
#include <surface/components.hpp>
 | 
			
		||||
#include <surface/requests/surface.hpp>
 | 
			
		||||
#include <surface/system.hpp>
 | 
			
		||||
#include <test/test.hpp>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +21,13 @@ constexpr auto height = 600u;
 | 
			
		|||
constexpr auto vsync = true;
 | 
			
		||||
constexpr auto visible = false;
 | 
			
		||||
 | 
			
		||||
template<class... Ts>
 | 
			
		||||
struct overloads: Ts...
 | 
			
		||||
{
 | 
			
		||||
	using Ts::operator()...;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Fixture
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +51,11 @@ public:
 | 
			
		|||
 | 
			
		||||
	void check_values(const SurfaceComponent &component)
 | 
			
		||||
	{
 | 
			
		||||
		expect_ne(std::get<SurfaceComponent::X11NativeHandle>(component.get_native_handle()), 0);
 | 
			
		||||
#ifdef LIGHT_PLATFORM_LINUX
 | 
			
		||||
		expect_not_nullptr(component.get_native_data().display);
 | 
			
		||||
		expect_ne(component.get_native_data().window, 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		expect_eq(component.get_resolution().x, width);
 | 
			
		||||
		expect_eq(component.get_resolution().y, height);
 | 
			
		||||
		expect_eq(component.get_title(), title);
 | 
			
		||||
| 
						 | 
				
			
			@ -61,9 +75,7 @@ Suite raii = [] {
 | 
			
		|||
 | 
			
		||||
	Case { "many won't freeze/throw" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
 | 
			
		||||
		/* range is small since glfw init/terminate is slow. */
 | 
			
		||||
		for (auto idx : std::views::iota(0, 100))
 | 
			
		||||
		for (auto idx : std::views::iota(0, 250))
 | 
			
		||||
		{
 | 
			
		||||
			ignore = System { fixture.registry() };
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +86,7 @@ Suite raii = [] {
 | 
			
		|||
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		fixture.add_surface_component();
 | 
			
		||||
		expect_throw([&] { ignore = System { { fixture.registry() } }; });
 | 
			
		||||
		expect_throw([&] { ignore = System { fixture.registry() }; });
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Case { "post construct has correct state" } = [] {
 | 
			
		||||
| 
						 | 
				
			
			@ -107,8 +119,8 @@ Suite system_events = [] {
 | 
			
		|||
	Case { "on_unregister won't throw" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
		system.on_register();
 | 
			
		||||
 | 
			
		||||
		system.on_register();
 | 
			
		||||
		system.on_unregister();
 | 
			
		||||
		expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
 | 
			
		||||
	};
 | 
			
		||||
| 
						 | 
				
			
			@ -185,14 +197,73 @@ Suite tick = [] {
 | 
			
		|||
		fixture.add_surface_component();
 | 
			
		||||
		system.tick();
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
	Case { "ticking on chaotic registry won't throw" } = [] {
 | 
			
		||||
Suite tick_handles_events = [] {
 | 
			
		||||
	Case { "ticking clears previous tick's events" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
		auto &surface = fixture.add_surface_component();
 | 
			
		||||
 | 
			
		||||
		// flush window-creation events
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(surface.peek_events().size(), 0);
 | 
			
		||||
 | 
			
		||||
		surface.push_event(surface::MovedEvent({}, {}));
 | 
			
		||||
		expect_eq(surface.peek_events().size(), 1);
 | 
			
		||||
 | 
			
		||||
		surface.push_event(surface::ButtonPressedEvent({}));
 | 
			
		||||
		expect_eq(surface.peek_events().size(), 2);
 | 
			
		||||
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(surface.peek_events().size(), 0);
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Suite property_setters = [] {
 | 
			
		||||
Suite tick_handles_requests = [] {
 | 
			
		||||
	Case { "ticking clears requests" } = [] {
 | 
			
		||||
		auto fixture = Fixture {};
 | 
			
		||||
		auto system = System { fixture.registry() };
 | 
			
		||||
		auto &surface = fixture.add_surface_component();
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
		constexpr auto title = "ABC";
 | 
			
		||||
		constexpr auto position = math::ivec2 { 50, 50 };
 | 
			
		||||
		constexpr auto resolution = math::uvec2 { 50, 50 };
 | 
			
		||||
 | 
			
		||||
Suite listeners = [] {
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 0);
 | 
			
		||||
 | 
			
		||||
		surface.push_request(surface::ModifyVisibilityRequest(true));
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 1);
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 0);
 | 
			
		||||
 | 
			
		||||
		surface.push_request(surface::ModifyTitleRequest(title));
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 1);
 | 
			
		||||
 | 
			
		||||
		surface.push_request(surface::ModifyResolutionRequest(resolution));
 | 
			
		||||
		surface.push_request(surface::ModifyPositionRequest(position));
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 1 + 2);
 | 
			
		||||
 | 
			
		||||
		surface.push_request(surface::ModifyVisibilityRequest(false));
 | 
			
		||||
		surface.push_request(surface::ModifyVisibilityRequest(true));
 | 
			
		||||
		surface.push_request(surface::ModifyVisibilityRequest(false));
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 1 + 2 + 3);
 | 
			
		||||
 | 
			
		||||
		system.tick();
 | 
			
		||||
		expect_eq(surface.peek_requests().size(), 0);
 | 
			
		||||
 | 
			
		||||
		expect_eq(surface.get_title(), title);
 | 
			
		||||
		expect_eq(surface.get_position(), position);
 | 
			
		||||
		expect_eq(surface.get_resolution(), resolution);
 | 
			
		||||
 | 
			
		||||
		log_dbg("EVENT COUNT: {}", surface.peek_events().size());
 | 
			
		||||
		for (const auto &event : surface.peek_events())
 | 
			
		||||
		{
 | 
			
		||||
			const auto visitor = overloads {
 | 
			
		||||
				[&](auto event) { log_dbg("event: {}", event.to_string()); },
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			std::visit(visitor, event);
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,143 +1,12 @@
 | 
			
		|||
#define GLFW_EXPOSE_NATIVE_X11
 | 
			
		||||
#include <GLFW/glfw3.h>
 | 
			
		||||
#include <GLFW/glfw3native.h>
 | 
			
		||||
#include <surface/system.hpp>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace lt::surface {
 | 
			
		||||
 | 
			
		||||
// This class is to ensure glfwInit/glfwTerminate is called only once and exactly when needed during
 | 
			
		||||
// entire application runtime
 | 
			
		||||
class GlfwSingleton
 | 
			
		||||
System::System(Ref<ecs::Registry> registry, Ref<app::EventMediator> event_mediator)
 | 
			
		||||
    : m_registry(std::move(registry))
 | 
			
		||||
    , m_event_mediator(std::move(event_mediator))
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	[[nodiscard]] static auto get() -> GlfwSingleton &
 | 
			
		||||
	{
 | 
			
		||||
		static auto instance = GlfwSingleton {};
 | 
			
		||||
		return instance;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	GlfwSingleton(GlfwSingleton &&) = delete;
 | 
			
		||||
 | 
			
		||||
	GlfwSingleton(const GlfwSingleton &) = delete;
 | 
			
		||||
 | 
			
		||||
	auto operator=(GlfwSingleton &&) -> GlfwSingleton & = delete;
 | 
			
		||||
 | 
			
		||||
	auto operator=(const GlfwSingleton &) -> GlfwSingleton & = delete;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GlfwSingleton()
 | 
			
		||||
	{
 | 
			
		||||
		log_inf("Initializing glfw...");
 | 
			
		||||
		ensure(glfwInit(), "Failed to initialize 'glfw'");
 | 
			
		||||
		log_inf("...Finished");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~GlfwSingleton()
 | 
			
		||||
	{
 | 
			
		||||
		log_inf("Terminating glfw...");
 | 
			
		||||
		glfwTerminate();
 | 
			
		||||
		log_inf("...Finished");
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void glfw_error_callbac(int32_t code, const char *description)
 | 
			
		||||
{
 | 
			
		||||
	log_err("GLFW ERROR: {} -> {}", code, description);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void handle_event(GLFWwindow *window, const SurfaceComponent::Event &event)
 | 
			
		||||
{
 | 
			
		||||
	auto &callbacks = *static_cast<std::vector<SurfaceComponent::EventCallback> *>(
 | 
			
		||||
	    glfwGetWindowUserPointer(window)
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	for (auto &callback : callbacks)
 | 
			
		||||
	{
 | 
			
		||||
		if (callback(event))
 | 
			
		||||
		{
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bind_glfw_events(GLFWwindow *handle)
 | 
			
		||||
{
 | 
			
		||||
	glfwSetWindowPosCallback(handle, [](GLFWwindow *window, int xpos, int ypos) {
 | 
			
		||||
		handle_event(window, MovedEvent { xpos, ypos });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowSizeCallback(handle, [](GLFWwindow *window, int width, int height) {
 | 
			
		||||
		handle_event(
 | 
			
		||||
		    window,
 | 
			
		||||
		    ResizedEvent { static_cast<uint32_t>(width), static_cast<uint32_t>(height) }
 | 
			
		||||
		);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowCloseCallback(handle, [](GLFWwindow *window) {
 | 
			
		||||
		handle_event(window, ClosedEvent {});
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowFocusCallback(handle, [](GLFWwindow *window, int focus) {
 | 
			
		||||
		if (focus == GLFW_TRUE)
 | 
			
		||||
		{
 | 
			
		||||
			handle_event(window, GainFocusEvent {});
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			handle_event(window, LostFocusEvent {});
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetCursorPosCallback(handle, [](GLFWwindow *window, double xpos, double ypos) {
 | 
			
		||||
		handle_event(
 | 
			
		||||
		    window,
 | 
			
		||||
		    MouseMovedEvent { static_cast<float>(xpos), static_cast<float>(ypos) }
 | 
			
		||||
		);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetMouseButtonCallback(
 | 
			
		||||
	    handle,
 | 
			
		||||
	    [](GLFWwindow *window, int button, int action, int /*mods*/) {
 | 
			
		||||
		    if (action == GLFW_PRESS)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, ButtonPressedEvent { button });
 | 
			
		||||
		    }
 | 
			
		||||
		    else if (action == GLFW_RELEASE)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, ButtonReleasedEvent { button });
 | 
			
		||||
		    }
 | 
			
		||||
	    }
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	glfwSetScrollCallback(handle, [](GLFWwindow *window, double /*xoffset*/, double yoffset) {
 | 
			
		||||
		handle_event(window, WheelScrolledEvent { static_cast<float>(yoffset) });
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwSetKeyCallback(
 | 
			
		||||
	    handle,
 | 
			
		||||
	    [](GLFWwindow *window, int key, int /*scancode*/, int action, int /*mods*/) {
 | 
			
		||||
		    if (action == GLFW_PRESS)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, KeyPressedEvent { key });
 | 
			
		||||
		    }
 | 
			
		||||
		    else if (action == GLFW_RELEASE)
 | 
			
		||||
		    {
 | 
			
		||||
			    handle_event(window, KeyReleasedEvent { key });
 | 
			
		||||
		    }
 | 
			
		||||
	    }
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	glfwSetCharCallback(handle, [](GLFWwindow *window, unsigned int character) {
 | 
			
		||||
		handle_event(window, KeySetCharEvent { character });
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
System::System(Ref<ecs::Registry> registry): m_registry(std::move(registry))
 | 
			
		||||
{
 | 
			
		||||
	glfwSetErrorCallback(&glfw_error_callbac);
 | 
			
		||||
 | 
			
		||||
	// will call `glfwInit()` only the first time
 | 
			
		||||
	auto &glfw_instance = GlfwSingleton::get();
 | 
			
		||||
	ensure(m_registry, "Failed to initialize surface system: null registry");
 | 
			
		||||
 | 
			
		||||
	ensure(
 | 
			
		||||
| 
						 | 
				
			
			@ -183,24 +52,9 @@ void System::on_surface_construct(entt::registry ®istry, entt::entity entity)
 | 
			
		|||
	try
 | 
			
		||||
	{
 | 
			
		||||
		auto &surface = registry.get<SurfaceComponent>(entity);
 | 
			
		||||
		const auto &resolution = surface.get_resolution();
 | 
			
		||||
		const auto &position = surface.get_position();
 | 
			
		||||
		ensure_component_sanity(surface);
 | 
			
		||||
 | 
			
		||||
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
 | 
			
		||||
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
 | 
			
		||||
		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 | 
			
		||||
 | 
			
		||||
		surface.m_glfw_handle = glfwCreateWindow(
 | 
			
		||||
		    static_cast<int>(surface.get_resolution().x),
 | 
			
		||||
		    static_cast<int>(surface.get_resolution().y),
 | 
			
		||||
		    surface.get_title().begin(),
 | 
			
		||||
		    nullptr,
 | 
			
		||||
		    nullptr
 | 
			
		||||
		);
 | 
			
		||||
		ensure(surface.m_glfw_handle, "Failed to create 'GLFWwindow'");
 | 
			
		||||
 | 
			
		||||
		glfwSetWindowUserPointer(surface.m_glfw_handle, &surface.m_event_callbacks);
 | 
			
		||||
		surface.m_native_handle = glfwGetX11Window(surface.m_glfw_handle);
 | 
			
		||||
		bind_glfw_events(surface.m_glfw_handle);
 | 
			
		||||
	}
 | 
			
		||||
	catch (...)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -212,17 +66,11 @@ void System::on_surface_construct(entt::registry ®istry, entt::entity entity)
 | 
			
		|||
void System::on_surface_update(entt::registry ®istry, entt::entity entity)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = registry.get<SurfaceComponent>(entity);
 | 
			
		||||
	glfwSetWindowUserPointer(surface.m_glfw_handle, &surface.m_event_callbacks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::on_surface_destroy(entt::registry ®istry, entt::entity entity)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = registry.get<SurfaceComponent>(entity);
 | 
			
		||||
 | 
			
		||||
	if (surface.m_glfw_handle)
 | 
			
		||||
	{
 | 
			
		||||
		glfwDestroyWindow(surface.m_glfw_handle);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_title(ecs::Entity entity, std::string_view new_title)
 | 
			
		||||
| 
						 | 
				
			
			@ -230,16 +78,10 @@ void System::set_title(ecs::Entity entity, std::string_view new_title)
 | 
			
		|||
	auto &surface = entity.get_component<SurfaceComponent>();
 | 
			
		||||
 | 
			
		||||
	surface.m_title = new_title;
 | 
			
		||||
	glfwSetWindowTitle(surface.m_glfw_handle, surface.m_title.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto System::tick() -> bool
 | 
			
		||||
{
 | 
			
		||||
	m_registry->view<SurfaceComponent>().each([](SurfaceComponent &surface) {
 | 
			
		||||
		glfwSwapBuffers(surface.m_glfw_handle);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	glfwPollEvents();
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -247,20 +89,12 @@ void System::set_size(ecs::Entity surface_entity, const math::uvec2 &new_size)
 | 
			
		|||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_resolution = new_size;
 | 
			
		||||
 | 
			
		||||
	glfwSetWindowSize(
 | 
			
		||||
	    surface.m_glfw_handle,
 | 
			
		||||
	    static_cast<int>(new_size.x),
 | 
			
		||||
	    static_cast<int>(new_size.y)
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_v_sync(ecs::Entity surface_entity, bool vsync)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_vsync = vsync;
 | 
			
		||||
 | 
			
		||||
	glfwSwapInterval(vsync);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::set_visibility(ecs::Entity surface_entity, bool visible)
 | 
			
		||||
| 
						 | 
				
			
			@ -270,23 +104,12 @@ void System::set_visibility(ecs::Entity surface_entity, bool visible)
 | 
			
		|||
 | 
			
		||||
	if (visible)
 | 
			
		||||
	{
 | 
			
		||||
		glfwShowWindow(surface.m_glfw_handle);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		glfwHideWindow(surface.m_glfw_handle);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::add_event_listener(
 | 
			
		||||
    ecs::Entity surface_entity,
 | 
			
		||||
    SurfaceComponent::EventCallback callback
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
	auto &surface = surface_entity.get_component<SurfaceComponent>();
 | 
			
		||||
	surface.m_event_callbacks.emplace_back(std::move(callback));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void System::ensure_component_sanity(const SurfaceComponent &component)
 | 
			
		||||
{
 | 
			
		||||
	auto [width, height] = component.get_resolution();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,16 +4,14 @@
 | 
			
		|||
#include <surface/events/keyboard.hpp>
 | 
			
		||||
#include <surface/events/mouse.hpp>
 | 
			
		||||
#include <surface/events/surface.hpp>
 | 
			
		||||
#include <surface/requests/surface.hpp>
 | 
			
		||||
#include <variant>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
typedef struct _XDisplay Display;
 | 
			
		||||
 | 
			
		||||
namespace lt::surface {
 | 
			
		||||
 | 
			
		||||
/** Represents a platform's surface (eg. a Window).
 | 
			
		||||
 *
 | 
			
		||||
 * @note Read-only component, should only be modified through a system.
 | 
			
		||||
 */
 | 
			
		||||
/** Represents a platform's surface (eg. a Window). */
 | 
			
		||||
class SurfaceComponent
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -29,23 +27,27 @@ public:
 | 
			
		|||
 | 
			
		||||
	    // keyboard events
 | 
			
		||||
	    KeyPressedEvent,
 | 
			
		||||
	    KeyRepeatEvent,
 | 
			
		||||
	    KeyReleasedEvent,
 | 
			
		||||
	    KeySetCharEvent,
 | 
			
		||||
 | 
			
		||||
	    // mouse events
 | 
			
		||||
	    MouseMovedEvent,
 | 
			
		||||
	    WheelScrolledEvent,
 | 
			
		||||
	    ButtonPressedEvent,
 | 
			
		||||
	    ButtonReleasedEvent>;
 | 
			
		||||
 | 
			
		||||
	using EventCallback = std::function<bool(const Event &)>;
 | 
			
		||||
	using Request = std::variant<
 | 
			
		||||
	    ModifyTitleRequest,
 | 
			
		||||
	    ModifyResolutionRequest,
 | 
			
		||||
	    ModifyPositionRequest,
 | 
			
		||||
	    ModifyVisibilityRequest>;
 | 
			
		||||
 | 
			
		||||
	using WindowsNativeHandle = void *;
 | 
			
		||||
 | 
			
		||||
	using X11NativeHandle = unsigned long;
 | 
			
		||||
 | 
			
		||||
	using NativeHandle = std::variant<WindowsNativeHandle, X11NativeHandle>;
 | 
			
		||||
#ifdef LIGHT_PLATFORM_LINUX
 | 
			
		||||
	struct NativeData
 | 
			
		||||
	{
 | 
			
		||||
		Display *display;
 | 
			
		||||
		uint32_t window;
 | 
			
		||||
		unsigned long wm_delete_message;
 | 
			
		||||
	};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	static constexpr auto max_dimension = 4096;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +69,7 @@ public:
 | 
			
		|||
	    , m_resolution(info.resolution)
 | 
			
		||||
	    , m_vsync(info.vsync)
 | 
			
		||||
	    , m_visible(info.visible)
 | 
			
		||||
	    , m_native_data({})
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +83,11 @@ public:
 | 
			
		|||
		return m_resolution;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_position() const -> const math::ivec2 &
 | 
			
		||||
	{
 | 
			
		||||
		return m_position;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto is_vsync() const -> bool
 | 
			
		||||
	{
 | 
			
		||||
		return m_vsync;
 | 
			
		||||
| 
						 | 
				
			
			@ -90,30 +98,48 @@ public:
 | 
			
		|||
		return m_visible;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_native_handle() const -> NativeHandle
 | 
			
		||||
	[[nodiscard]] auto get_native_data() const -> const NativeData &
 | 
			
		||||
	{
 | 
			
		||||
		return m_native_handle;
 | 
			
		||||
		return m_native_data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto peek_events() const -> const std::vector<Event> &
 | 
			
		||||
	{
 | 
			
		||||
		return m_event_queue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto peek_requests() const -> const std::vector<Request> &
 | 
			
		||||
	{
 | 
			
		||||
		return m_requests;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void push_request(const Request &request)
 | 
			
		||||
	{
 | 
			
		||||
		m_requests.emplace_back(request);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/** @note: Only the surface system and tests should push events */
 | 
			
		||||
	void push_event(const Event &event)
 | 
			
		||||
	{
 | 
			
		||||
		m_event_queue.emplace_back(event);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	[[nodiscard]] auto get_glfw_handle() const -> GLFWwindow *
 | 
			
		||||
	{
 | 
			
		||||
		return m_glfw_handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string m_title;
 | 
			
		||||
 | 
			
		||||
	math::uvec2 m_resolution;
 | 
			
		||||
 | 
			
		||||
	math::ivec2 m_position;
 | 
			
		||||
 | 
			
		||||
	bool m_vsync;
 | 
			
		||||
 | 
			
		||||
	bool m_visible;
 | 
			
		||||
 | 
			
		||||
	NativeHandle m_native_handle;
 | 
			
		||||
	NativeData m_native_data;
 | 
			
		||||
 | 
			
		||||
	GLFWwindow *m_glfw_handle {};
 | 
			
		||||
	std::vector<Event> m_event_queue;
 | 
			
		||||
 | 
			
		||||
	std::vector<EventCallback> m_event_callbacks;
 | 
			
		||||
	std::vector<Request> m_requests;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt::surface
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,11 +7,11 @@ namespace lt::surface {
 | 
			
		|||
class KeyPressedEvent
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	KeyPressedEvent(int32_t key): m_key(key)
 | 
			
		||||
	KeyPressedEvent(uint32_t key): m_key(key)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_key() const -> int32_t
 | 
			
		||||
	[[nodiscard]] auto get_key() const -> uint32_t
 | 
			
		||||
	{
 | 
			
		||||
		return m_key;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ public:
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	int32_t m_key;
 | 
			
		||||
	uint32_t m_key;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class KeyRepeatEvent
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ public:
 | 
			
		|||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_key() const -> int32_t
 | 
			
		||||
	[[nodiscard]] auto get_key() const -> uint32_t
 | 
			
		||||
	{
 | 
			
		||||
		return m_key;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -43,17 +43,17 @@ public:
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	int32_t m_key;
 | 
			
		||||
	uint32_t m_key;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class KeyReleasedEvent
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	KeyReleasedEvent(int key): m_key(key)
 | 
			
		||||
	KeyReleasedEvent(uint32_t key): m_key(key)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] auto get_key() const -> int32_t
 | 
			
		||||
	[[nodiscard]] auto get_key() const -> uint32_t
 | 
			
		||||
	{
 | 
			
		||||
		return m_key;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ public:
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	int32_t m_key;
 | 
			
		||||
	uint32_t m_key;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class KeySetCharEvent
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								modules/surface/public/requests/surface.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/surface/public/requests/surface.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <math/vec2.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt::surface {
 | 
			
		||||
 | 
			
		||||
struct ModifyTitleRequest
 | 
			
		||||
{
 | 
			
		||||
	std::string title;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ModifyResolutionRequest
 | 
			
		||||
{
 | 
			
		||||
	math::uvec2 resolution;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ModifyPositionRequest
 | 
			
		||||
{
 | 
			
		||||
	math::ivec2 position;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ModifyVisibilityRequest
 | 
			
		||||
{
 | 
			
		||||
	bool visible;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}; // namespace lt::surface
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,7 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <app/system.hpp>
 | 
			
		||||
#include <ecs/entity.hpp>
 | 
			
		||||
#include <ecs/scene.hpp>
 | 
			
		||||
#include <surface/components.hpp>
 | 
			
		||||
 | 
			
		||||
namespace lt::surface {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,26 +20,12 @@ public:
 | 
			
		|||
 | 
			
		||||
	auto operator=(const System &) -> System & = delete;
 | 
			
		||||
 | 
			
		||||
	void on_register() override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	void on_register() override;
 | 
			
		||||
 | 
			
		||||
	void on_unregister() override
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	void on_unregister() override;
 | 
			
		||||
 | 
			
		||||
	auto tick() -> bool override;
 | 
			
		||||
 | 
			
		||||
	static void set_title(ecs::Entity surface_entity, std::string_view new_title);
 | 
			
		||||
 | 
			
		||||
	void set_size(ecs::Entity surface_entity, const math::uvec2 &new_size);
 | 
			
		||||
 | 
			
		||||
	void set_v_sync(ecs::Entity surface_entity, bool vsync);
 | 
			
		||||
 | 
			
		||||
	void set_visibility(ecs::Entity surface_entity, bool visible);
 | 
			
		||||
 | 
			
		||||
	void add_event_listener(ecs::Entity surface_entity, SurfaceComponent::EventCallback callback);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void on_surface_construct(entt::registry ®istry, entt::entity entity);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,10 +33,35 @@ private:
 | 
			
		|||
 | 
			
		||||
	void on_surface_destroy(entt::registry ®istry, entt::entity entity);
 | 
			
		||||
 | 
			
		||||
	void ensure_component_sanity(const SurfaceComponent &component);
 | 
			
		||||
	void handle_requests(struct SurfaceComponent &surface);
 | 
			
		||||
 | 
			
		||||
	void handle_events(struct SurfaceComponent &surface);
 | 
			
		||||
 | 
			
		||||
	void modify_title(struct SurfaceComponent &surface, const struct ModifyTitleRequest &request);
 | 
			
		||||
 | 
			
		||||
	void modify_resolution(
 | 
			
		||||
	    struct SurfaceComponent &surface,
 | 
			
		||||
	    const struct ModifyResolutionRequest &request
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	void modify_position(
 | 
			
		||||
	    struct SurfaceComponent &surface,
 | 
			
		||||
	    const struct ModifyPositionRequest &request
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	void modify_visiblity(
 | 
			
		||||
	    struct SurfaceComponent &surface,
 | 
			
		||||
	    const struct ModifyVisibilityRequest &request
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	void modify_position(ecs::Entity surface_entity, const math::ivec2 &new_size);
 | 
			
		||||
 | 
			
		||||
	void modify_position(ecs::Entity surface_entity, const math::uvec2 &new_size);
 | 
			
		||||
 | 
			
		||||
	void set_visibility(ecs::Entity surface_entity, bool visible);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	Ref<ecs::Registry> m_registry;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // namespace lt::surface
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,12 @@
 | 
			
		|||
namespace lt::test {
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
concept Printable = requires(std::ostream &stream, T value) {
 | 
			
		||||
	{ stream << value } -> std::same_as<std::ostream &>;
 | 
			
		||||
} || requires(std::ostream &stream, T value) {
 | 
			
		||||
concept Formattable = requires(T &v, std::format_context ctx) {
 | 
			
		||||
	std::formatter<std::remove_cvref_t<T>>().format(v, ctx);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
concept Printable = Formattable<T> || requires(std::ostream &stream, T value) {
 | 
			
		||||
	{ stream << std::to_underlying<T>(value) } -> std::same_as<std::ostream &>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
add_library_module(ui ui.cpp gl/ui.cpp gl/backend.cpp glfw/glfw.cpp)
 | 
			
		||||
add_library_module(ui ui.cpp)
 | 
			
		||||
target_link_libraries(ui PUBLIC imgui renderer logger lt_debug)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
# Disable all checks in this subdirectory
 | 
			
		||||
Checks: '-*'
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,70 +0,0 @@
 | 
			
		|||
// clang-format off
 | 
			
		||||
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
 | 
			
		||||
// - Desktop GL: 2.x 3.x 4.x
 | 
			
		||||
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
 | 
			
		||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
 | 
			
		||||
 | 
			
		||||
// Implemented features:
 | 
			
		||||
//  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
 | 
			
		||||
//  [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
 | 
			
		||||
//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
 | 
			
		||||
//  [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
 | 
			
		||||
 | 
			
		||||
// About WebGL/ES:
 | 
			
		||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
 | 
			
		||||
// - This is done automatically on iOS, Android and Emscripten targets.
 | 
			
		||||
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
 | 
			
		||||
 | 
			
		||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 | 
			
		||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 | 
			
		||||
// Learn about Dear ImGui:
 | 
			
		||||
// - FAQ                  https://dearimgui.com/faq
 | 
			
		||||
// - Getting Started      https://dearimgui.com/getting-started
 | 
			
		||||
// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 | 
			
		||||
// - Introduction, links and more at the top of imgui.cpp
 | 
			
		||||
 | 
			
		||||
// About GLSL version:
 | 
			
		||||
//  The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
 | 
			
		||||
//  On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
 | 
			
		||||
//  Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "imgui.h"      // IMGUI_IMPL_API
 | 
			
		||||
#ifndef IMGUI_DISABLE
 | 
			
		||||
 | 
			
		||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
 | 
			
		||||
IMGUI_IMPL_API bool     ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplOpenGL3_Shutdown();
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplOpenGL3_NewFrame();
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
 | 
			
		||||
 | 
			
		||||
// (Optional) Called by Init/NewFrame/Shutdown
 | 
			
		||||
IMGUI_IMPL_API bool     ImGui_ImplOpenGL3_CreateDeviceObjects();
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplOpenGL3_DestroyDeviceObjects();
 | 
			
		||||
 | 
			
		||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
 | 
			
		||||
 | 
			
		||||
// Configuration flags to add in your imconfig file:
 | 
			
		||||
//#define IMGUI_IMPL_OPENGL_ES2     // Enable ES 2 (Auto-detected on Emscripten)
 | 
			
		||||
//#define IMGUI_IMPL_OPENGL_ES3     // Enable ES 3 (Auto-detected on iOS/Android)
 | 
			
		||||
 | 
			
		||||
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
 | 
			
		||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) \
 | 
			
		||||
 && !defined(IMGUI_IMPL_OPENGL_ES3)
 | 
			
		||||
 | 
			
		||||
// Try to detect GLES on matching platforms
 | 
			
		||||
#if defined(__APPLE__)
 | 
			
		||||
#include <TargetConditionals.h>
 | 
			
		||||
#endif
 | 
			
		||||
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
 | 
			
		||||
#define IMGUI_IMPL_OPENGL_ES3               // iOS, Android  -> GL ES 3, "#version 300 es"
 | 
			
		||||
#elif defined(__EMSCRIPTEN__) || defined(__amigaos4__)
 | 
			
		||||
#define IMGUI_IMPL_OPENGL_ES2               // Emscripten    -> GL ES 2, "#version 100"
 | 
			
		||||
#else
 | 
			
		||||
// Otherwise imgui_impl_opengl3_loader.h will be used.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef IMGUI_DISABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -1,923 +0,0 @@
 | 
			
		|||
// clang-format off
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
// About imgui_impl_opengl3_loader.h:
 | 
			
		||||
//
 | 
			
		||||
// We embed our own OpenGL loader to not require user to provide their own or to have to use ours,
 | 
			
		||||
// which proved to be endless problems for users.
 | 
			
		||||
// Our loader is custom-generated, based on gl3w but automatically filtered to only include
 | 
			
		||||
// enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small.
 | 
			
		||||
//
 | 
			
		||||
// YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY.
 | 
			
		||||
// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
 | 
			
		||||
//
 | 
			
		||||
// IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions):
 | 
			
		||||
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCLUDING 'imgui_impl_opengl3_loader.h'
 | 
			
		||||
// IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER.
 | 
			
		||||
// (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS)
 | 
			
		||||
// YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT.
 | 
			
		||||
// BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp
 | 
			
		||||
// WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT.
 | 
			
		||||
//
 | 
			
		||||
// Regenerate with:
 | 
			
		||||
//   python3 gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
 | 
			
		||||
//
 | 
			
		||||
// More info:
 | 
			
		||||
//   https://github.com/dearimgui/gl3w_stripped
 | 
			
		||||
//   https://github.com/ocornut/imgui/issues/4445
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This file was generated with gl3w_gen.py, part of imgl3w
 | 
			
		||||
 * (hosted at https://github.com/dearimgui/gl3w_stripped)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free and unencumbered software released into the public domain.
 | 
			
		||||
 *
 | 
			
		||||
 * Anyone is free to copy, modify, publish, use, compile, sell, or
 | 
			
		||||
 * distribute this software, either in source code form or as a compiled
 | 
			
		||||
 * binary, for any purpose, commercial or non-commercial, and by any
 | 
			
		||||
 * means.
 | 
			
		||||
 *
 | 
			
		||||
 * In jurisdictions that recognize copyright laws, the author or authors
 | 
			
		||||
 * of this software dedicate any and all copyright interest in the
 | 
			
		||||
 * software to the public domain. We make this dedication for the benefit
 | 
			
		||||
 * of the public at large and to the detriment of our heirs and
 | 
			
		||||
 * successors. We intend this dedication to be an overt act of
 | 
			
		||||
 * relinquishment in perpetuity of all present and future rights to this
 | 
			
		||||
 * software under copyright law.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 | 
			
		||||
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 | 
			
		||||
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | 
			
		||||
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
			
		||||
 * OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __gl3w_h_
 | 
			
		||||
#define __gl3w_h_
 | 
			
		||||
 | 
			
		||||
// Adapted from KHR/khrplatform.h to avoid including entire file.
 | 
			
		||||
#ifndef __khrplatform_h_
 | 
			
		||||
typedef          float         khronos_float_t;
 | 
			
		||||
typedef signed   char          khronos_int8_t;
 | 
			
		||||
typedef unsigned char          khronos_uint8_t;
 | 
			
		||||
typedef signed   short int     khronos_int16_t;
 | 
			
		||||
typedef unsigned short int     khronos_uint16_t;
 | 
			
		||||
#ifdef _WIN64
 | 
			
		||||
typedef signed   long long int khronos_intptr_t;
 | 
			
		||||
typedef signed   long long int khronos_ssize_t;
 | 
			
		||||
#else
 | 
			
		||||
typedef signed   long  int     khronos_intptr_t;
 | 
			
		||||
typedef signed   long  int     khronos_ssize_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(__clang__)
 | 
			
		||||
typedef signed   __int64       khronos_int64_t;
 | 
			
		||||
typedef unsigned __int64       khronos_uint64_t;
 | 
			
		||||
#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
typedef          int64_t       khronos_int64_t;
 | 
			
		||||
typedef          uint64_t      khronos_uint64_t;
 | 
			
		||||
#else
 | 
			
		||||
typedef signed   long long     khronos_int64_t;
 | 
			
		||||
typedef unsigned long long     khronos_uint64_t;
 | 
			
		||||
#endif
 | 
			
		||||
#endif  // __khrplatform_h_
 | 
			
		||||
 | 
			
		||||
#ifndef __gl_glcorearb_h_
 | 
			
		||||
#define __gl_glcorearb_h_ 1
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
/*
 | 
			
		||||
** Copyright 2013-2020 The Khronos Group Inc.
 | 
			
		||||
** SPDX-License-Identifier: MIT
 | 
			
		||||
**
 | 
			
		||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
 | 
			
		||||
** API Registry. The current version of the Registry, generator scripts
 | 
			
		||||
** used to make the header, and the header can be found at
 | 
			
		||||
**   https://github.com/KhronosGroup/OpenGL-Registry
 | 
			
		||||
*/
 | 
			
		||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
 | 
			
		||||
#ifndef WIN32_LEAN_AND_MEAN
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN 1
 | 
			
		||||
#endif
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef APIENTRY
 | 
			
		||||
#define APIENTRY
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef APIENTRYP
 | 
			
		||||
#define APIENTRYP APIENTRY *
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef GLAPI
 | 
			
		||||
#define GLAPI extern
 | 
			
		||||
#endif
 | 
			
		||||
/* glcorearb.h is for use with OpenGL core profile implementations.
 | 
			
		||||
** It should should be placed in the same directory as gl.h and
 | 
			
		||||
** included as <GL/glcorearb.h>.
 | 
			
		||||
**
 | 
			
		||||
** glcorearb.h includes only APIs in the latest OpenGL core profile
 | 
			
		||||
** implementation together with APIs in newer ARB extensions which 
 | 
			
		||||
** can be supported by the core profile. It does not, and never will
 | 
			
		||||
** include functionality removed from the core profile, such as
 | 
			
		||||
** fixed-function vertex and fragment processing.
 | 
			
		||||
**
 | 
			
		||||
** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or
 | 
			
		||||
** <GL/glext.h> in the same source file.
 | 
			
		||||
*/
 | 
			
		||||
/* Generated C header for:
 | 
			
		||||
 * API: gl
 | 
			
		||||
 * Profile: core
 | 
			
		||||
 * Versions considered: .*
 | 
			
		||||
 * Versions emitted: .*
 | 
			
		||||
 * Default extensions included: glcore
 | 
			
		||||
 * Additional extensions included: _nomatch_^
 | 
			
		||||
 * Extensions removed: _nomatch_^
 | 
			
		||||
 */
 | 
			
		||||
#ifndef GL_VERSION_1_0
 | 
			
		||||
typedef void GLvoid;
 | 
			
		||||
typedef unsigned int GLenum;
 | 
			
		||||
 | 
			
		||||
typedef khronos_float_t GLfloat;
 | 
			
		||||
typedef int GLint;
 | 
			
		||||
typedef int GLsizei;
 | 
			
		||||
typedef unsigned int GLbitfield;
 | 
			
		||||
typedef double GLdouble;
 | 
			
		||||
typedef unsigned int GLuint;
 | 
			
		||||
typedef unsigned char GLboolean;
 | 
			
		||||
typedef khronos_uint8_t GLubyte;
 | 
			
		||||
#define GL_COLOR_BUFFER_BIT               0x00004000
 | 
			
		||||
#define GL_FALSE                          0
 | 
			
		||||
#define GL_TRUE                           1
 | 
			
		||||
#define GL_TRIANGLES                      0x0004
 | 
			
		||||
#define GL_ONE                            1
 | 
			
		||||
#define GL_SRC_ALPHA                      0x0302
 | 
			
		||||
#define GL_ONE_MINUS_SRC_ALPHA            0x0303
 | 
			
		||||
#define GL_FRONT                          0x0404
 | 
			
		||||
#define GL_BACK                           0x0405
 | 
			
		||||
#define GL_FRONT_AND_BACK                 0x0408
 | 
			
		||||
#define GL_POLYGON_MODE                   0x0B40
 | 
			
		||||
#define GL_CULL_FACE                      0x0B44
 | 
			
		||||
#define GL_DEPTH_TEST                     0x0B71
 | 
			
		||||
#define GL_STENCIL_TEST                   0x0B90
 | 
			
		||||
#define GL_VIEWPORT                       0x0BA2
 | 
			
		||||
#define GL_BLEND                          0x0BE2
 | 
			
		||||
#define GL_SCISSOR_BOX                    0x0C10
 | 
			
		||||
#define GL_SCISSOR_TEST                   0x0C11
 | 
			
		||||
#define GL_UNPACK_ROW_LENGTH              0x0CF2
 | 
			
		||||
#define GL_PACK_ALIGNMENT                 0x0D05
 | 
			
		||||
#define GL_MAX_TEXTURE_SIZE               0x0D33
 | 
			
		||||
#define GL_TEXTURE_2D                     0x0DE1
 | 
			
		||||
#define GL_UNSIGNED_BYTE                  0x1401
 | 
			
		||||
#define GL_UNSIGNED_SHORT                 0x1403
 | 
			
		||||
#define GL_UNSIGNED_INT                   0x1405
 | 
			
		||||
#define GL_FLOAT                          0x1406
 | 
			
		||||
#define GL_RGBA                           0x1908
 | 
			
		||||
#define GL_FILL                           0x1B02
 | 
			
		||||
#define GL_VENDOR                         0x1F00
 | 
			
		||||
#define GL_RENDERER                       0x1F01
 | 
			
		||||
#define GL_VERSION                        0x1F02
 | 
			
		||||
#define GL_EXTENSIONS                     0x1F03
 | 
			
		||||
#define GL_LINEAR                         0x2601
 | 
			
		||||
#define GL_TEXTURE_MAG_FILTER             0x2800
 | 
			
		||||
#define GL_TEXTURE_MIN_FILTER             0x2801
 | 
			
		||||
#define GL_TEXTURE_WRAP_S                 0x2802
 | 
			
		||||
#define GL_TEXTURE_WRAP_T                 0x2803
 | 
			
		||||
#define GL_REPEAT                         0x2901
 | 
			
		||||
typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
 | 
			
		||||
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
 | 
			
		||||
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
 | 
			
		||||
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
 | 
			
		||||
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
 | 
			
		||||
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
 | 
			
		||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
 | 
			
		||||
typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
 | 
			
		||||
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
 | 
			
		||||
GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
 | 
			
		||||
GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
 | 
			
		||||
GLAPI void APIENTRY glClear (GLbitfield mask);
 | 
			
		||||
GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 | 
			
		||||
GLAPI void APIENTRY glDisable (GLenum cap);
 | 
			
		||||
GLAPI void APIENTRY glEnable (GLenum cap);
 | 
			
		||||
GLAPI void APIENTRY glFlush (void);
 | 
			
		||||
GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
 | 
			
		||||
GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
 | 
			
		||||
GLAPI GLenum APIENTRY glGetError (void);
 | 
			
		||||
GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);
 | 
			
		||||
GLAPI const GLubyte *APIENTRY glGetString (GLenum name);
 | 
			
		||||
GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
 | 
			
		||||
GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_1_0 */
 | 
			
		||||
#ifndef GL_VERSION_1_1
 | 
			
		||||
typedef khronos_float_t GLclampf;
 | 
			
		||||
typedef double GLclampd;
 | 
			
		||||
#define GL_TEXTURE_BINDING_2D             0x8069
 | 
			
		||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
 | 
			
		||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
 | 
			
		||||
GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
 | 
			
		||||
GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
 | 
			
		||||
GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
 | 
			
		||||
GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_1_1 */
 | 
			
		||||
#ifndef GL_VERSION_1_2
 | 
			
		||||
#define GL_CLAMP_TO_EDGE                  0x812F
 | 
			
		||||
#endif /* GL_VERSION_1_2 */
 | 
			
		||||
#ifndef GL_VERSION_1_3
 | 
			
		||||
#define GL_TEXTURE0                       0x84C0
 | 
			
		||||
#define GL_ACTIVE_TEXTURE                 0x84E0
 | 
			
		||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glActiveTexture (GLenum texture);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_1_3 */
 | 
			
		||||
#ifndef GL_VERSION_1_4
 | 
			
		||||
#define GL_BLEND_DST_RGB                  0x80C8
 | 
			
		||||
#define GL_BLEND_SRC_RGB                  0x80C9
 | 
			
		||||
#define GL_BLEND_DST_ALPHA                0x80CA
 | 
			
		||||
#define GL_BLEND_SRC_ALPHA                0x80CB
 | 
			
		||||
#define GL_FUNC_ADD                       0x8006
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
 | 
			
		||||
GLAPI void APIENTRY glBlendEquation (GLenum mode);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_1_4 */
 | 
			
		||||
#ifndef GL_VERSION_1_5
 | 
			
		||||
typedef khronos_ssize_t GLsizeiptr;
 | 
			
		||||
typedef khronos_intptr_t GLintptr;
 | 
			
		||||
#define GL_ARRAY_BUFFER                   0x8892
 | 
			
		||||
#define GL_ELEMENT_ARRAY_BUFFER           0x8893
 | 
			
		||||
#define GL_ARRAY_BUFFER_BINDING           0x8894
 | 
			
		||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
 | 
			
		||||
#define GL_STREAM_DRAW                    0x88E0
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
 | 
			
		||||
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
 | 
			
		||||
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
 | 
			
		||||
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
 | 
			
		||||
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_1_5 */
 | 
			
		||||
#ifndef GL_VERSION_2_0
 | 
			
		||||
typedef char GLchar;
 | 
			
		||||
typedef khronos_int16_t GLshort;
 | 
			
		||||
typedef khronos_int8_t GLbyte;
 | 
			
		||||
typedef khronos_uint16_t GLushort;
 | 
			
		||||
#define GL_BLEND_EQUATION_RGB             0x8009
 | 
			
		||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
 | 
			
		||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
 | 
			
		||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
 | 
			
		||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
 | 
			
		||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
 | 
			
		||||
#define GL_BLEND_EQUATION_ALPHA           0x883D
 | 
			
		||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
 | 
			
		||||
#define GL_FRAGMENT_SHADER                0x8B30
 | 
			
		||||
#define GL_VERTEX_SHADER                  0x8B31
 | 
			
		||||
#define GL_COMPILE_STATUS                 0x8B81
 | 
			
		||||
#define GL_LINK_STATUS                    0x8B82
 | 
			
		||||
#define GL_INFO_LOG_LENGTH                0x8B84
 | 
			
		||||
#define GL_CURRENT_PROGRAM                0x8B8D
 | 
			
		||||
#define GL_UPPER_LEFT                     0x8CA2
 | 
			
		||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
 | 
			
		||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
 | 
			
		||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
 | 
			
		||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
 | 
			
		||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
 | 
			
		||||
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
 | 
			
		||||
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
 | 
			
		||||
typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
 | 
			
		||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 | 
			
		||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
 | 
			
		||||
GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
 | 
			
		||||
GLAPI void APIENTRY glCompileShader (GLuint shader);
 | 
			
		||||
GLAPI GLuint APIENTRY glCreateProgram (void);
 | 
			
		||||
GLAPI GLuint APIENTRY glCreateShader (GLenum type);
 | 
			
		||||
GLAPI void APIENTRY glDeleteProgram (GLuint program);
 | 
			
		||||
GLAPI void APIENTRY glDeleteShader (GLuint shader);
 | 
			
		||||
GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
 | 
			
		||||
GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
 | 
			
		||||
GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
 | 
			
		||||
GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
 | 
			
		||||
GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
 | 
			
		||||
GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
 | 
			
		||||
GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
 | 
			
		||||
GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
 | 
			
		||||
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
 | 
			
		||||
GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
 | 
			
		||||
GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
 | 
			
		||||
GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
 | 
			
		||||
GLAPI void APIENTRY glLinkProgram (GLuint program);
 | 
			
		||||
GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
 | 
			
		||||
GLAPI void APIENTRY glUseProgram (GLuint program);
 | 
			
		||||
GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
 | 
			
		||||
GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 | 
			
		||||
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_2_0 */
 | 
			
		||||
#ifndef GL_VERSION_2_1
 | 
			
		||||
#define GL_PIXEL_UNPACK_BUFFER            0x88EC
 | 
			
		||||
#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF
 | 
			
		||||
#endif /* GL_VERSION_2_1 */
 | 
			
		||||
#ifndef GL_VERSION_3_0
 | 
			
		||||
typedef khronos_uint16_t GLhalf;
 | 
			
		||||
#define GL_MAJOR_VERSION                  0x821B
 | 
			
		||||
#define GL_MINOR_VERSION                  0x821C
 | 
			
		||||
#define GL_NUM_EXTENSIONS                 0x821D
 | 
			
		||||
#define GL_FRAMEBUFFER_SRGB               0x8DB9
 | 
			
		||||
#define GL_VERTEX_ARRAY_BINDING           0x85B5
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
 | 
			
		||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
 | 
			
		||||
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
 | 
			
		||||
GLAPI void APIENTRY glBindVertexArray (GLuint array);
 | 
			
		||||
GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
 | 
			
		||||
GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_3_0 */
 | 
			
		||||
#ifndef GL_VERSION_3_1
 | 
			
		||||
#define GL_VERSION_3_1 1
 | 
			
		||||
#define GL_PRIMITIVE_RESTART              0x8F9D
 | 
			
		||||
#endif /* GL_VERSION_3_1 */
 | 
			
		||||
#ifndef GL_VERSION_3_2
 | 
			
		||||
#define GL_VERSION_3_2 1
 | 
			
		||||
typedef struct __GLsync *GLsync;
 | 
			
		||||
typedef khronos_uint64_t GLuint64;
 | 
			
		||||
typedef khronos_int64_t GLint64;
 | 
			
		||||
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
 | 
			
		||||
#define GL_CONTEXT_PROFILE_MASK           0x9126
 | 
			
		||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_3_2 */
 | 
			
		||||
#ifndef GL_VERSION_3_3
 | 
			
		||||
#define GL_VERSION_3_3 1
 | 
			
		||||
#define GL_SAMPLER_BINDING                0x8919
 | 
			
		||||
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
 | 
			
		||||
#ifdef GL_GLEXT_PROTOTYPES
 | 
			
		||||
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* GL_VERSION_3_3 */
 | 
			
		||||
#ifndef GL_VERSION_4_1
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
 | 
			
		||||
#endif /* GL_VERSION_4_1 */
 | 
			
		||||
#ifndef GL_VERSION_4_3
 | 
			
		||||
typedef void (APIENTRY  *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
 | 
			
		||||
#endif /* GL_VERSION_4_3 */
 | 
			
		||||
#ifndef GL_VERSION_4_5
 | 
			
		||||
#define GL_CLIP_ORIGIN                    0x935C
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
 | 
			
		||||
#endif /* GL_VERSION_4_5 */
 | 
			
		||||
#ifndef GL_ARB_bindless_texture
 | 
			
		||||
typedef khronos_uint64_t GLuint64EXT;
 | 
			
		||||
#endif /* GL_ARB_bindless_texture */
 | 
			
		||||
#ifndef GL_ARB_cl_event
 | 
			
		||||
struct _cl_context;
 | 
			
		||||
struct _cl_event;
 | 
			
		||||
#endif /* GL_ARB_cl_event */
 | 
			
		||||
#ifndef GL_ARB_clip_control
 | 
			
		||||
#define GL_ARB_clip_control 1
 | 
			
		||||
#endif /* GL_ARB_clip_control */
 | 
			
		||||
#ifndef GL_ARB_debug_output
 | 
			
		||||
typedef void (APIENTRY  *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
 | 
			
		||||
#endif /* GL_ARB_debug_output */
 | 
			
		||||
#ifndef GL_EXT_EGL_image_storage
 | 
			
		||||
typedef void *GLeglImageOES;
 | 
			
		||||
#endif /* GL_EXT_EGL_image_storage */
 | 
			
		||||
#ifndef GL_EXT_direct_state_access
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
 | 
			
		||||
#endif /* GL_EXT_direct_state_access */
 | 
			
		||||
#ifndef GL_NV_draw_vulkan_image
 | 
			
		||||
typedef void (APIENTRY  *GLVULKANPROCNV)(void);
 | 
			
		||||
#endif /* GL_NV_draw_vulkan_image */
 | 
			
		||||
#ifndef GL_NV_gpu_shader5
 | 
			
		||||
typedef khronos_int64_t GLint64EXT;
 | 
			
		||||
#endif /* GL_NV_gpu_shader5 */
 | 
			
		||||
#ifndef GL_NV_vertex_buffer_unified_memory
 | 
			
		||||
typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
 | 
			
		||||
#endif /* GL_NV_vertex_buffer_unified_memory */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GL3W_API
 | 
			
		||||
#define GL3W_API
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef __gl_h_
 | 
			
		||||
#define __gl_h_
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define GL3W_OK 0
 | 
			
		||||
#define GL3W_ERROR_INIT -1
 | 
			
		||||
#define GL3W_ERROR_LIBRARY_OPEN -2
 | 
			
		||||
#define GL3W_ERROR_OPENGL_VERSION -3
 | 
			
		||||
 | 
			
		||||
typedef void (*GL3WglProc)(void);
 | 
			
		||||
typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
 | 
			
		||||
 | 
			
		||||
/* gl3w api */
 | 
			
		||||
GL3W_API int imgl3wInit(void);
 | 
			
		||||
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
 | 
			
		||||
GL3W_API int imgl3wIsSupported(int major, int minor);
 | 
			
		||||
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
 | 
			
		||||
 | 
			
		||||
/* gl3w internal state */
 | 
			
		||||
union ImGL3WProcs {
 | 
			
		||||
    GL3WglProc ptr[60];
 | 
			
		||||
    struct {
 | 
			
		||||
        PFNGLACTIVETEXTUREPROC            ActiveTexture;
 | 
			
		||||
        PFNGLATTACHSHADERPROC             AttachShader;
 | 
			
		||||
        PFNGLBINDBUFFERPROC               BindBuffer;
 | 
			
		||||
        PFNGLBINDSAMPLERPROC              BindSampler;
 | 
			
		||||
        PFNGLBINDTEXTUREPROC              BindTexture;
 | 
			
		||||
        PFNGLBINDVERTEXARRAYPROC          BindVertexArray;
 | 
			
		||||
        PFNGLBLENDEQUATIONPROC            BlendEquation;
 | 
			
		||||
        PFNGLBLENDEQUATIONSEPARATEPROC    BlendEquationSeparate;
 | 
			
		||||
        PFNGLBLENDFUNCSEPARATEPROC        BlendFuncSeparate;
 | 
			
		||||
        PFNGLBUFFERDATAPROC               BufferData;
 | 
			
		||||
        PFNGLBUFFERSUBDATAPROC            BufferSubData;
 | 
			
		||||
        PFNGLCLEARPROC                    Clear;
 | 
			
		||||
        PFNGLCLEARCOLORPROC               ClearColor;
 | 
			
		||||
        PFNGLCOMPILESHADERPROC            CompileShader;
 | 
			
		||||
        PFNGLCREATEPROGRAMPROC            CreateProgram;
 | 
			
		||||
        PFNGLCREATESHADERPROC             CreateShader;
 | 
			
		||||
        PFNGLDELETEBUFFERSPROC            DeleteBuffers;
 | 
			
		||||
        PFNGLDELETEPROGRAMPROC            DeleteProgram;
 | 
			
		||||
        PFNGLDELETESHADERPROC             DeleteShader;
 | 
			
		||||
        PFNGLDELETETEXTURESPROC           DeleteTextures;
 | 
			
		||||
        PFNGLDELETEVERTEXARRAYSPROC       DeleteVertexArrays;
 | 
			
		||||
        PFNGLDETACHSHADERPROC             DetachShader;
 | 
			
		||||
        PFNGLDISABLEPROC                  Disable;
 | 
			
		||||
        PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
 | 
			
		||||
        PFNGLDRAWELEMENTSPROC             DrawElements;
 | 
			
		||||
        PFNGLDRAWELEMENTSBASEVERTEXPROC   DrawElementsBaseVertex;
 | 
			
		||||
        PFNGLENABLEPROC                   Enable;
 | 
			
		||||
        PFNGLENABLEVERTEXATTRIBARRAYPROC  EnableVertexAttribArray;
 | 
			
		||||
        PFNGLFLUSHPROC                    Flush;
 | 
			
		||||
        PFNGLGENBUFFERSPROC               GenBuffers;
 | 
			
		||||
        PFNGLGENTEXTURESPROC              GenTextures;
 | 
			
		||||
        PFNGLGENVERTEXARRAYSPROC          GenVertexArrays;
 | 
			
		||||
        PFNGLGETATTRIBLOCATIONPROC        GetAttribLocation;
 | 
			
		||||
        PFNGLGETERRORPROC                 GetError;
 | 
			
		||||
        PFNGLGETINTEGERVPROC              GetIntegerv;
 | 
			
		||||
        PFNGLGETPROGRAMINFOLOGPROC        GetProgramInfoLog;
 | 
			
		||||
        PFNGLGETPROGRAMIVPROC             GetProgramiv;
 | 
			
		||||
        PFNGLGETSHADERINFOLOGPROC         GetShaderInfoLog;
 | 
			
		||||
        PFNGLGETSHADERIVPROC              GetShaderiv;
 | 
			
		||||
        PFNGLGETSTRINGPROC                GetString;
 | 
			
		||||
        PFNGLGETSTRINGIPROC               GetStringi;
 | 
			
		||||
        PFNGLGETUNIFORMLOCATIONPROC       GetUniformLocation;
 | 
			
		||||
        PFNGLGETVERTEXATTRIBPOINTERVPROC  GetVertexAttribPointerv;
 | 
			
		||||
        PFNGLGETVERTEXATTRIBIVPROC        GetVertexAttribiv;
 | 
			
		||||
        PFNGLISENABLEDPROC                IsEnabled;
 | 
			
		||||
        PFNGLISPROGRAMPROC                IsProgram;
 | 
			
		||||
        PFNGLLINKPROGRAMPROC              LinkProgram;
 | 
			
		||||
        PFNGLPIXELSTOREIPROC              PixelStorei;
 | 
			
		||||
        PFNGLPOLYGONMODEPROC              PolygonMode;
 | 
			
		||||
        PFNGLREADPIXELSPROC               ReadPixels;
 | 
			
		||||
        PFNGLSCISSORPROC                  Scissor;
 | 
			
		||||
        PFNGLSHADERSOURCEPROC             ShaderSource;
 | 
			
		||||
        PFNGLTEXIMAGE2DPROC               TexImage2D;
 | 
			
		||||
        PFNGLTEXPARAMETERIPROC            TexParameteri;
 | 
			
		||||
        PFNGLTEXSUBIMAGE2DPROC            TexSubImage2D;
 | 
			
		||||
        PFNGLUNIFORM1IPROC                Uniform1i;
 | 
			
		||||
        PFNGLUNIFORMMATRIX4FVPROC         UniformMatrix4fv;
 | 
			
		||||
        PFNGLUSEPROGRAMPROC               UseProgram;
 | 
			
		||||
        PFNGLVERTEXATTRIBPOINTERPROC      VertexAttribPointer;
 | 
			
		||||
        PFNGLVIEWPORTPROC                 Viewport;
 | 
			
		||||
    } gl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GL3W_API extern union ImGL3WProcs imgl3wProcs;
 | 
			
		||||
 | 
			
		||||
/* OpenGL functions */
 | 
			
		||||
#define glActiveTexture                   imgl3wProcs.gl.ActiveTexture
 | 
			
		||||
#define glAttachShader                    imgl3wProcs.gl.AttachShader
 | 
			
		||||
#define glBindBuffer                      imgl3wProcs.gl.BindBuffer
 | 
			
		||||
#define glBindSampler                     imgl3wProcs.gl.BindSampler
 | 
			
		||||
#define glBindTexture                     imgl3wProcs.gl.BindTexture
 | 
			
		||||
#define glBindVertexArray                 imgl3wProcs.gl.BindVertexArray
 | 
			
		||||
#define glBlendEquation                   imgl3wProcs.gl.BlendEquation
 | 
			
		||||
#define glBlendEquationSeparate           imgl3wProcs.gl.BlendEquationSeparate
 | 
			
		||||
#define glBlendFuncSeparate               imgl3wProcs.gl.BlendFuncSeparate
 | 
			
		||||
#define glBufferData                      imgl3wProcs.gl.BufferData
 | 
			
		||||
#define glBufferSubData                   imgl3wProcs.gl.BufferSubData
 | 
			
		||||
#define glClear                           imgl3wProcs.gl.Clear
 | 
			
		||||
#define glClearColor                      imgl3wProcs.gl.ClearColor
 | 
			
		||||
#define glCompileShader                   imgl3wProcs.gl.CompileShader
 | 
			
		||||
#define glCreateProgram                   imgl3wProcs.gl.CreateProgram
 | 
			
		||||
#define glCreateShader                    imgl3wProcs.gl.CreateShader
 | 
			
		||||
#define glDeleteBuffers                   imgl3wProcs.gl.DeleteBuffers
 | 
			
		||||
#define glDeleteProgram                   imgl3wProcs.gl.DeleteProgram
 | 
			
		||||
#define glDeleteShader                    imgl3wProcs.gl.DeleteShader
 | 
			
		||||
#define glDeleteTextures                  imgl3wProcs.gl.DeleteTextures
 | 
			
		||||
#define glDeleteVertexArrays              imgl3wProcs.gl.DeleteVertexArrays
 | 
			
		||||
#define glDetachShader                    imgl3wProcs.gl.DetachShader
 | 
			
		||||
#define glDisable                         imgl3wProcs.gl.Disable
 | 
			
		||||
#define glDisableVertexAttribArray        imgl3wProcs.gl.DisableVertexAttribArray
 | 
			
		||||
#define glDrawElements                    imgl3wProcs.gl.DrawElements
 | 
			
		||||
#define glDrawElementsBaseVertex          imgl3wProcs.gl.DrawElementsBaseVertex
 | 
			
		||||
#define glEnable                          imgl3wProcs.gl.Enable
 | 
			
		||||
#define glEnableVertexAttribArray         imgl3wProcs.gl.EnableVertexAttribArray
 | 
			
		||||
#define glFlush                           imgl3wProcs.gl.Flush
 | 
			
		||||
#define glGenBuffers                      imgl3wProcs.gl.GenBuffers
 | 
			
		||||
#define glGenTextures                     imgl3wProcs.gl.GenTextures
 | 
			
		||||
#define glGenVertexArrays                 imgl3wProcs.gl.GenVertexArrays
 | 
			
		||||
#define glGetAttribLocation               imgl3wProcs.gl.GetAttribLocation
 | 
			
		||||
#define glGetError                        imgl3wProcs.gl.GetError
 | 
			
		||||
#define glGetIntegerv                     imgl3wProcs.gl.GetIntegerv
 | 
			
		||||
#define glGetProgramInfoLog               imgl3wProcs.gl.GetProgramInfoLog
 | 
			
		||||
#define glGetProgramiv                    imgl3wProcs.gl.GetProgramiv
 | 
			
		||||
#define glGetShaderInfoLog                imgl3wProcs.gl.GetShaderInfoLog
 | 
			
		||||
#define glGetShaderiv                     imgl3wProcs.gl.GetShaderiv
 | 
			
		||||
#define glGetString                       imgl3wProcs.gl.GetString
 | 
			
		||||
#define glGetStringi                      imgl3wProcs.gl.GetStringi
 | 
			
		||||
#define glGetUniformLocation              imgl3wProcs.gl.GetUniformLocation
 | 
			
		||||
#define glGetVertexAttribPointerv         imgl3wProcs.gl.GetVertexAttribPointerv
 | 
			
		||||
#define glGetVertexAttribiv               imgl3wProcs.gl.GetVertexAttribiv
 | 
			
		||||
#define glIsEnabled                       imgl3wProcs.gl.IsEnabled
 | 
			
		||||
#define glIsProgram                       imgl3wProcs.gl.IsProgram
 | 
			
		||||
#define glLinkProgram                     imgl3wProcs.gl.LinkProgram
 | 
			
		||||
#define glPixelStorei                     imgl3wProcs.gl.PixelStorei
 | 
			
		||||
#define glPolygonMode                     imgl3wProcs.gl.PolygonMode
 | 
			
		||||
#define glReadPixels                      imgl3wProcs.gl.ReadPixels
 | 
			
		||||
#define glScissor                         imgl3wProcs.gl.Scissor
 | 
			
		||||
#define glShaderSource                    imgl3wProcs.gl.ShaderSource
 | 
			
		||||
#define glTexImage2D                      imgl3wProcs.gl.TexImage2D
 | 
			
		||||
#define glTexParameteri                   imgl3wProcs.gl.TexParameteri
 | 
			
		||||
#define glTexSubImage2D                   imgl3wProcs.gl.TexSubImage2D
 | 
			
		||||
#define glUniform1i                       imgl3wProcs.gl.Uniform1i
 | 
			
		||||
#define glUniformMatrix4fv                imgl3wProcs.gl.UniformMatrix4fv
 | 
			
		||||
#define glUseProgram                      imgl3wProcs.gl.UseProgram
 | 
			
		||||
#define glVertexAttribPointer             imgl3wProcs.gl.VertexAttribPointer
 | 
			
		||||
#define glViewport                        imgl3wProcs.gl.Viewport
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef IMGL3W_IMPL
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#define GL3W_ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#ifndef WIN32_LEAN_AND_MEAN
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN 1
 | 
			
		||||
#endif
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
 | 
			
		||||
static HMODULE libgl;
 | 
			
		||||
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
 | 
			
		||||
static GL3WglGetProcAddr wgl_get_proc_address;
 | 
			
		||||
 | 
			
		||||
static int open_libgl(void)
 | 
			
		||||
{
 | 
			
		||||
    libgl = LoadLibraryA("opengl32.dll");
 | 
			
		||||
    if (!libgl)
 | 
			
		||||
        return GL3W_ERROR_LIBRARY_OPEN;
 | 
			
		||||
    wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
 | 
			
		||||
    return GL3W_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void close_libgl(void) { FreeLibrary(libgl); }
 | 
			
		||||
static GL3WglProc get_proc(const char *proc)
 | 
			
		||||
{
 | 
			
		||||
    GL3WglProc res;
 | 
			
		||||
    res = (GL3WglProc)wgl_get_proc_address(proc);
 | 
			
		||||
    if (!res)
 | 
			
		||||
        res = (GL3WglProc)GetProcAddress(libgl, proc);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
#elif defined(__APPLE__)
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
static void *libgl;
 | 
			
		||||
static int open_libgl(void)
 | 
			
		||||
{
 | 
			
		||||
    libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
    if (!libgl)
 | 
			
		||||
        return GL3W_ERROR_LIBRARY_OPEN;
 | 
			
		||||
    return GL3W_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void close_libgl(void) { dlclose(libgl); }
 | 
			
		||||
 | 
			
		||||
static GL3WglProc get_proc(const char *proc)
 | 
			
		||||
{
 | 
			
		||||
    GL3WglProc res;
 | 
			
		||||
    *(void **)(&res) = dlsym(libgl, proc);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
static void* libgl;  // OpenGL library
 | 
			
		||||
static void* libglx;  // GLX library
 | 
			
		||||
static void* libegl;  // EGL library
 | 
			
		||||
static GL3WGetProcAddressProc gl_get_proc_address;
 | 
			
		||||
 | 
			
		||||
static void close_libgl(void)
 | 
			
		||||
{
 | 
			
		||||
    if (libgl) {
 | 
			
		||||
        dlclose(libgl);
 | 
			
		||||
        libgl = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (libegl) {
 | 
			
		||||
        dlclose(libegl);
 | 
			
		||||
        libegl = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (libglx) {
 | 
			
		||||
        dlclose(libglx);
 | 
			
		||||
        libglx = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_library_loaded(const char* name, void** lib)
 | 
			
		||||
{
 | 
			
		||||
    *lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
 | 
			
		||||
    return *lib != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int open_libs(void)
 | 
			
		||||
{
 | 
			
		||||
    // On Linux we have two APIs to get process addresses: EGL and GLX.
 | 
			
		||||
    // EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
 | 
			
		||||
 | 
			
		||||
    libgl = NULL;
 | 
			
		||||
    libegl = NULL;
 | 
			
		||||
    libglx = NULL;
 | 
			
		||||
 | 
			
		||||
    // First check what's already loaded, the windowing library might have
 | 
			
		||||
    // already loaded either EGL or GLX and we want to use the same one.
 | 
			
		||||
 | 
			
		||||
    if (is_library_loaded("libEGL.so.1", &libegl) ||
 | 
			
		||||
        is_library_loaded("libGLX.so.0", &libglx)) {
 | 
			
		||||
        libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
        if (libgl)
 | 
			
		||||
            return GL3W_OK;
 | 
			
		||||
        else
 | 
			
		||||
            close_libgl();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (is_library_loaded("libGL.so", &libgl))
 | 
			
		||||
        return GL3W_OK;
 | 
			
		||||
    if (is_library_loaded("libGL.so.1", &libgl))
 | 
			
		||||
        return GL3W_OK;
 | 
			
		||||
    if (is_library_loaded("libGL.so.3", &libgl))
 | 
			
		||||
        return GL3W_OK;
 | 
			
		||||
 | 
			
		||||
    // Neither is already loaded, so we have to load one.  Try EGL first
 | 
			
		||||
    // because it is supported under both X11 and Wayland.
 | 
			
		||||
 | 
			
		||||
    // Load OpenGL + EGL
 | 
			
		||||
    libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
    libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
    if (libgl && libegl)
 | 
			
		||||
        return GL3W_OK;
 | 
			
		||||
    else
 | 
			
		||||
        close_libgl();
 | 
			
		||||
 | 
			
		||||
    // Fall back to legacy libGL, which includes GLX
 | 
			
		||||
    // While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983
 | 
			
		||||
    libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
    if (!libgl)
 | 
			
		||||
        libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
    if (!libgl)
 | 
			
		||||
        libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
 | 
			
		||||
    if (libgl)
 | 
			
		||||
        return GL3W_OK;
 | 
			
		||||
 | 
			
		||||
    return GL3W_ERROR_LIBRARY_OPEN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int open_libgl(void)
 | 
			
		||||
{
 | 
			
		||||
    int res = open_libs();
 | 
			
		||||
    if (res)
 | 
			
		||||
        return res;
 | 
			
		||||
 | 
			
		||||
    if (libegl)
 | 
			
		||||
        *(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
 | 
			
		||||
    else if (libglx)
 | 
			
		||||
        *(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
 | 
			
		||||
    else
 | 
			
		||||
        *(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
 | 
			
		||||
 | 
			
		||||
    if (!gl_get_proc_address) {
 | 
			
		||||
        close_libgl();
 | 
			
		||||
        return GL3W_ERROR_LIBRARY_OPEN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return GL3W_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GL3WglProc get_proc(const char* proc)
 | 
			
		||||
{
 | 
			
		||||
    GL3WglProc res = NULL;
 | 
			
		||||
 | 
			
		||||
    // Before EGL version 1.5, eglGetProcAddress doesn't support querying core
 | 
			
		||||
    // functions and may return a dummy function if we try, so try to load the
 | 
			
		||||
    // function from the GL library directly first.
 | 
			
		||||
    if (libegl)
 | 
			
		||||
        *(void**)(&res) = dlsym(libgl, proc);
 | 
			
		||||
 | 
			
		||||
    if (!res)
 | 
			
		||||
        res = gl_get_proc_address(proc);
 | 
			
		||||
 | 
			
		||||
    if (!libegl && !res)
 | 
			
		||||
        *(void**)(&res) = dlsym(libgl, proc);
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static struct { int major, minor; } version;
 | 
			
		||||
 | 
			
		||||
static int parse_version(void)
 | 
			
		||||
{
 | 
			
		||||
    if (!glGetIntegerv)
 | 
			
		||||
        return GL3W_ERROR_INIT;
 | 
			
		||||
    glGetIntegerv(GL_MAJOR_VERSION, &version.major);
 | 
			
		||||
    glGetIntegerv(GL_MINOR_VERSION, &version.minor);
 | 
			
		||||
    if (version.major == 0 && version.minor == 0)
 | 
			
		||||
    {
 | 
			
		||||
        // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
 | 
			
		||||
        if (const char* gl_version = (const char*)glGetString(GL_VERSION))
 | 
			
		||||
            sscanf(gl_version, "%d.%d", &version.major, &version.minor);
 | 
			
		||||
    }
 | 
			
		||||
    if (version.major < 2)
 | 
			
		||||
        return GL3W_ERROR_OPENGL_VERSION;
 | 
			
		||||
    return GL3W_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void load_procs(GL3WGetProcAddressProc proc);
 | 
			
		||||
 | 
			
		||||
int imgl3wInit(void)
 | 
			
		||||
{
 | 
			
		||||
    int res = open_libgl();
 | 
			
		||||
    if (res)
 | 
			
		||||
        return res;
 | 
			
		||||
    atexit(close_libgl);
 | 
			
		||||
    return imgl3wInit2(get_proc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int imgl3wInit2(GL3WGetProcAddressProc proc)
 | 
			
		||||
{
 | 
			
		||||
    load_procs(proc);
 | 
			
		||||
    return parse_version();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int imgl3wIsSupported(int major, int minor)
 | 
			
		||||
{
 | 
			
		||||
    if (major < 2)
 | 
			
		||||
        return 0;
 | 
			
		||||
    if (version.major == major)
 | 
			
		||||
        return version.minor >= minor;
 | 
			
		||||
    return version.major >= major;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }
 | 
			
		||||
 | 
			
		||||
static const char *proc_names[] = {
 | 
			
		||||
    "glActiveTexture",
 | 
			
		||||
    "glAttachShader",
 | 
			
		||||
    "glBindBuffer",
 | 
			
		||||
    "glBindSampler",
 | 
			
		||||
    "glBindTexture",
 | 
			
		||||
    "glBindVertexArray",
 | 
			
		||||
    "glBlendEquation",
 | 
			
		||||
    "glBlendEquationSeparate",
 | 
			
		||||
    "glBlendFuncSeparate",
 | 
			
		||||
    "glBufferData",
 | 
			
		||||
    "glBufferSubData",
 | 
			
		||||
    "glClear",
 | 
			
		||||
    "glClearColor",
 | 
			
		||||
    "glCompileShader",
 | 
			
		||||
    "glCreateProgram",
 | 
			
		||||
    "glCreateShader",
 | 
			
		||||
    "glDeleteBuffers",
 | 
			
		||||
    "glDeleteProgram",
 | 
			
		||||
    "glDeleteShader",
 | 
			
		||||
    "glDeleteTextures",
 | 
			
		||||
    "glDeleteVertexArrays",
 | 
			
		||||
    "glDetachShader",
 | 
			
		||||
    "glDisable",
 | 
			
		||||
    "glDisableVertexAttribArray",
 | 
			
		||||
    "glDrawElements",
 | 
			
		||||
    "glDrawElementsBaseVertex",
 | 
			
		||||
    "glEnable",
 | 
			
		||||
    "glEnableVertexAttribArray",
 | 
			
		||||
    "glFlush",
 | 
			
		||||
    "glGenBuffers",
 | 
			
		||||
    "glGenTextures",
 | 
			
		||||
    "glGenVertexArrays",
 | 
			
		||||
    "glGetAttribLocation",
 | 
			
		||||
    "glGetError",
 | 
			
		||||
    "glGetIntegerv",
 | 
			
		||||
    "glGetProgramInfoLog",
 | 
			
		||||
    "glGetProgramiv",
 | 
			
		||||
    "glGetShaderInfoLog",
 | 
			
		||||
    "glGetShaderiv",
 | 
			
		||||
    "glGetString",
 | 
			
		||||
    "glGetStringi",
 | 
			
		||||
    "glGetUniformLocation",
 | 
			
		||||
    "glGetVertexAttribPointerv",
 | 
			
		||||
    "glGetVertexAttribiv",
 | 
			
		||||
    "glIsEnabled",
 | 
			
		||||
    "glIsProgram",
 | 
			
		||||
    "glLinkProgram",
 | 
			
		||||
    "glPixelStorei",
 | 
			
		||||
    "glPolygonMode",
 | 
			
		||||
    "glReadPixels",
 | 
			
		||||
    "glScissor",
 | 
			
		||||
    "glShaderSource",
 | 
			
		||||
    "glTexImage2D",
 | 
			
		||||
    "glTexParameteri",
 | 
			
		||||
    "glTexSubImage2D",
 | 
			
		||||
    "glUniform1i",
 | 
			
		||||
    "glUniformMatrix4fv",
 | 
			
		||||
    "glUseProgram",
 | 
			
		||||
    "glVertexAttribPointer",
 | 
			
		||||
    "glViewport",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GL3W_API union ImGL3WProcs imgl3wProcs;
 | 
			
		||||
 | 
			
		||||
static void load_procs(GL3WGetProcAddressProc proc)
 | 
			
		||||
{
 | 
			
		||||
    size_t i;
 | 
			
		||||
    for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
 | 
			
		||||
        imgl3wProcs.ptr[i] = proc(proc_names[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,64 +0,0 @@
 | 
			
		|||
#include <GLFW/glfw3.h>
 | 
			
		||||
#include <imgui.h>
 | 
			
		||||
#include <input/key_codes.hpp>
 | 
			
		||||
#include <ui/gl/backend.hpp>
 | 
			
		||||
#include <ui/gl/ui.hpp>
 | 
			
		||||
#include <ui/glfw/glfw.h>
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
void glUserInterface::platform_implementation(
 | 
			
		||||
    GLFWwindow *windowHandle,
 | 
			
		||||
    Ref<SharedContext> /* shared_context */
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
	m_window_handle = windowHandle;
 | 
			
		||||
 | 
			
		||||
	ImGui_ImplGlfw_InitForOpenGL(windowHandle, false);
 | 
			
		||||
	ImGui_ImplOpenGL3_Init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
glUserInterface::~glUserInterface()
 | 
			
		||||
{
 | 
			
		||||
	// #todo: handle this in a better way
 | 
			
		||||
	auto &io = ImGui::GetIO();
 | 
			
		||||
 | 
			
		||||
	if (io.IniFilename == "default_gui_layout.ini")
 | 
			
		||||
	{
 | 
			
		||||
		io.IniFilename = "user_gui_layout.ini";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ImGui_ImplOpenGL3_Shutdown();
 | 
			
		||||
	ImGui_ImplGlfw_Shutdown();
 | 
			
		||||
	ImGui::DestroyContext();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void glUserInterface::begin()
 | 
			
		||||
{
 | 
			
		||||
	ImGui_ImplOpenGL3_NewFrame();
 | 
			
		||||
	ImGui_ImplGlfw_NewFrame();
 | 
			
		||||
	ImGui::NewFrame();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void glUserInterface::end()
 | 
			
		||||
{
 | 
			
		||||
	ImGui::Render();
 | 
			
		||||
	ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
 | 
			
		||||
 | 
			
		||||
	ImGui::UpdatePlatformWindows();
 | 
			
		||||
	ImGui::RenderPlatformWindowsDefault();
 | 
			
		||||
	glfwMakeContextCurrent(m_window_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void glUserInterface::log_debug_data()
 | 
			
		||||
{
 | 
			
		||||
	// #todo: improve
 | 
			
		||||
	log_inf("________________________________________");
 | 
			
		||||
	log_inf("UserInterface::");
 | 
			
		||||
	log_inf("       API    : ImGui");
 | 
			
		||||
	log_inf("       Version: {}", ImGui::GetVersion());
 | 
			
		||||
	log_inf("  GraphicsAPI : OpenGL");
 | 
			
		||||
	log_inf("________________________________________");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			@ -1,31 +0,0 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <ui/ui.hpp>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class glUserInterface: public UserInterface
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	glUserInterface() = default;
 | 
			
		||||
 | 
			
		||||
	~glUserInterface() override;
 | 
			
		||||
 | 
			
		||||
	void platform_implementation(
 | 
			
		||||
	    GLFWwindow *windowHandle,
 | 
			
		||||
	    Ref<SharedContext> sharedContext
 | 
			
		||||
	) override;
 | 
			
		||||
 | 
			
		||||
	void begin() override;
 | 
			
		||||
 | 
			
		||||
	void end() override;
 | 
			
		||||
 | 
			
		||||
	void log_debug_data() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	GLFWwindow *m_window_handle {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
# Disable all checks in this subdirectory
 | 
			
		||||
Checks: '-*'
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,74 +0,0 @@
 | 
			
		|||
// clang-format off
 | 
			
		||||
// dear imgui: Platform Backend for GLFW
 | 
			
		||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
 | 
			
		||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
 | 
			
		||||
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)
 | 
			
		||||
 | 
			
		||||
// Implemented features:
 | 
			
		||||
//  [X] Platform: Clipboard support.
 | 
			
		||||
//  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
 | 
			
		||||
//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 | 
			
		||||
//  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 | 
			
		||||
//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 | 
			
		||||
//  [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
 | 
			
		||||
//  [X] Multiple Dear ImGui contexts support.
 | 
			
		||||
// Missing features or Issues:
 | 
			
		||||
//  [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
 | 
			
		||||
//  [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
 | 
			
		||||
//  [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
 | 
			
		||||
 | 
			
		||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 | 
			
		||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 | 
			
		||||
// Learn about Dear ImGui:
 | 
			
		||||
// - FAQ                  https://dearimgui.com/faq
 | 
			
		||||
// - Getting Started      https://dearimgui.com/getting-started
 | 
			
		||||
// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 | 
			
		||||
// - Introduction, links and more at the top of imgui.cpp
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "imgui.h"      // IMGUI_IMPL_API
 | 
			
		||||
#ifndef IMGUI_DISABLE
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
struct GLFWmonitor;
 | 
			
		||||
 | 
			
		||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
 | 
			
		||||
IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
 | 
			
		||||
IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
 | 
			
		||||
IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_Shutdown();
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_NewFrame();
 | 
			
		||||
 | 
			
		||||
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
 | 
			
		||||
//static inline void    ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// GLFW callbacks install
 | 
			
		||||
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
 | 
			
		||||
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
 | 
			
		||||
 | 
			
		||||
// GFLW callbacks options:
 | 
			
		||||
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
 | 
			
		||||
 | 
			
		||||
// GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks)
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);        // Since 1.84
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);        // Since 1.84
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y);   // Since 1.87
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
 | 
			
		||||
 | 
			
		||||
// GLFW helpers
 | 
			
		||||
IMGUI_IMPL_API void     ImGui_ImplGlfw_Sleep(int milliseconds);
 | 
			
		||||
IMGUI_IMPL_API float    ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window);
 | 
			
		||||
IMGUI_IMPL_API float    ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef IMGUI_DISABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +25,7 @@ namespace lt {
 | 
			
		|||
 | 
			
		||||
UserInterface *UserInterface::s_context = nullptr;
 | 
			
		||||
 | 
			
		||||
auto UserInterface::create(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
 | 
			
		||||
    -> Scope<UserInterface>
 | 
			
		||||
auto UserInterface::create(Ref<SharedContext> sharedContext) -> Scope<UserInterface>
 | 
			
		||||
{
 | 
			
		||||
	auto scopeUserInterface = Scope<UserInterface> { nullptr };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +65,7 @@ UserInterface::UserInterface()
 | 
			
		|||
	s_context = this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UserInterface::init(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
 | 
			
		||||
void UserInterface::init(Ref<SharedContext> sharedContext)
 | 
			
		||||
{
 | 
			
		||||
	// create context
 | 
			
		||||
	IMGUI_CHECKVERSION();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,5 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <imgui.h>
 | 
			
		||||
 | 
			
		||||
struct GLFWwindow;
 | 
			
		||||
 | 
			
		||||
namespace lt {
 | 
			
		||||
 | 
			
		||||
class Event;
 | 
			
		||||
| 
						 | 
				
			
			@ -12,8 +8,7 @@ class SharedContext;
 | 
			
		|||
class UserInterface
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	static auto create(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
 | 
			
		||||
	    -> Scope<UserInterface>;
 | 
			
		||||
	static auto create(Ref<SharedContext> sharedContext) -> Scope<UserInterface>;
 | 
			
		||||
 | 
			
		||||
	static void dockspace_begin();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,12 +20,9 @@ public:
 | 
			
		|||
 | 
			
		||||
	virtual ~UserInterface() = default;
 | 
			
		||||
 | 
			
		||||
	void init(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext);
 | 
			
		||||
	void init(Ref<SharedContext> sharedContext);
 | 
			
		||||
 | 
			
		||||
	virtual void platform_implementation(
 | 
			
		||||
	    GLFWwindow *window_handle,
 | 
			
		||||
	    Ref<SharedContext> sharedContext
 | 
			
		||||
	) = 0;
 | 
			
		||||
	virtual void platform_implementation(Ref<SharedContext> sharedContext) = 0;
 | 
			
		||||
 | 
			
		||||
	virtual void begin() = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,8 +37,6 @@ private:
 | 
			
		|||
	static UserInterface *s_context;
 | 
			
		||||
 | 
			
		||||
	void set_dark_theme_colors();
 | 
			
		||||
 | 
			
		||||
	ImGuiWindowFlags m_dockspace_flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lt
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,6 @@ RUN pacman -Syu --noconfirm --disable-download-timeout \
 | 
			
		|||
    && pacman -S  --noconfirm --disable-download-timeout reflector \
 | 
			
		||||
    && reflector --verbose --latest 10 --protocol https --sort rate --save /etc/pacman.d/mirrorlist \
 | 
			
		||||
    && sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \
 | 
			
		||||
    && grep "ParallelDownloads" /etc/pacman.conf
 | 
			
		||||
 | 
			
		||||
RUN pacman -S --noconfirm --disable-download-timeout \
 | 
			
		||||
    bash \
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +13,7 @@ RUN pacman -S --noconfirm --disable-download-timeout \
 | 
			
		|||
    python \
 | 
			
		||||
    python-pip \
 | 
			
		||||
    clang \
 | 
			
		||||
    gcc \
 | 
			
		||||
    llvm \
 | 
			
		||||
    mesa \
 | 
			
		||||
    mold \
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,13 @@ RUN pacman -S --noconfirm --disable-download-timeout \
 | 
			
		|||
    wget \
 | 
			
		||||
    zlib \
 | 
			
		||||
    libc++ \
 | 
			
		||||
    libinput
 | 
			
		||||
    libinput \
 | 
			
		||||
    xorg-server-xvfb \
 | 
			
		||||
    libx11 \
 | 
			
		||||
    libxrandr \
 | 
			
		||||
    libxinerama \
 | 
			
		||||
    libxcursor \
 | 
			
		||||
    libxi
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,8 @@ rm -rf ./build
 | 
			
		|||
 | 
			
		||||
Xvfb :99 -screen 0 1024x768x16 &
 | 
			
		||||
export DISPLAY=:99
 | 
			
		||||
export CXX=$(which clang++)
 | 
			
		||||
export CC=$(which clang)
 | 
			
		||||
 | 
			
		||||
conan build . \
 | 
			
		||||
    -c tools.system.package_manager:mode=install \
 | 
			
		||||
| 
						 | 
				
			
			@ -37,11 +39,6 @@ LLVM_COV_SHOW=$(llvm-cov show \
 | 
			
		|||
        $(find ./build -type f -name '*\.a' -exec printf -- '-object %s ' {} \;) \
 | 
			
		||||
        -ignore-filename-regex='\.test\.cpp$' \
 | 
			
		||||
        -ignore-filename-regex='./external/' \
 | 
			
		||||
        -ignore-filename-regex='gl\/backend.cpp$' \
 | 
			
		||||
        -ignore-filename-regex='gl\/backend.hpp$' \
 | 
			
		||||
        -ignore-filename-regex='gl\/loader.hpp$' \
 | 
			
		||||
        -ignore-filename-regex='glfw\/glfw.h$' \
 | 
			
		||||
        -ignore-filename-regex='glfw\/glfw.cpp$'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
echo "${LLVM_COV_SHOW}" > './build/coverage/coverage.txt'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										72
									
								
								tools/ci/amd64/clang/fuzz.dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tools/ci/amd64/clang/fuzz.dockerfile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
FROM archlinux:base-devel
 | 
			
		||||
 | 
			
		||||
RUN pacman -Syyu --noconfirm && \
 | 
			
		||||
    pacman -S --noconfirm \
 | 
			
		||||
    bash \
 | 
			
		||||
    base-devel \
 | 
			
		||||
    clang \
 | 
			
		||||
    llvm \
 | 
			
		||||
    libc++ \
 | 
			
		||||
    cmake \
 | 
			
		||||
    git \
 | 
			
		||||
    python \
 | 
			
		||||
    python-pip \
 | 
			
		||||
    mesa \
 | 
			
		||||
    mold \
 | 
			
		||||
    ninja \
 | 
			
		||||
    zlib \
 | 
			
		||||
    libc++ \
 | 
			
		||||
    libinput \
 | 
			
		||||
    xorg-server-xvfb \
 | 
			
		||||
    libx11 \
 | 
			
		||||
    libxrandr \
 | 
			
		||||
    libxinerama \
 | 
			
		||||
    libxcursor \
 | 
			
		||||
    libxi \
 | 
			
		||||
    afl++ \
 | 
			
		||||
    afl-utils
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
 | 
			
		||||
RUN clang --version  \
 | 
			
		||||
    && conan --version \
 | 
			
		||||
    && pip --version \
 | 
			
		||||
    && cmake --version \
 | 
			
		||||
    && g++ --version \
 | 
			
		||||
    && clang --version \
 | 
			
		||||
    && ninja --version \
 | 
			
		||||
    && mold --version \
 | 
			
		||||
    && afl-fuzz --version \
 | 
			
		||||
    && afl-clang-lto --version \
 | 
			
		||||
    && afl-clang-lto++ --version
 | 
			
		||||
 | 
			
		||||
RUN git clone 'https://git.light7734.com/light7734/light.git' --depth=1 \
 | 
			
		||||
    && cd light \
 | 
			
		||||
    && export CC=$(which afl-clang-lto) \
 | 
			
		||||
    && export CXX=$(which afl-clang-lto++) \
 | 
			
		||||
    && export AR=$(which llvm-ar) \
 | 
			
		||||
    && export RANLIB=$(which llvm-ranlib) \
 | 
			
		||||
    && export AS=$(which llvm-as) \
 | 
			
		||||
    && conan install . \
 | 
			
		||||
        -c tools.system.package_manager:mode=install \
 | 
			
		||||
        -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
        -c tools.build:compiler_executables='{"c": "afl-clang-lto", "cpp": "afl-clang-lto++"}' \
 | 
			
		||||
        -s build_type=Release \
 | 
			
		||||
        -s compiler=clang \
 | 
			
		||||
        -s compiler.version=20 \
 | 
			
		||||
        -s compiler.libcxx=libc++ \
 | 
			
		||||
        -o use_mold=True \
 | 
			
		||||
        --build=missing \
 | 
			
		||||
    && conan install . \
 | 
			
		||||
        -c tools.system.package_manager:mode=install \
 | 
			
		||||
        -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
        -c tools.build:compiler_executables='{"c": "clang", "cpp": "clang++"}' \
 | 
			
		||||
        -s build_type=Release \
 | 
			
		||||
        -s compiler=clang \
 | 
			
		||||
        -s compiler.version=20 \
 | 
			
		||||
        -s compiler.libcxx=libc++ \
 | 
			
		||||
        -o use_mold=True \
 | 
			
		||||
        -o enable_llvm_coverage=True \
 | 
			
		||||
        --build=missing \
 | 
			
		||||
    && rm -r ../light/
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,15 @@ RUN pacman -Syu --noconfirm && \
 | 
			
		|||
    mold \
 | 
			
		||||
    ninja \
 | 
			
		||||
    zlib \
 | 
			
		||||
    libunwind
 | 
			
		||||
    libc++ \
 | 
			
		||||
    libinput \
 | 
			
		||||
    libunwind \
 | 
			
		||||
    xorg-server-xvfb \
 | 
			
		||||
    libx11 \
 | 
			
		||||
    libxrandr \
 | 
			
		||||
    libxinerama \
 | 
			
		||||
    libxcursor \
 | 
			
		||||
    libxi
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,17 @@ RUN pacman -Syu --noconfirm && \
 | 
			
		|||
    mold \
 | 
			
		||||
    ninja \
 | 
			
		||||
    zlib \
 | 
			
		||||
    libunwind
 | 
			
		||||
    libc++ \
 | 
			
		||||
    libinput \
 | 
			
		||||
    libunwind \
 | 
			
		||||
    xorg-server-xvfb \
 | 
			
		||||
    libx11 \
 | 
			
		||||
    libxrandr \
 | 
			
		||||
    libxinerama \
 | 
			
		||||
    libxcursor \
 | 
			
		||||
    libxi \
 | 
			
		||||
    xcb-util-cursor
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,22 +1,39 @@
 | 
			
		|||
FROM alpine:latest
 | 
			
		||||
FROM archlinux:base-devel
 | 
			
		||||
 | 
			
		||||
RUN apk add --no-cache \
 | 
			
		||||
RUN pacman -Syu --noconfirm --disable-download-timeout \
 | 
			
		||||
    && pacman -S --noconfirm --needed --disable-download-timeout reflector \
 | 
			
		||||
    && reflector --verbose --latest 10 --protocol https --sort rate --save /etc/pacman.d/mirrorlist \
 | 
			
		||||
    && sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 9/' /etc/pacman.conf
 | 
			
		||||
 | 
			
		||||
RUN pacman -S --noconfirm --needed --disable-download-timeout \
 | 
			
		||||
    bash \
 | 
			
		||||
    clang \
 | 
			
		||||
    llvm \
 | 
			
		||||
    cmake \
 | 
			
		||||
    base-devel \
 | 
			
		||||
    git \
 | 
			
		||||
    make \
 | 
			
		||||
    g++ \
 | 
			
		||||
    python3 \
 | 
			
		||||
    py3-pip \
 | 
			
		||||
    mesa-dev \
 | 
			
		||||
    mesa-gl \
 | 
			
		||||
    pkgconf \
 | 
			
		||||
    cmake \
 | 
			
		||||
    python \
 | 
			
		||||
    python-pip \
 | 
			
		||||
    clang \
 | 
			
		||||
    gcc \
 | 
			
		||||
    llvm \
 | 
			
		||||
    mesa \
 | 
			
		||||
    ninja \
 | 
			
		||||
    mold
 | 
			
		||||
    mold \
 | 
			
		||||
    curl \
 | 
			
		||||
    wget \
 | 
			
		||||
    zlib \
 | 
			
		||||
    libc++ \
 | 
			
		||||
    libinput \
 | 
			
		||||
    xorg-server-xvfb \
 | 
			
		||||
    libx11 \
 | 
			
		||||
    libxrandr \
 | 
			
		||||
    libxinerama \
 | 
			
		||||
    libxcursor \
 | 
			
		||||
    libxi \
 | 
			
		||||
    xcb-util-cursor
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages \
 | 
			
		||||
    conan \
 | 
			
		||||
    gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
 | 
			
		||||
RUN clang --version  \
 | 
			
		||||
| 
						 | 
				
			
			@ -28,11 +45,22 @@ RUN clang --version  \
 | 
			
		|||
    && ninja --version \
 | 
			
		||||
    && mold --version
 | 
			
		||||
 | 
			
		||||
RUN git clone 'https://git.light7734.com/light7734/light.git' \
 | 
			
		||||
# We `build` instead of `install` to make sure the project can be built with the current image state.
 | 
			
		||||
RUN git clone 'https://git.light7734.com/light7734/light.git' --depth=1 \
 | 
			
		||||
    && cd light \
 | 
			
		||||
    && conan install . \
 | 
			
		||||
        -s build_type=Release \
 | 
			
		||||
        -c tools.system.package_manager:mode=install \
 | 
			
		||||
        -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
        -o use_mold=True \
 | 
			
		||||
        --build=missing
 | 
			
		||||
    && conan build . \
 | 
			
		||||
    -c tools.system.package_manager:mode=install \
 | 
			
		||||
    -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
    -c tools.build:compiler_executables='{"c": "gcc", "cpp": "g++"}' \
 | 
			
		||||
    -s build_type=Release \
 | 
			
		||||
    -s compiler=gcc \
 | 
			
		||||
    -s compiler.version=15 \
 | 
			
		||||
    -s compiler.libcxx=libstdc++ \
 | 
			
		||||
    -o enable_unit_tests=True \
 | 
			
		||||
    -o enable_fuzz_tests=False \
 | 
			
		||||
    -o enable_llvm_coverage=False \
 | 
			
		||||
    -o enable_static_analysis=False \
 | 
			
		||||
    -o use_mold=True \
 | 
			
		||||
    -o export_compile_commands=False \
 | 
			
		||||
    --build=missing \
 | 
			
		||||
    && rm -rf ../light
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,6 @@ conan build . \
 | 
			
		|||
    -s compiler=gcc \
 | 
			
		||||
    -s compiler.version=15 \
 | 
			
		||||
    -s compiler.libcxx=libstdc++ \
 | 
			
		||||
    -o use_mold=True \
 | 
			
		||||
    -o enable_unit_tests=True \
 | 
			
		||||
    -o enable_fuzz_tests=False \
 | 
			
		||||
    -o enable_llvm_coverage=False \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,23 +1,41 @@
 | 
			
		|||
FROM alpine:latest
 | 
			
		||||
FROM archlinux:base-devel
 | 
			
		||||
 | 
			
		||||
RUN apk add --no-cache \
 | 
			
		||||
RUN pacman -Syu --noconfirm --disable-download-timeout \
 | 
			
		||||
    && pacman -S --noconfirm --needed --disable-download-timeout reflector \
 | 
			
		||||
    && reflector --verbose --latest 10 --protocol https --sort rate --save /etc/pacman.d/mirrorlist \
 | 
			
		||||
    && sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 9/' /etc/pacman.conf
 | 
			
		||||
 | 
			
		||||
RUN pacman -S --noconfirm --needed --disable-download-timeout \
 | 
			
		||||
    bash \
 | 
			
		||||
    clang \
 | 
			
		||||
    llvm \
 | 
			
		||||
    cmake \
 | 
			
		||||
    base-devel \
 | 
			
		||||
    git \
 | 
			
		||||
    make \
 | 
			
		||||
    g++ \
 | 
			
		||||
    python3 \
 | 
			
		||||
    py3-pip \
 | 
			
		||||
    mesa-dev \
 | 
			
		||||
    mesa-gl \
 | 
			
		||||
    pkgconf \
 | 
			
		||||
    cmake \
 | 
			
		||||
    python \
 | 
			
		||||
    python-pip \
 | 
			
		||||
    clang \
 | 
			
		||||
    gcc \
 | 
			
		||||
    llvm \
 | 
			
		||||
    mesa \
 | 
			
		||||
    ninja \
 | 
			
		||||
    mold \
 | 
			
		||||
    valgrind
 | 
			
		||||
    valgrind \
 | 
			
		||||
    curl \
 | 
			
		||||
    wget \
 | 
			
		||||
    zlib \
 | 
			
		||||
    libc++ \
 | 
			
		||||
    libinput \
 | 
			
		||||
    xorg-server-xvfb \
 | 
			
		||||
    libx11 \
 | 
			
		||||
    libxrandr \
 | 
			
		||||
    libxinerama \
 | 
			
		||||
    libxcursor \
 | 
			
		||||
    libxi \
 | 
			
		||||
    xcb-util-cursor
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages \
 | 
			
		||||
    conan \
 | 
			
		||||
    gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
 | 
			
		||||
RUN clang --version  \
 | 
			
		||||
| 
						 | 
				
			
			@ -27,13 +45,25 @@ RUN clang --version  \
 | 
			
		|||
    && g++ --version \
 | 
			
		||||
    && clang --version \
 | 
			
		||||
    && ninja --version \
 | 
			
		||||
    && mold --version
 | 
			
		||||
    && mold --version \
 | 
			
		||||
    && valgrind --version
 | 
			
		||||
 | 
			
		||||
RUN git clone 'https://git.light7734.com/light7734/light.git' \
 | 
			
		||||
# We `build` instead of `install` to make sure the project can be built with the current image state.
 | 
			
		||||
RUN git clone 'https://git.light7734.com/light7734/light.git' --depth=1 \
 | 
			
		||||
    && cd light \
 | 
			
		||||
    && conan install . \
 | 
			
		||||
        -s build_type=Release \
 | 
			
		||||
        -c tools.system.package_manager:mode=install \
 | 
			
		||||
        -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
        -o use_mold=True \
 | 
			
		||||
        --build=missing
 | 
			
		||||
    && conan build . \
 | 
			
		||||
    -c tools.system.package_manager:mode=install \
 | 
			
		||||
    -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
    -c tools.build:compiler_executables='{"c": "gcc", "cpp": "g++"}' \
 | 
			
		||||
    -s build_type=Release \
 | 
			
		||||
    -s compiler=gcc \
 | 
			
		||||
    -s compiler.version=15 \
 | 
			
		||||
    -s compiler.libcxx=libstdc++ \
 | 
			
		||||
    -o enable_unit_tests=True \
 | 
			
		||||
    -o enable_fuzz_tests=False \
 | 
			
		||||
    -o enable_llvm_coverage=False \
 | 
			
		||||
    -o enable_static_analysis=False \
 | 
			
		||||
    -o use_mold=True \
 | 
			
		||||
    -o export_compile_commands=False \
 | 
			
		||||
    --build=missing \
 | 
			
		||||
    && rm -rf ../light
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								tools/ci/documentation.dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tools/ci/documentation.dockerfile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
FROM alpine:latest
 | 
			
		||||
 | 
			
		||||
RUN apk add --no-cache \
 | 
			
		||||
    bash \
 | 
			
		||||
    clang \
 | 
			
		||||
    llvm \
 | 
			
		||||
    cmake \
 | 
			
		||||
    git \
 | 
			
		||||
    make \
 | 
			
		||||
    g++ \
 | 
			
		||||
    python3 \
 | 
			
		||||
    py3-pip \
 | 
			
		||||
    mesa-dev \
 | 
			
		||||
    mesa-gl \
 | 
			
		||||
    pkgconf \
 | 
			
		||||
    clang-extra-tools \
 | 
			
		||||
    mold \
 | 
			
		||||
    ninja \
 | 
			
		||||
    doxygen \
 | 
			
		||||
    openssh
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages \
 | 
			
		||||
    conan \
 | 
			
		||||
    gitpython \
 | 
			
		||||
    Sphinx \
 | 
			
		||||
    sphinx_rtd_theme \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,4 @@
 | 
			
		|||
find_package(glfw3 REQUIRED)
 | 
			
		||||
find_package(stb REQUIRED)
 | 
			
		||||
find_package(yaml-cpp REQUIRED)
 | 
			
		||||
find_package(EnTT REQUIRED)
 | 
			
		||||
find_package(opengl_system REQUIRED)
 | 
			
		||||
find_package(lz4 REQUIRED)
 | 
			
		||||
 | 
			
		||||
find_package(imgui REQUIRED)
 | 
			
		||||
add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD)
 | 
			
		||||
target_link_libraries(
 | 
			
		||||
  imgui::imgui
 | 
			
		||||
  INTERFACE glad
 | 
			
		||||
  INTERFACE opengl::opengl
 | 
			
		||||
  INTERFACE glfw
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,25 +3,34 @@
 | 
			
		|||
set -e
 | 
			
		||||
CI_DIR="$(git rev-parse --show-toplevel)/tools/ci/"
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: clang_format"
 | 
			
		||||
docker build -t clang_format -f $CI_DIR/static_analysis/clang_format.dockerfile .
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: static_analysis"
 | 
			
		||||
docker build -t clang_tidy -f $CI_DIR/static_analysis/clang_tidy.dockerfile .
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_gcc_unit_tests"
 | 
			
		||||
docker build -t amd64_gcc_unit_tests -f $CI_DIR/amd64/gcc/unit_tests.dockerfile .
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_gcc_valgrind"
 | 
			
		||||
docker build -t amd64_gcc_valgrind -f $CI_DIR/amd64/gcc/valgrind.dockerfile .
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_clang_coverage"
 | 
			
		||||
echo "===========[ amd64_clang ]==========="]
 | 
			
		||||
echo "==> Building amd64_clang_coverage..."
 | 
			
		||||
docker build -t amd64_clang_coverage -f $CI_DIR/amd64/clang/coverage.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_clang_lsan"
 | 
			
		||||
echo "==> Building amd64_clang_lsan..."
 | 
			
		||||
docker build -t amd64_clang_lsan -f $CI_DIR/amd64/clang/lsan.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_clang_msan"
 | 
			
		||||
docker build -t amd64_clang_msan -f $CI_DIR/amd64/clang/msan.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: clang_format"
 | 
			
		||||
docker build -t clang_format -f $CI_DIR/static_analysis/clang_format.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: static_analysis"
 | 
			
		||||
docker build -t clang_tidy -f $CI_DIR/static_analysis/clang_tidy.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "===========[ amd64_gcc ]==========="]
 | 
			
		||||
echo "==> Building image: amd64_gcc_unit_tests"
 | 
			
		||||
docker build -t amd64_gcc_unit_tests -f $CI_DIR/amd64/gcc/unit_tests.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_gcc_valgrind"
 | 
			
		||||
docker build -t amd64_gcc_valgrind -f $CI_DIR/amd64/gcc/valgrind.dockerfile .
 | 
			
		||||
echo "...DONE <=="
 | 
			
		||||
 | 
			
		||||
echo "WOOOOOOOOOOOOOOOOH!!! DONE :D"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue