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 ()
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/modules)
|
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(./asset_manager)
|
||||||
#
|
#
|
||||||
add_subdirectory(./camera)
|
add_subdirectory(./camera)
|
||||||
# add_subdirectory(./input)
|
add_subdirectory(./input)
|
||||||
# add_subdirectory(./ui)
|
# add_subdirectory(./ui)
|
||||||
#
|
#
|
||||||
add_subdirectory(./surface)
|
add_subdirectory(./surface)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
add_library_module(ecs entity.cpp scene.cpp uuid.cpp )
|
add_library_module(ecs entity.cpp scene.cpp uuid.cpp )
|
||||||
target_link_libraries(ecs
|
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)
|
add_library_module(input system.cpp)
|
||||||
target_link_libraries(input PUBLIC surface math imgui::imgui logger)
|
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>
|
#include <input/system.hpp>
|
||||||
|
|
||||||
namespace lt::input {
|
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
|
} // 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
|
#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 {
|
namespace lt::input {
|
||||||
|
|
||||||
template<class... Ts>
|
class System: public app::ISystem
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
System(lt::surface::System &surface_system)
|
System(Ref<ecs::Registry> registry);
|
||||||
{
|
|
||||||
surface_system.add_event_listener([this](auto &&event) {
|
auto tick() -> bool override;
|
||||||
return handle_event(std::forward<decltype(event)>(event));
|
|
||||||
});
|
void on_register() override;
|
||||||
};
|
|
||||||
|
void on_unregister() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto handle_event(const lt::surface::System::Event &event) -> bool
|
void handle_event(const surface::SurfaceComponent::Event &event);
|
||||||
{
|
|
||||||
const auto visitor = overloads {
|
|
||||||
[this](const lt::surface::KeyPressedEvent &event) {
|
|
||||||
m_keys[event.get_key()] = true;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
[](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; },
|
Ref<ecs::Registry> m_registry;
|
||||||
|
|
||||||
[](const auto &) { return false; },
|
|
||||||
};
|
|
||||||
|
|
||||||
return std::visit(visitor, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_callbacks(GLFWwindow *handle);
|
|
||||||
|
|
||||||
std::array<bool, 512> m_keys {};
|
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
|
struct mat4_impl
|
||||||
{
|
{
|
||||||
using Column_T = vec4_impl<T>;
|
using Column_T = vec4_impl<T>;
|
||||||
explicit mat4_impl(T scalar = 0)
|
constexpr explicit mat4_impl(T scalar = 0)
|
||||||
: values(
|
: values(
|
||||||
{
|
{
|
||||||
Column_T { scalar },
|
Column_T { scalar },
|
||||||
|
|
@ -22,7 +22,7 @@ struct mat4_impl
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
mat4_impl(
|
constexpr mat4_impl(
|
||||||
const T& x0, const T& y0, const T& z0, const T& w0,
|
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& x1, const T& y1, const T& z1, const T& w1,
|
||||||
const T& x2, const T& y2, const T& z2, const T& w2,
|
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_x,
|
||||||
const Column_T &column_y,
|
const Column_T &column_y,
|
||||||
const Column_T &column_z,
|
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];
|
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];
|
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> {};
|
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> {};
|
return vec4_impl<T> {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,28 @@ namespace lt::math {
|
||||||
template<typename T = float>
|
template<typename T = float>
|
||||||
struct vec2_impl
|
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
|
[[nodiscard]] auto operator*(const vec2_impl<T> &other) const -> vec2_impl
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
|
|
@ -41,12 +51,12 @@ struct vec2_impl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
T x; // NOLINT
|
T x; // NOLINT
|
||||||
|
|
||||||
T y; // NOLINT
|
T y; // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
using vec2 = vec2_impl<float>;
|
using vec2 = vec2_impl<float>;
|
||||||
|
|
||||||
using ivec2 = vec2_impl<int32_t>;
|
using ivec2 = vec2_impl<int32_t>;
|
||||||
|
|
@ -54,3 +64,17 @@ using ivec2 = vec2_impl<int32_t>;
|
||||||
using uvec2 = vec2_impl<uint32_t>;
|
using uvec2 = vec2_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // 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>
|
template<typename T = float>
|
||||||
struct vec3_impl
|
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 {
|
return {
|
||||||
x - other.x,
|
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 {
|
return {
|
||||||
x * other.x,
|
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 x; // NOLINT
|
||||||
|
|
||||||
T y; // NOLINT
|
T y; // NOLINT
|
||||||
|
|
@ -51,3 +67,17 @@ using ivec3 = vec3_impl<int32_t>;
|
||||||
using uvec3 = vec3_impl<uint32_t>;
|
using uvec3 = vec3_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // 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>
|
template<typename T = float>
|
||||||
struct vec4_impl
|
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 {
|
return {
|
||||||
x - other.x,
|
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];
|
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];
|
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
|
// NOLINTNEXTLINE
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
|
@ -76,3 +92,17 @@ using ivec4 = vec4_impl<int32_t>;
|
||||||
using uvec4 = vec4_impl<uint32_t>;
|
using uvec4 = vec4_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // 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
|
libmirror
|
||||||
INTERFACE
|
INTERFACE
|
||||||
app
|
app
|
||||||
opengl::opengl
|
time
|
||||||
|
input
|
||||||
surface
|
surface
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -16,4 +17,4 @@ add_test_module(libmirror
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable_module(mirror entrypoint/mirror.cpp)
|
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/application.hpp>
|
||||||
#include <app/entrypoint.hpp>
|
#include <app/entrypoint.hpp>
|
||||||
#include <app/system.hpp>
|
#include <app/system.hpp>
|
||||||
|
#include <ecs/entity.hpp>
|
||||||
|
#include <input/components.hpp>
|
||||||
|
#include <input/system.hpp>
|
||||||
#include <math/vec2.hpp>
|
#include <math/vec2.hpp>
|
||||||
|
#include <surface/events/keyboard.hpp>
|
||||||
|
#include <surface/events/surface.hpp>
|
||||||
#include <surface/system.hpp>
|
#include <surface/system.hpp>
|
||||||
|
#include <time/timer.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
template<class... Ts>
|
class MirrorSystem: public lt::app::ISystem
|
||||||
struct overloads: Ts...
|
|
||||||
{
|
{
|
||||||
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
|
class Mirror: public app::Application
|
||||||
|
|
@ -20,53 +105,99 @@ public:
|
||||||
m_editor_registry = create_ref<ecs::Registry>();
|
m_editor_registry = create_ref<ecs::Registry>();
|
||||||
|
|
||||||
setup_window_system();
|
setup_window_system();
|
||||||
|
setup_input_system();
|
||||||
|
|
||||||
register_systems();
|
register_systems();
|
||||||
|
}
|
||||||
|
|
||||||
m_window_system->add_event_listener(
|
void on_window_close()
|
||||||
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;
|
|
||||||
|
|
||||||
if (event.get_key() == 81)
|
|
||||||
{
|
{
|
||||||
unregister_system(m_window_system);
|
log_inf("Window close requested...");
|
||||||
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()
|
void setup_window_system()
|
||||||
{
|
{
|
||||||
|
using lt::input::InputComponent;
|
||||||
using lt::surface::SurfaceComponent;
|
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 = m_editor_registry->create_entity("Editor Window");
|
||||||
m_window.add_component<SurfaceComponent>(SurfaceComponent::CreateInfo {
|
m_window.add_component<SurfaceComponent>(SurfaceComponent::CreateInfo {
|
||||||
.title = "Editor Window",
|
.title = "Editor Window",
|
||||||
.resolution = { 800u, 600u },
|
.resolution = { 400u, 400u },
|
||||||
.vsync = true,
|
.vsync = true,
|
||||||
.visible = 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()
|
void register_systems()
|
||||||
{
|
{
|
||||||
register_system(m_window_system);
|
register_system(m_surface_system);
|
||||||
|
register_system(m_input_system);
|
||||||
|
register_system(m_mirror_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<ecs::Registry> m_editor_registry;
|
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;
|
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
|
renderer
|
||||||
PUBLIC camera
|
PUBLIC camera
|
||||||
PUBLIC input
|
PUBLIC input
|
||||||
PUBLIC glad
|
|
||||||
PUBLIC logger
|
PUBLIC logger
|
||||||
PUBLIC opengl::opengl
|
|
||||||
PUBLIC glfw
|
|
||||||
PUBLIC imgui
|
PUBLIC imgui
|
||||||
PUBLIC asset_parser
|
PUBLIC asset_parser
|
||||||
PUBLIC yaml-cpp::yaml-cpp
|
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 <renderer/renderer.hpp> // required for forward declaratio>
|
||||||
#include <ui/ui.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 {
|
namespace lt {
|
||||||
|
|
||||||
dxGraphicsContext::dxGraphicsContext(GLFWwindow *windowHandle)
|
dxGraphicsContext::dxGraphicsContext(): m_window_handle(windowHandle), m_debug_interface(nullptr)
|
||||||
: m_window_handle(windowHandle)
|
|
||||||
, m_debug_interface(nullptr)
|
|
||||||
{
|
{
|
||||||
// set 'GraphicsAPI';
|
// set 'GraphicsAPI';
|
||||||
m_graphics_api = GraphicsAPI::DirectX;
|
m_graphics_api = GraphicsAPI::DirectX;
|
||||||
|
|
@ -28,7 +22,7 @@ dxGraphicsContext::dxGraphicsContext(GLFWwindow *windowHandle)
|
||||||
setup_debug_interface();
|
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);
|
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.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
sd.BufferCount = 1u;
|
sd.BufferCount = 1u;
|
||||||
|
|
||||||
// #todo: don't handle Windows's window with glfw, create it yourself
|
sd.OutputWindow = {}; // ...
|
||||||
sd.OutputWindow = static_cast<HWND>(glfwGetWin32Window(windowHandle));
|
|
||||||
sd.Windowed = true;
|
sd.Windowed = true;
|
||||||
|
|
||||||
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,19 @@
|
||||||
#include <renderer/graphics_context.hpp>
|
#include <renderer/graphics_context.hpp>
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class dxGraphicsContext: public GraphicsContext
|
class dxGraphicsContext: public GraphicsContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
dxGraphicsContext(GLFWwindow *windowHandle);
|
dxGraphicsContext();
|
||||||
|
|
||||||
virtual void log_debug_data() override;
|
virtual void log_debug_data() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLFWwindow *m_window_handle;
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID3D11Debug> m_debug_interface;
|
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();
|
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 <ui/ui.hpp>
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class dxSharedContext;
|
class dxSharedContext;
|
||||||
|
|
@ -17,10 +15,7 @@ public:
|
||||||
|
|
||||||
~dxUserInterface();
|
~dxUserInterface();
|
||||||
|
|
||||||
void platform_implementation(
|
void platform_implementation(Ref<SharedContext> sharedContext) override;
|
||||||
GLFWwindow *windowHandle,
|
|
||||||
Ref<SharedContext> sharedContext
|
|
||||||
) override;
|
|
||||||
|
|
||||||
void begin() override;
|
void begin() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <renderer/gl/blender.hpp>
|
#include <renderer/gl/blender.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <logger/logger.hpp>
|
#include <logger/logger.hpp>
|
||||||
#include <renderer/gl/buffers.hpp>
|
#include <renderer/gl/buffers.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <renderer/gl/framebuffers.hpp>
|
#include <renderer/gl/framebuffers.hpp>
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <input/events/window.hpp>
|
#include <input/events/window.hpp>
|
||||||
#include <renderer/blender.hpp> // required for forward declaratio>
|
#include <renderer/blender.hpp> // required for forward declaratio>
|
||||||
#include <renderer/buffers.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/render_command.hpp> // required for forward declaratio>
|
||||||
#include <renderer/renderer.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 {
|
namespace lt {
|
||||||
|
|
||||||
glGraphicsContext::glGraphicsContext(GLFWwindow *windowHandle): m_window_handle(windowHandle)
|
glGraphicsContext::glGraphicsContext()
|
||||||
{
|
{
|
||||||
m_graphics_api = GraphicsAPI::OpenGL;
|
m_graphics_api = GraphicsAPI::OpenGL;
|
||||||
glfwMakeContextCurrent(windowHandle);
|
|
||||||
ensure(gladLoadGL(glfwGetProcAddress), "Failed to initialize opengl (glad)");
|
|
||||||
|
|
||||||
set_debug_message_callback();
|
set_debug_message_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,16 @@
|
||||||
|
|
||||||
#include <renderer/graphics_context.hpp>
|
#include <renderer/graphics_context.hpp>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class glGraphicsContext: public GraphicsContext
|
class glGraphicsContext: public GraphicsContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
glGraphicsContext(GLFWwindow *windowHandle);
|
glGraphicsContext();
|
||||||
|
|
||||||
void log_debug_data() override;
|
void log_debug_data() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLFWwindow *m_window_handle;
|
|
||||||
|
|
||||||
void set_debug_message_callback();
|
void set_debug_message_callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <renderer/gl/render_command.hpp>
|
#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 {
|
namespace lt {
|
||||||
|
|
||||||
glRenderCommand::glRenderCommand(GLFWwindow *windowHandle): m_window_handle(windowHandle)
|
glRenderCommand::glRenderCommand(): m_window_handle(windowHandle)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void glRenderCommand::swap_buffers()
|
void glRenderCommand::swap_buffers()
|
||||||
{
|
{
|
||||||
glfwSwapBuffers(m_window_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void glRenderCommand::clear_back_buffer(const math::vec4 &clearColor)
|
void glRenderCommand::clear_back_buffer(const math::vec4 &clearColor)
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,12 @@
|
||||||
#include <math/vec4.hpp>
|
#include <math/vec4.hpp>
|
||||||
#include <renderer/render_command.hpp>
|
#include <renderer/render_command.hpp>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class glRenderCommand: public RenderCommand
|
class glRenderCommand: public RenderCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
glRenderCommand(GLFWwindow *windowHandle);
|
glRenderCommand();
|
||||||
|
|
||||||
void swap_buffers() override;
|
void swap_buffers() override;
|
||||||
|
|
||||||
|
|
@ -28,9 +26,6 @@ public:
|
||||||
unsigned int width,
|
unsigned int width,
|
||||||
unsigned int height
|
unsigned int height
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
private:
|
|
||||||
GLFWwindow *m_window_handle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt
|
} // namespace lt
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
#include <asset_parser/assets/text.hpp>
|
#include <asset_parser/assets/text.hpp>
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <renderer/gl/shader.hpp>
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#include <asset_parser/assets/texture.hpp>
|
#include <asset_parser/assets/texture.hpp>
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <lt_debug/assertions.hpp>
|
#include <lt_debug/assertions.hpp>
|
||||||
#include <renderer/gl/texture.hpp>
|
#include <renderer/gl/texture.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include <ui/ui.hpp>
|
#include <ui/ui.hpp>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class glUserInterface: public UserInterface
|
class glUserInterface: public UserInterface
|
||||||
|
|
@ -14,19 +12,13 @@ public:
|
||||||
|
|
||||||
~glUserInterface() override;
|
~glUserInterface() override;
|
||||||
|
|
||||||
void platform_implementation(
|
void platform_implementation(Ref<SharedContext> sharedContext) override;
|
||||||
GLFWwindow *windowHandle,
|
|
||||||
Ref<SharedContext> sharedContext
|
|
||||||
) override;
|
|
||||||
|
|
||||||
void begin() override;
|
void begin() override;
|
||||||
|
|
||||||
void end() override;
|
void end() override;
|
||||||
|
|
||||||
void log_debug_data() override;
|
void log_debug_data() override;
|
||||||
|
|
||||||
private:
|
|
||||||
GLFWwindow *m_window_handle {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt
|
} // namespace lt
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <glad/gl.h>
|
|
||||||
#include <lt_debug/assertions.hpp>
|
#include <lt_debug/assertions.hpp>
|
||||||
#include <renderer/gl/buffers.hpp>
|
#include <renderer/gl/buffers.hpp>
|
||||||
#include <renderer/gl/vertex_layout.hpp>
|
#include <renderer/gl/vertex_layout.hpp>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ GraphicsContext *GraphicsContext::s_context = nullptr;
|
||||||
|
|
||||||
GraphicsContext::~GraphicsContext() = default;
|
GraphicsContext::~GraphicsContext() = default;
|
||||||
|
|
||||||
auto GraphicsContext::create(GraphicsAPI api, GLFWwindow *window_handle) -> Scope<GraphicsContext>
|
auto GraphicsContext::create(GraphicsAPI api) -> Scope<GraphicsContext>
|
||||||
{
|
{
|
||||||
delete s_context;
|
delete s_context;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,11 @@
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
auto RenderCommand::create(GLFWwindow *windowHandle, const Ref<SharedContext> & /*sharedContext*/)
|
auto RenderCommand::create(const Ref<SharedContext> & /*sharedContext*/) -> Scope<RenderCommand>
|
||||||
-> Scope<RenderCommand>
|
|
||||||
{
|
{
|
||||||
switch (GraphicsContext::get_graphics_api())
|
switch (GraphicsContext::get_graphics_api())
|
||||||
{
|
{
|
||||||
case GraphicsAPI::OpenGL: return create_scope<glRenderCommand>(windowHandle);
|
case GraphicsAPI::OpenGL: return create_scope<glRenderCommand>();
|
||||||
|
|
||||||
case GraphicsAPI::DirectX:
|
case GraphicsAPI::DirectX:
|
||||||
lt_win(
|
lt_win(
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,7 @@ namespace lt {
|
||||||
|
|
||||||
Renderer *Renderer::s_context = nullptr;
|
Renderer *Renderer::s_context = nullptr;
|
||||||
|
|
||||||
Renderer::Renderer(
|
Renderer::Renderer(const Ref<SharedContext> &shared_context, CreateInfo create_info)
|
||||||
GLFWwindow *window_handle,
|
|
||||||
const Ref<SharedContext> &shared_context,
|
|
||||||
CreateInfo create_info
|
|
||||||
)
|
|
||||||
: m_quad_renderer(
|
: m_quad_renderer(
|
||||||
create_scope<QuadRendererProgram>(
|
create_scope<QuadRendererProgram>(
|
||||||
LT_MAX_QUAD_RENDERER_VERTICES,
|
LT_MAX_QUAD_RENDERER_VERTICES,
|
||||||
|
|
@ -66,15 +62,9 @@ Renderer::~Renderer() // NOLINT
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Renderer::create(
|
auto Renderer::create(Ref<SharedContext> sharedContext, CreateInfo create_info) -> Scope<Renderer>
|
||||||
GLFWwindow *windowHandle,
|
|
||||||
Ref<SharedContext> sharedContext,
|
|
||||||
CreateInfo create_info
|
|
||||||
) -> Scope<Renderer>
|
|
||||||
{
|
{
|
||||||
return make_scope<Renderer>(
|
return make_scope<Renderer>(new Renderer(std::move(sharedContext), std::move(create_info)));
|
||||||
new Renderer(windowHandle, std::move(sharedContext), std::move(create_info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::on_window_resize(const WindowResizedEvent &event)
|
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))
|
System::System(InitRequirements requirements): m_registry(std::move(requirements.registry))
|
||||||
{
|
{
|
||||||
ensure(m_registry, "null registry");
|
ensure(m_registry, "null registry");
|
||||||
ensure(requirements.glfw_window_handle, "null glfw handle");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
System::~System() = default;
|
System::~System() = default;
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,8 @@ Suite raii = [] {
|
||||||
using lt::test::expect_throw;
|
using lt::test::expect_throw;
|
||||||
using renderer::System;
|
using renderer::System;
|
||||||
|
|
||||||
auto *window = static_cast<GLFWwindow *>(lt::Window::create([](auto &&PH1) {})->get_handle());
|
|
||||||
|
|
||||||
Case { "happy" } = [=] {
|
Case { "happy" } = [=] {
|
||||||
std::ignore = System { {
|
std::ignore = System { {
|
||||||
.glfw_window_handle = window,
|
|
||||||
.registry = create_ref<ecs::Registry>(),
|
.registry = create_ref<ecs::Registry>(),
|
||||||
} };
|
} };
|
||||||
};
|
};
|
||||||
|
|
@ -25,14 +22,12 @@ Suite raii = [] {
|
||||||
Case { "unhappy" } = [=] {
|
Case { "unhappy" } = [=] {
|
||||||
expect_throw([=] {
|
expect_throw([=] {
|
||||||
std::ignore = System { {
|
std::ignore = System { {
|
||||||
.glfw_window_handle = window,
|
|
||||||
.registry = {},
|
.registry = {},
|
||||||
} };
|
} };
|
||||||
});
|
});
|
||||||
|
|
||||||
expect_throw([=] {
|
expect_throw([=] {
|
||||||
std::ignore = System { {
|
std::ignore = System { {
|
||||||
.glfw_window_handle = {},
|
|
||||||
.registry = create_ref<ecs::Registry>(),
|
.registry = create_ref<ecs::Registry>(),
|
||||||
} };
|
} };
|
||||||
});
|
});
|
||||||
|
|
@ -42,7 +37,6 @@ Suite raii = [] {
|
||||||
for (auto idx : std::views::iota(0, 100'001))
|
for (auto idx : std::views::iota(0, 100'001))
|
||||||
{
|
{
|
||||||
std::ignore = System { {
|
std::ignore = System { {
|
||||||
.glfw_window_handle = window,
|
|
||||||
.registry = create_ref<ecs::Registry>(),
|
.registry = create_ref<ecs::Registry>(),
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class SharedContext;
|
class SharedContext;
|
||||||
|
|
@ -19,12 +17,7 @@ enum class GraphicsAPI
|
||||||
class GraphicsContext
|
class GraphicsContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static auto create(
|
static auto create(GraphicsAPI api) -> Scope<GraphicsContext>;
|
||||||
GraphicsAPI api,
|
|
||||||
GLFWwindow *window_handle
|
|
||||||
|
|
||||||
) -> Scope<GraphicsContext>;
|
|
||||||
|
|
||||||
GraphicsContext(const GraphicsContext &) = delete;
|
GraphicsContext(const GraphicsContext &) = delete;
|
||||||
|
|
||||||
GraphicsContext &operator=(const GraphicsContext &) = delete;
|
GraphicsContext &operator=(const GraphicsContext &) = delete;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
#include <math/vec4.hpp>
|
#include <math/vec4.hpp>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class SharedContext;
|
class SharedContext;
|
||||||
|
|
@ -11,8 +9,7 @@ class SharedContext;
|
||||||
class RenderCommand
|
class RenderCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static auto create(GLFWwindow *windowHandle, const Ref<SharedContext> &sharedContext)
|
static auto create(const Ref<SharedContext> &sharedContext) -> Scope<RenderCommand>;
|
||||||
-> Scope<RenderCommand>;
|
|
||||||
|
|
||||||
RenderCommand(const RenderCommand &) = delete;
|
RenderCommand(const RenderCommand &) = delete;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
#define LT_MAX_TEXTURE_RENDERER_VERTICES (1028u * 4u)
|
#define LT_MAX_TEXTURE_RENDERER_VERTICES (1028u * 4u)
|
||||||
#define LT_MAX_TINTED_TEXTURE_RENDERER_VERTICES (1028u * 4u)
|
#define LT_MAX_TINTED_TEXTURE_RENDERER_VERTICES (1028u * 4u)
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class ConstantBuffer;
|
class ConstantBuffer;
|
||||||
|
|
@ -42,11 +40,7 @@ public:
|
||||||
Ref<Shader> tinted_texture_renderer_shader;
|
Ref<Shader> tinted_texture_renderer_shader;
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto create(
|
static auto create(Ref<SharedContext> sharedContext, CreateInfo create_info) -> Scope<Renderer>;
|
||||||
GLFWwindow *windowHandle,
|
|
||||||
Ref<SharedContext> sharedContext,
|
|
||||||
CreateInfo create_info
|
|
||||||
) -> Scope<Renderer>;
|
|
||||||
|
|
||||||
static void draw_quad(
|
static void draw_quad(
|
||||||
const math::vec3 &position,
|
const math::vec3 &position,
|
||||||
|
|
@ -134,11 +128,7 @@ private:
|
||||||
|
|
||||||
bool m_should_clear_backbuffer { false };
|
bool m_should_clear_backbuffer { false };
|
||||||
|
|
||||||
Renderer(
|
Renderer(const Ref<SharedContext> &shared_context, CreateInfo create_info);
|
||||||
GLFWwindow *window_handle,
|
|
||||||
const Ref<SharedContext> &shared_context,
|
|
||||||
CreateInfo create_info
|
|
||||||
);
|
|
||||||
|
|
||||||
void draw_quad_impl(
|
void draw_quad_impl(
|
||||||
const math::vec3 &position,
|
const math::vec3 &position,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
#include <base/base.hpp>
|
#include <base/base.hpp>
|
||||||
#include <ecs/scene.hpp>
|
#include <ecs/scene.hpp>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt::renderer {
|
namespace lt::renderer {
|
||||||
|
|
||||||
/** The system for putting gore on your display
|
/** The system for putting gore on your display
|
||||||
|
|
@ -28,8 +26,6 @@ public:
|
||||||
/** The requirements for this system to initialize. */
|
/** The requirements for this system to initialize. */
|
||||||
struct InitRequirements
|
struct InitRequirements
|
||||||
{
|
{
|
||||||
GLFWwindow *glfw_window_handle;
|
|
||||||
|
|
||||||
Ref<ecs::Registry> registry;
|
Ref<ecs::Registry> registry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
namespace Assets {
|
namespace Assets {
|
||||||
|
|
||||||
class TextureAsset;
|
class TextureAsset;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
add_library_module(surface linux/system.cpp)
|
add_library_module(surface linux/system.cpp)
|
||||||
|
target_link_libraries(surface PRIVATE X11)
|
||||||
|
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
add_library_module(surface windows/system.cpp)
|
add_library_module(surface windows/system.cpp)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(surface PUBLIC
|
target_link_libraries(surface PUBLIC
|
||||||
ecs
|
ecs
|
||||||
app
|
app
|
||||||
PRIVATE
|
PRIVATE
|
||||||
glfw
|
|
||||||
logger
|
logger
|
||||||
lt_debug
|
lt_debug
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,143 +1,42 @@
|
||||||
#define GLFW_EXPOSE_NATIVE_X11
|
#include <ecs/components.hpp>
|
||||||
#include <GLFW/glfw3.h>
|
#include <surface/components.hpp>
|
||||||
#include <GLFW/glfw3native.h>
|
#include <surface/events/mouse.hpp>
|
||||||
|
#include <surface/requests/surface.hpp>
|
||||||
#include <surface/system.hpp>
|
#include <surface/system.hpp>
|
||||||
|
|
||||||
|
//
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <X11/keysymdef.h>
|
||||||
|
|
||||||
namespace lt::surface {
|
namespace lt::surface {
|
||||||
|
|
||||||
// This class is to ensure glfwInit/glfwTerminate is called only once and exactly when needed during
|
template<class... Ts>
|
||||||
// entire application runtime
|
struct overloads: Ts...
|
||||||
class GlfwSingleton
|
|
||||||
{
|
{
|
||||||
public:
|
using Ts::operator()...;
|
||||||
[[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)
|
void ensure_component_sanity(const SurfaceComponent &component);
|
||||||
{
|
|
||||||
log_err("GLFW ERROR: {} -> {}", code, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_event(GLFWwindow *window, const SurfaceComponent::Event &event)
|
constexpr auto all_events_mask = KeyPressMask | //
|
||||||
{
|
KeyReleaseMask | //
|
||||||
auto &callbacks = *static_cast<std::vector<SurfaceComponent::EventCallback> *>(
|
ButtonPressMask | //
|
||||||
glfwGetWindowUserPointer(window)
|
ButtonReleaseMask | //
|
||||||
);
|
EnterWindowMask | //
|
||||||
|
LeaveWindowMask | //
|
||||||
for (auto &callback : callbacks)
|
PointerMotionMask | //
|
||||||
{
|
KeymapStateMask | //
|
||||||
if (callback(event))
|
ExposureMask | //
|
||||||
{
|
VisibilityChangeMask | //
|
||||||
return;
|
StructureNotifyMask | //
|
||||||
}
|
FocusChangeMask | //
|
||||||
}
|
ColormapChangeMask | //
|
||||||
}
|
OwnerGrabButtonMask;
|
||||||
|
|
||||||
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))
|
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(m_registry, "Failed to initialize surface system: null registry");
|
||||||
|
|
||||||
ensure(
|
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)
|
void System::on_surface_construct(entt::registry ®istry, entt::entity entity)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto &surface = registry.get<SurfaceComponent>(entity);
|
auto &surface = registry.get<SurfaceComponent>(entity);
|
||||||
|
const auto &resolution = surface.get_resolution();
|
||||||
|
const auto &position = surface.get_position();
|
||||||
ensure_component_sanity(surface);
|
ensure_component_sanity(surface);
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
// TODO(Light): refactor "environment" into standalone module
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
auto *display_env = std::getenv("DISPLAY");
|
||||||
|
ensure(display_env != nullptr, "DISPLAY env var not found!");
|
||||||
|
|
||||||
surface.m_glfw_handle = glfwCreateWindow(
|
auto *display = XOpenDisplay(display_env);
|
||||||
static_cast<int>(surface.get_resolution().x),
|
auto root_window = XDefaultRootWindow(display);
|
||||||
static_cast<int>(surface.get_resolution().y),
|
|
||||||
surface.get_title().begin(),
|
auto border_width = 0;
|
||||||
nullptr,
|
auto depth = int32_t { CopyFromParent };
|
||||||
nullptr
|
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_data.wm_delete_message = XInternAtom(display, "WM_DELETE_WINDOW", False);
|
||||||
surface.m_native_handle = glfwGetX11Window(surface.m_glfw_handle);
|
XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1);
|
||||||
bind_glfw_events(surface.m_glfw_handle);
|
|
||||||
|
// 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 (...)
|
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)
|
void System::on_surface_update(entt::registry ®istry, entt::entity entity)
|
||||||
{
|
{
|
||||||
auto &surface = registry.get<SurfaceComponent>(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)
|
void System::on_surface_destroy(entt::registry ®istry, entt::entity entity)
|
||||||
{
|
{
|
||||||
auto &surface = registry.get<SurfaceComponent>(entity);
|
const auto &[display, window, _] = registry.get<SurfaceComponent>(entity).get_native_data();
|
||||||
|
if (!display)
|
||||||
if (surface.m_glfw_handle)
|
|
||||||
{
|
{
|
||||||
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;
|
for (const auto &request : surface.peek_requests())
|
||||||
glfwSetWindowTitle(surface.m_glfw_handle, surface.m_title.c_str());
|
{
|
||||||
|
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
|
auto System::tick() -> bool
|
||||||
{
|
{
|
||||||
m_registry->view<SurfaceComponent>().each([](SurfaceComponent &surface) {
|
m_registry->view<SurfaceComponent>().each([this](SurfaceComponent &surface) {
|
||||||
glfwSwapBuffers(surface.m_glfw_handle);
|
handle_requests(surface);
|
||||||
|
|
||||||
|
handle_events(surface);
|
||||||
});
|
});
|
||||||
|
|
||||||
glfwPollEvents();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::set_size(ecs::Entity surface_entity, const math::uvec2 &new_size)
|
void ensure_component_sanity(const SurfaceComponent &component)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
auto [width, height] = component.get_resolution();
|
auto [width, height] = component.get_resolution();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
|
#include <ecs/entity.hpp>
|
||||||
#include <ecs/scene.hpp>
|
#include <ecs/scene.hpp>
|
||||||
|
#include <surface/components.hpp>
|
||||||
#include <surface/system.hpp>
|
#include <surface/system.hpp>
|
||||||
#include <test/fuzz.hpp>
|
#include <test/fuzz.hpp>
|
||||||
#include <test/test.hpp>
|
#include <test/test.hpp>
|
||||||
|
|
||||||
namespace lt::surface {
|
namespace lt::surface {
|
||||||
|
|
||||||
enum class Action : uint8_t
|
enum class FuzzAction : uint8_t
|
||||||
{
|
{
|
||||||
create_entity,
|
create_entity,
|
||||||
|
|
||||||
|
|
@ -13,7 +15,22 @@ enum class Action : uint8_t
|
||||||
|
|
||||||
destroy_surface_component,
|
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)
|
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()
|
void check_invariants()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -67,9 +92,14 @@ test::FuzzHarness harness = [](const uint8_t *data, size_t size) {
|
||||||
|
|
||||||
while (auto action = provider.consume<uint8_t>())
|
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 length = std::min(provider.consume<uint32_t>().value_or(16), 255u);
|
||||||
const auto tag = provider.consume_string(length).value_or("");
|
const auto tag = provider.consume_string(length).value_or("");
|
||||||
|
|
@ -77,17 +107,36 @@ test::FuzzHarness harness = [](const uint8_t *data, size_t size) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Action::create_surface_component:
|
case FuzzAction::create_surface_component:
|
||||||
{
|
{
|
||||||
create_surface_component(provider, *registry);
|
create_surface_component(provider, *registry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Action::destroy_surface_component:
|
case FuzzAction::destroy_surface_component:
|
||||||
{
|
{
|
||||||
remove_surface_component(*registry);
|
remove_surface_component(*registry);
|
||||||
break;
|
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();
|
system.tick();
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include <ecs/entity.hpp>
|
||||||
|
#include <surface/components.hpp>
|
||||||
|
#include <surface/requests/surface.hpp>
|
||||||
#include <surface/system.hpp>
|
#include <surface/system.hpp>
|
||||||
#include <test/test.hpp>
|
#include <test/test.hpp>
|
||||||
|
|
||||||
|
|
@ -18,6 +21,13 @@ constexpr auto height = 600u;
|
||||||
constexpr auto vsync = true;
|
constexpr auto vsync = true;
|
||||||
constexpr auto visible = false;
|
constexpr auto visible = false;
|
||||||
|
|
||||||
|
template<class... Ts>
|
||||||
|
struct overloads: Ts...
|
||||||
|
{
|
||||||
|
using Ts::operator()...;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Fixture
|
class Fixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -41,7 +51,11 @@ public:
|
||||||
|
|
||||||
void check_values(const SurfaceComponent &component)
|
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().x, width);
|
||||||
expect_eq(component.get_resolution().y, height);
|
expect_eq(component.get_resolution().y, height);
|
||||||
expect_eq(component.get_title(), title);
|
expect_eq(component.get_title(), title);
|
||||||
|
|
@ -61,9 +75,7 @@ Suite raii = [] {
|
||||||
|
|
||||||
Case { "many won't freeze/throw" } = [] {
|
Case { "many won't freeze/throw" } = [] {
|
||||||
auto fixture = Fixture {};
|
auto fixture = Fixture {};
|
||||||
|
for (auto idx : std::views::iota(0, 250))
|
||||||
/* range is small since glfw init/terminate is slow. */
|
|
||||||
for (auto idx : std::views::iota(0, 100))
|
|
||||||
{
|
{
|
||||||
ignore = System { fixture.registry() };
|
ignore = System { fixture.registry() };
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +86,7 @@ Suite raii = [] {
|
||||||
|
|
||||||
auto fixture = Fixture {};
|
auto fixture = Fixture {};
|
||||||
fixture.add_surface_component();
|
fixture.add_surface_component();
|
||||||
expect_throw([&] { ignore = System { { fixture.registry() } }; });
|
expect_throw([&] { ignore = System { fixture.registry() }; });
|
||||||
};
|
};
|
||||||
|
|
||||||
Case { "post construct has correct state" } = [] {
|
Case { "post construct has correct state" } = [] {
|
||||||
|
|
@ -107,8 +119,8 @@ Suite system_events = [] {
|
||||||
Case { "on_unregister won't throw" } = [] {
|
Case { "on_unregister won't throw" } = [] {
|
||||||
auto fixture = Fixture {};
|
auto fixture = Fixture {};
|
||||||
auto system = System { fixture.registry() };
|
auto system = System { fixture.registry() };
|
||||||
system.on_register();
|
|
||||||
|
|
||||||
|
system.on_register();
|
||||||
system.on_unregister();
|
system.on_unregister();
|
||||||
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
|
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
|
||||||
};
|
};
|
||||||
|
|
@ -185,14 +197,73 @@ Suite tick = [] {
|
||||||
fixture.add_surface_component();
|
fixture.add_surface_component();
|
||||||
system.tick();
|
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 <surface/system.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace lt::surface {
|
namespace lt::surface {
|
||||||
|
|
||||||
// This class is to ensure glfwInit/glfwTerminate is called only once and exactly when needed during
|
System::System(Ref<ecs::Registry> registry, Ref<app::EventMediator> event_mediator)
|
||||||
// entire application runtime
|
: m_registry(std::move(registry))
|
||||||
class GlfwSingleton
|
, 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(m_registry, "Failed to initialize surface system: null registry");
|
||||||
|
|
||||||
ensure(
|
ensure(
|
||||||
|
|
@ -183,24 +52,9 @@ void System::on_surface_construct(entt::registry ®istry, entt::entity entity)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto &surface = registry.get<SurfaceComponent>(entity);
|
auto &surface = registry.get<SurfaceComponent>(entity);
|
||||||
|
const auto &resolution = surface.get_resolution();
|
||||||
|
const auto &position = surface.get_position();
|
||||||
ensure_component_sanity(surface);
|
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 (...)
|
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)
|
void System::on_surface_update(entt::registry ®istry, entt::entity entity)
|
||||||
{
|
{
|
||||||
auto &surface = registry.get<SurfaceComponent>(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)
|
void System::on_surface_destroy(entt::registry ®istry, entt::entity entity)
|
||||||
{
|
{
|
||||||
auto &surface = registry.get<SurfaceComponent>(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)
|
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>();
|
auto &surface = entity.get_component<SurfaceComponent>();
|
||||||
|
|
||||||
surface.m_title = new_title;
|
surface.m_title = new_title;
|
||||||
glfwSetWindowTitle(surface.m_glfw_handle, surface.m_title.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto System::tick() -> bool
|
auto System::tick() -> bool
|
||||||
{
|
{
|
||||||
m_registry->view<SurfaceComponent>().each([](SurfaceComponent &surface) {
|
|
||||||
glfwSwapBuffers(surface.m_glfw_handle);
|
|
||||||
});
|
|
||||||
|
|
||||||
glfwPollEvents();
|
|
||||||
return false;
|
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>();
|
auto &surface = surface_entity.get_component<SurfaceComponent>();
|
||||||
surface.m_resolution = new_size;
|
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)
|
void System::set_v_sync(ecs::Entity surface_entity, bool vsync)
|
||||||
{
|
{
|
||||||
auto &surface = surface_entity.get_component<SurfaceComponent>();
|
auto &surface = surface_entity.get_component<SurfaceComponent>();
|
||||||
surface.m_vsync = vsync;
|
surface.m_vsync = vsync;
|
||||||
|
|
||||||
glfwSwapInterval(vsync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::set_visibility(ecs::Entity surface_entity, bool visible)
|
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)
|
if (visible)
|
||||||
{
|
{
|
||||||
glfwShowWindow(surface.m_glfw_handle);
|
|
||||||
}
|
}
|
||||||
else
|
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 System::ensure_component_sanity(const SurfaceComponent &component)
|
||||||
{
|
{
|
||||||
auto [width, height] = component.get_resolution();
|
auto [width, height] = component.get_resolution();
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,14 @@
|
||||||
#include <surface/events/keyboard.hpp>
|
#include <surface/events/keyboard.hpp>
|
||||||
#include <surface/events/mouse.hpp>
|
#include <surface/events/mouse.hpp>
|
||||||
#include <surface/events/surface.hpp>
|
#include <surface/events/surface.hpp>
|
||||||
|
#include <surface/requests/surface.hpp>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
struct GLFWwindow;
|
typedef struct _XDisplay Display;
|
||||||
|
|
||||||
namespace lt::surface {
|
namespace lt::surface {
|
||||||
|
|
||||||
/** Represents a platform's surface (eg. a Window).
|
/** Represents a platform's surface (eg. a Window). */
|
||||||
*
|
|
||||||
* @note Read-only component, should only be modified through a system.
|
|
||||||
*/
|
|
||||||
class SurfaceComponent
|
class SurfaceComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -29,23 +27,27 @@ public:
|
||||||
|
|
||||||
// keyboard events
|
// keyboard events
|
||||||
KeyPressedEvent,
|
KeyPressedEvent,
|
||||||
KeyRepeatEvent,
|
|
||||||
KeyReleasedEvent,
|
KeyReleasedEvent,
|
||||||
KeySetCharEvent,
|
|
||||||
|
|
||||||
// mouse events
|
// mouse events
|
||||||
MouseMovedEvent,
|
MouseMovedEvent,
|
||||||
WheelScrolledEvent,
|
|
||||||
ButtonPressedEvent,
|
ButtonPressedEvent,
|
||||||
ButtonReleasedEvent>;
|
ButtonReleasedEvent>;
|
||||||
|
|
||||||
using EventCallback = std::function<bool(const Event &)>;
|
using Request = std::variant<
|
||||||
|
ModifyTitleRequest,
|
||||||
|
ModifyResolutionRequest,
|
||||||
|
ModifyPositionRequest,
|
||||||
|
ModifyVisibilityRequest>;
|
||||||
|
|
||||||
using WindowsNativeHandle = void *;
|
#ifdef LIGHT_PLATFORM_LINUX
|
||||||
|
struct NativeData
|
||||||
using X11NativeHandle = unsigned long;
|
{
|
||||||
|
Display *display;
|
||||||
using NativeHandle = std::variant<WindowsNativeHandle, X11NativeHandle>;
|
uint32_t window;
|
||||||
|
unsigned long wm_delete_message;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static constexpr auto max_dimension = 4096;
|
static constexpr auto max_dimension = 4096;
|
||||||
|
|
||||||
|
|
@ -67,6 +69,7 @@ public:
|
||||||
, m_resolution(info.resolution)
|
, m_resolution(info.resolution)
|
||||||
, m_vsync(info.vsync)
|
, m_vsync(info.vsync)
|
||||||
, m_visible(info.visible)
|
, m_visible(info.visible)
|
||||||
|
, m_native_data({})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +83,11 @@ public:
|
||||||
return m_resolution;
|
return m_resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_position() const -> const math::ivec2 &
|
||||||
|
{
|
||||||
|
return m_position;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto is_vsync() const -> bool
|
[[nodiscard]] auto is_vsync() const -> bool
|
||||||
{
|
{
|
||||||
return m_vsync;
|
return m_vsync;
|
||||||
|
|
@ -90,30 +98,48 @@ public:
|
||||||
return m_visible;
|
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:
|
private:
|
||||||
[[nodiscard]] auto get_glfw_handle() const -> GLFWwindow *
|
|
||||||
{
|
|
||||||
return m_glfw_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_title;
|
std::string m_title;
|
||||||
|
|
||||||
math::uvec2 m_resolution;
|
math::uvec2 m_resolution;
|
||||||
|
|
||||||
|
math::ivec2 m_position;
|
||||||
|
|
||||||
bool m_vsync;
|
bool m_vsync;
|
||||||
|
|
||||||
bool m_visible;
|
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
|
} // namespace lt::surface
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ namespace lt::surface {
|
||||||
class KeyPressedEvent
|
class KeyPressedEvent
|
||||||
{
|
{
|
||||||
public:
|
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;
|
return m_key;
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t m_key;
|
uint32_t m_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyRepeatEvent
|
class KeyRepeatEvent
|
||||||
|
|
@ -32,7 +32,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_key() const -> int32_t
|
[[nodiscard]] auto get_key() const -> uint32_t
|
||||||
{
|
{
|
||||||
return m_key;
|
return m_key;
|
||||||
}
|
}
|
||||||
|
|
@ -43,17 +43,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t m_key;
|
uint32_t m_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyReleasedEvent
|
class KeyReleasedEvent
|
||||||
{
|
{
|
||||||
public:
|
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;
|
return m_key;
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t m_key;
|
uint32_t m_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeySetCharEvent
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <app/system.hpp>
|
#include <app/system.hpp>
|
||||||
#include <ecs/entity.hpp>
|
|
||||||
#include <ecs/scene.hpp>
|
#include <ecs/scene.hpp>
|
||||||
#include <surface/components.hpp>
|
|
||||||
|
|
||||||
namespace lt::surface {
|
namespace lt::surface {
|
||||||
|
|
||||||
|
|
@ -22,26 +20,12 @@ public:
|
||||||
|
|
||||||
auto operator=(const System &) -> System & = delete;
|
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;
|
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:
|
private:
|
||||||
void on_surface_construct(entt::registry ®istry, entt::entity entity);
|
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 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;
|
Ref<ecs::Registry> m_registry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace lt::surface
|
} // namespace lt::surface
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@
|
||||||
namespace lt::test {
|
namespace lt::test {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Printable = requires(std::ostream &stream, T value) {
|
concept Formattable = requires(T &v, std::format_context ctx) {
|
||||||
{ stream << value } -> std::same_as<std::ostream &>;
|
std::formatter<std::remove_cvref_t<T>>().format(v, ctx);
|
||||||
} || requires(std::ostream &stream, T value) {
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Printable = Formattable<T> || requires(std::ostream &stream, T value) {
|
||||||
{ stream << std::to_underlying<T>(value) } -> std::same_as<std::ostream &>;
|
{ 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)
|
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;
|
UserInterface *UserInterface::s_context = nullptr;
|
||||||
|
|
||||||
auto UserInterface::create(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
|
auto UserInterface::create(Ref<SharedContext> sharedContext) -> Scope<UserInterface>
|
||||||
-> Scope<UserInterface>
|
|
||||||
{
|
{
|
||||||
auto scopeUserInterface = Scope<UserInterface> { nullptr };
|
auto scopeUserInterface = Scope<UserInterface> { nullptr };
|
||||||
|
|
||||||
|
|
@ -66,7 +65,7 @@ UserInterface::UserInterface()
|
||||||
s_context = this;
|
s_context = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInterface::init(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
|
void UserInterface::init(Ref<SharedContext> sharedContext)
|
||||||
{
|
{
|
||||||
// create context
|
// create context
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
class Event;
|
class Event;
|
||||||
|
|
@ -12,8 +8,7 @@ class SharedContext;
|
||||||
class UserInterface
|
class UserInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static auto create(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
|
static auto create(Ref<SharedContext> sharedContext) -> Scope<UserInterface>;
|
||||||
-> Scope<UserInterface>;
|
|
||||||
|
|
||||||
static void dockspace_begin();
|
static void dockspace_begin();
|
||||||
|
|
||||||
|
|
@ -25,12 +20,9 @@ public:
|
||||||
|
|
||||||
virtual ~UserInterface() = default;
|
virtual ~UserInterface() = default;
|
||||||
|
|
||||||
void init(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext);
|
void init(Ref<SharedContext> sharedContext);
|
||||||
|
|
||||||
virtual void platform_implementation(
|
virtual void platform_implementation(Ref<SharedContext> sharedContext) = 0;
|
||||||
GLFWwindow *window_handle,
|
|
||||||
Ref<SharedContext> sharedContext
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual void begin() = 0;
|
virtual void begin() = 0;
|
||||||
|
|
||||||
|
|
@ -45,8 +37,6 @@ private:
|
||||||
static UserInterface *s_context;
|
static UserInterface *s_context;
|
||||||
|
|
||||||
void set_dark_theme_colors();
|
void set_dark_theme_colors();
|
||||||
|
|
||||||
ImGuiWindowFlags m_dockspace_flags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt
|
} // namespace lt
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ RUN pacman -Syu --noconfirm --disable-download-timeout \
|
||||||
&& pacman -S --noconfirm --disable-download-timeout reflector \
|
&& pacman -S --noconfirm --disable-download-timeout reflector \
|
||||||
&& reflector --verbose --latest 10 --protocol https --sort rate --save /etc/pacman.d/mirrorlist \
|
&& reflector --verbose --latest 10 --protocol https --sort rate --save /etc/pacman.d/mirrorlist \
|
||||||
&& sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \
|
&& sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \
|
||||||
&& grep "ParallelDownloads" /etc/pacman.conf
|
|
||||||
|
|
||||||
RUN pacman -S --noconfirm --disable-download-timeout \
|
RUN pacman -S --noconfirm --disable-download-timeout \
|
||||||
bash \
|
bash \
|
||||||
|
|
@ -14,6 +13,7 @@ RUN pacman -S --noconfirm --disable-download-timeout \
|
||||||
python \
|
python \
|
||||||
python-pip \
|
python-pip \
|
||||||
clang \
|
clang \
|
||||||
|
gcc \
|
||||||
llvm \
|
llvm \
|
||||||
mesa \
|
mesa \
|
||||||
mold \
|
mold \
|
||||||
|
|
@ -22,7 +22,13 @@ RUN pacman -S --noconfirm --disable-download-timeout \
|
||||||
wget \
|
wget \
|
||||||
zlib \
|
zlib \
|
||||||
libc++ \
|
libc++ \
|
||||||
libinput
|
libinput \
|
||||||
|
xorg-server-xvfb \
|
||||||
|
libx11 \
|
||||||
|
libxrandr \
|
||||||
|
libxinerama \
|
||||||
|
libxcursor \
|
||||||
|
libxi
|
||||||
|
|
||||||
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
|
&& conan profile detect
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ rm -rf ./build
|
||||||
|
|
||||||
Xvfb :99 -screen 0 1024x768x16 &
|
Xvfb :99 -screen 0 1024x768x16 &
|
||||||
export DISPLAY=:99
|
export DISPLAY=:99
|
||||||
|
export CXX=$(which clang++)
|
||||||
|
export CC=$(which clang)
|
||||||
|
|
||||||
conan build . \
|
conan build . \
|
||||||
-c tools.system.package_manager:mode=install \
|
-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 ' {} \;) \
|
$(find ./build -type f -name '*\.a' -exec printf -- '-object %s ' {} \;) \
|
||||||
-ignore-filename-regex='\.test\.cpp$' \
|
-ignore-filename-regex='\.test\.cpp$' \
|
||||||
-ignore-filename-regex='./external/' \
|
-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'
|
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 \
|
mold \
|
||||||
ninja \
|
ninja \
|
||||||
zlib \
|
zlib \
|
||||||
libunwind
|
libc++ \
|
||||||
|
libinput \
|
||||||
|
libunwind \
|
||||||
|
xorg-server-xvfb \
|
||||||
|
libx11 \
|
||||||
|
libxrandr \
|
||||||
|
libxinerama \
|
||||||
|
libxcursor \
|
||||||
|
libxi
|
||||||
|
|
||||||
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
|
&& conan profile detect
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,17 @@ RUN pacman -Syu --noconfirm && \
|
||||||
mold \
|
mold \
|
||||||
ninja \
|
ninja \
|
||||||
zlib \
|
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 \
|
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
|
||||||
&& conan profile detect
|
&& 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 \
|
bash \
|
||||||
clang \
|
base-devel \
|
||||||
llvm \
|
|
||||||
cmake \
|
|
||||||
git \
|
git \
|
||||||
make \
|
cmake \
|
||||||
g++ \
|
python \
|
||||||
python3 \
|
python-pip \
|
||||||
py3-pip \
|
clang \
|
||||||
mesa-dev \
|
gcc \
|
||||||
mesa-gl \
|
llvm \
|
||||||
pkgconf \
|
mesa \
|
||||||
ninja \
|
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
|
&& conan profile detect
|
||||||
|
|
||||||
RUN clang --version \
|
RUN clang --version \
|
||||||
|
|
@ -28,11 +45,22 @@ RUN clang --version \
|
||||||
&& ninja --version \
|
&& ninja --version \
|
||||||
&& mold --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 \
|
&& cd light \
|
||||||
&& conan install . \
|
&& conan build . \
|
||||||
-s build_type=Release \
|
|
||||||
-c tools.system.package_manager:mode=install \
|
-c tools.system.package_manager:mode=install \
|
||||||
-c tools.cmake.cmaketoolchain:generator=Ninja \
|
-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 use_mold=True \
|
||||||
--build=missing
|
-o export_compile_commands=False \
|
||||||
|
--build=missing \
|
||||||
|
&& rm -rf ../light
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ conan build . \
|
||||||
-s compiler=gcc \
|
-s compiler=gcc \
|
||||||
-s compiler.version=15 \
|
-s compiler.version=15 \
|
||||||
-s compiler.libcxx=libstdc++ \
|
-s compiler.libcxx=libstdc++ \
|
||||||
-o use_mold=True \
|
|
||||||
-o enable_unit_tests=True \
|
-o enable_unit_tests=True \
|
||||||
-o enable_fuzz_tests=False \
|
-o enable_fuzz_tests=False \
|
||||||
-o enable_llvm_coverage=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 \
|
bash \
|
||||||
clang \
|
base-devel \
|
||||||
llvm \
|
|
||||||
cmake \
|
|
||||||
git \
|
git \
|
||||||
make \
|
cmake \
|
||||||
g++ \
|
python \
|
||||||
python3 \
|
python-pip \
|
||||||
py3-pip \
|
clang \
|
||||||
mesa-dev \
|
gcc \
|
||||||
mesa-gl \
|
llvm \
|
||||||
pkgconf \
|
mesa \
|
||||||
ninja \
|
ninja \
|
||||||
mold \
|
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
|
&& conan profile detect
|
||||||
|
|
||||||
RUN clang --version \
|
RUN clang --version \
|
||||||
|
|
@ -27,13 +45,25 @@ RUN clang --version \
|
||||||
&& g++ --version \
|
&& g++ --version \
|
||||||
&& clang --version \
|
&& clang --version \
|
||||||
&& ninja --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 \
|
&& cd light \
|
||||||
&& conan install . \
|
&& conan build . \
|
||||||
-s build_type=Release \
|
|
||||||
-c tools.system.package_manager:mode=install \
|
-c tools.system.package_manager:mode=install \
|
||||||
-c tools.cmake.cmaketoolchain:generator=Ninja \
|
-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 use_mold=True \
|
||||||
--build=missing
|
-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(stb REQUIRED)
|
||||||
find_package(yaml-cpp REQUIRED)
|
find_package(yaml-cpp REQUIRED)
|
||||||
find_package(EnTT REQUIRED)
|
find_package(EnTT REQUIRED)
|
||||||
find_package(opengl_system REQUIRED)
|
|
||||||
find_package(lz4 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
|
set -e
|
||||||
CI_DIR="$(git rev-parse --show-toplevel)/tools/ci/"
|
CI_DIR="$(git rev-parse --show-toplevel)/tools/ci/"
|
||||||
|
|
||||||
echo "==> Building image: clang_format"
|
echo "===========[ amd64_clang ]==========="]
|
||||||
docker build -t clang_format -f $CI_DIR/static_analysis/clang_format.dockerfile .
|
echo "==> Building amd64_clang_coverage..."
|
||||||
|
|
||||||
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"
|
|
||||||
docker build -t amd64_clang_coverage -f $CI_DIR/amd64/clang/coverage.dockerfile .
|
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 .
|
docker build -t amd64_clang_lsan -f $CI_DIR/amd64/clang/lsan.dockerfile .
|
||||||
|
echo "...DONE <=="
|
||||||
|
|
||||||
echo "==> Building image: amd64_clang_msan"
|
echo "==> Building image: amd64_clang_msan"
|
||||||
docker build -t amd64_clang_msan -f $CI_DIR/amd64/clang/msan.dockerfile .
|
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"
|
echo "WOOOOOOOOOOOOOOOOH!!! DONE :D"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue