Commit e9432e3d authored by Florian Oetke's avatar Florian Oetke
Browse files

switched from nuklear to imgui

parent 490ba1ad
Pipeline #2625 passed with stage
in 12 minutes and 11 seconds
......@@ -19,9 +19,6 @@
[submodule "dependencies/magic_get"]
path = dependencies/magic_get
url = https://github.com/apolukhin/magic_get.git
[submodule "dependencies/nuklear"]
path = dependencies/nuklear
url = https://github.com/vurtun/nuklear.git
[submodule "dependencies/physfs"]
path = dependencies/physfs
url = https://github.com/lowkey42/physfs.git
......@@ -43,3 +40,6 @@
[submodule "dependencies/crunch"]
path = dependencies/crunch
url = https://github.com/lowkey42/crunch.git
[submodule "dependencies/imgui"]
path = dependencies/imgui
url = https://github.com/ocornut/imgui.git
......@@ -11,7 +11,7 @@ add_subdirectory(enet)
include(glm_interface.cmake)
include(gsl_interface.cmake)
include(moodycamel_interface.cmake)
include(nuklear_interface.cmake)
include(imgui_interface.cmake)
include(magic_get_interface.cmake)
......
Subproject commit a53c57152b83491a4bcd7fceca9d6cbc887c0c54
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project(imgui)
add_library(imgui STATIC
imgui/imgui.cpp
imgui/imgui.h
imgui/imgui_demo.cpp
imgui/imgui_draw.cpp
imgui/imgui_internal.h
imgui/imgui_widgets.cpp
imgui/imstb_rectpack.h
imgui/imstb_textedit.h
imgui/imstb_truetype.h
)
add_library(imgui::imgui ALIAS imgui)
target_include_directories(imgui SYSTEM INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/imgui>
$<INSTALL_INTERFACE:include>
)
install(TARGETS imgui EXPORT imguiTargets
INCLUDES DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
export(
EXPORT imguiTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/imguiTargets.cmake"
)
install(
EXPORT imguiTargets FILE imguiTargets.cmake
NAMESPACE imgui::
DESTINATION lib/cmake
)
Subproject commit 181cfd86c47ae83eceabaf4e640587b844e613b6
......@@ -44,16 +44,11 @@ namespace mirrage {
auto& anim = anim_mb.get_or_throw();
auto ctx = _gui.ctx();
if(nk_begin_titled(ctx,
"Animation",
"Animation",
_gui.centered_right(300, 500),
NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_TITLE | NK_WINDOW_MINIMIZABLE)) {
ImGui::PositionNextWindow(
{300, 500}, ImGui::WindowPosition_X::right, ImGui::WindowPosition_Y::center);
if(ImGui::Begin("Animation")) {
ImGui::TextUnformatted("Animation");
nk_layout_row_dynamic(ctx, 20, 1);
nk_label(ctx, "Animation", NK_TEXT_LEFT);
auto animations_strs = std::array<const char*, 9>{
{"[None]", "Attack", "Dance", "Die", "Flee", "Idle", "Sad", "Sleep", "Walk"}};
auto animations_ids = std::array<util::Str_id, 9>{{""_strid,
......@@ -68,20 +63,13 @@ namespace mirrage {
(void) animations_ids;
auto curr_animation_id = anim.animation_id().get_or(""_strid);
auto curr_idx =
std::distance(animations_ids.begin(),
std::find(animations_ids.begin(), animations_ids.end(), curr_animation_id));
auto new_idx = nk_combo(ctx,
animations_strs.data(),
gsl::narrow<int>(animations_strs.size()),
int(curr_idx),
14,
nk_vec2(100.f, 200));
if(new_idx != curr_idx) {
anim.play(animations_ids.at(std::size_t(new_idx)));
anim_lbs_mb.process([&](auto& anim) { anim.play(animations_ids.at(std::size_t(new_idx))); });
auto curr_idx = int(std::distance(
animations_ids.begin(),
std::find(animations_ids.begin(), animations_ids.end(), curr_animation_id)));
if(ImGui::Combo("Animation", &curr_idx, animations_strs.data(), int(animations_strs.size()))) {
anim.play(animations_ids.at(std::size_t(curr_idx)));
anim_lbs_mb.process([&](auto& anim) { anim.play(animations_ids.at(std::size_t(curr_idx))); });
}
anim.animation().process([&](auto& curr_animation) {
......@@ -106,8 +94,7 @@ namespace mirrage {
auto duration = curr_animation->duration();
nk_label(ctx, "Time", NK_TEXT_LEFT);
auto new_time = nk_slide_float(ctx, 0.f, time, duration, 0.01f);
auto new_time = ImGui::ValueSliderFloat("Time", time, 0.f, duration);
if(std::abs(new_time - time) > 0.00001f) {
dqs_anim.mark_dirty();
lbs_anim.mark_dirty();
......@@ -119,29 +106,30 @@ namespace mirrage {
curr_lbs_state->time = new_time;
}
nk_label(ctx,
(util::to_string(new_time) + " / " + util::to_string(duration)).c_str(),
NK_TEXT_LEFT);
ImGui::TextUnformatted(
(util::to_string(new_time) + " / " + util::to_string(duration)).c_str());
auto speed = anim.speed();
nk_property_float(ctx, "Speed", 0.f, &speed, 5.f, 0.1f, 0.05f);
anim.speed(speed);
anim.speed(ImGui::ValueSliderFloat("Speed", anim.speed(), 0.f, 5.f));
if(anim.paused())
anim.pause(!nk_button_label(ctx, "Continue"));
anim.pause(!ImGui::Button("Continue"));
else
anim.pause(nk_button_label(ctx, "Pause"));
anim.pause(ImGui::Button("Pause"));
ImGui::SameLine();
if(anim.reversed())
anim.reverse(!nk_button_label(ctx, "Reverse (->)"));
anim.reverse(!ImGui::Button("Reverse (->)"));
else
anim.reverse(nk_button_label(ctx, "Reverse (<-)"));
anim.reverse(ImGui::Button("Reverse (<-)"));
ImGui::SameLine();
if(anim.looped())
anim.loop(!nk_button_label(ctx, "Once"));
anim.loop(!ImGui::Button("Once"));
else
anim.loop(nk_button_label(ctx, "Repeat"));
anim.loop(ImGui::Button("Repeat"));
anim_lbs_mb.process([&](auto& anim_lbs) {
......@@ -153,18 +141,18 @@ namespace mirrage {
});
}
nk_label(ctx, "Rotation Test", NK_TEXT_LEFT);
ImGui::TextUnformatted("Rotation Test");
_animation_test2_dqs.get<renderer::Simple_animation_controller_comp>().process([&](auto& anim) {
if(anim.paused())
anim.pause(!nk_button_label(ctx, "Continue"));
anim.pause(!ImGui::Button("Continue"));
else
anim.pause(nk_button_label(ctx, "Pause"));
anim.pause(ImGui::Button("Pause"));
_animation_test2_lbs.get<renderer::Simple_animation_controller_comp>().process(
[&](auto& anim_lbs) { anim_lbs.pause(anim.paused()); });
});
nk_end(ctx);
ImGui::End();
Test_screen::_draw();
}
......
......@@ -328,16 +328,10 @@ namespace mirrage {
}
void Test_screen::_draw_settings_window()
{
auto ctx = _gui.ctx();
if(nk_begin_titled(ctx,
"debug_controls",
"Debug Controls",
_gui.centered_left(250, 220),
NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_TITLE | NK_WINDOW_MINIMIZABLE)) {
ImGui::PositionNextWindow({250, 400}, ImGui::WindowPosition_X::left, ImGui::WindowPosition_Y::center);
if(ImGui::Begin("Debug Controls")) {
nk_layout_row_dynamic(ctx, 20, 2);
nk_label(ctx, "Preset", NK_TEXT_LEFT);
ImGui::TextUnformatted("Preset");
auto preset_options = std::array<const char*, 7>{{"Free Motion",
"Center",
"Top-Down",
......@@ -345,34 +339,26 @@ namespace mirrage {
"Hallway",
"Hallway2",
"Cornell Box"}};
_set_preset(nk_combo(ctx,
preset_options.data(),
gsl::narrow<int>(preset_options.size()),
_selected_preset,
14,
nk_vec2(100.f, 200)));
nk_layout_row_dynamic(ctx, 20, 1);
ImGui::Combo("preset", &_selected_preset, preset_options.data(), int(preset_options.size()));
_camera.process<renderer::Camera_comp>([&](auto& cam) {
cam.dof_focus(nk_propertyf(ctx, "Focus Plane", 0.1f, cam.dof_focus(), 100.f, 1.f, 0.01f));
cam.dof_range(nk_propertyf(ctx, "Focus Range", 0.1f, cam.dof_range(), 10.f, 0.1f, 0.001f));
cam.dof_power(nk_propertyf(ctx, "DOF Power", 0.01f, cam.dof_power(), 1.f, 0.1f, 0.001f));
cam.dof_focus(ImGui::ValueSliderFloat("Focus Plane", cam.dof_focus(), 0.1f, 100.f));
cam.dof_range(ImGui::ValueSliderFloat("Focus Range", cam.dof_range(), 0.1f, 10.f));
cam.dof_power(ImGui::ValueSliderFloat("DOF Power", cam.dof_power(), 0.01f, 1.f));
});
if(!_meta_system.nims().is_playing()) {
nk_layout_row_dynamic(ctx, 20, 1);
nk_label(ctx, "Directional Light", NK_TEXT_LEFT);
ImGui::TextUnformatted("Directional Light");
nk_layout_row_dynamic(ctx, 14, 1);
auto elevation = nk_propertyf(ctx, "Elevation", 0.f, _sun_elevation, 1.f, 0.05f, 0.001f);
auto elevation = ImGui::ValueSliderFloat("Elevation", _sun_elevation, 0.f, 1.f);
if(std::abs(elevation - _sun_elevation) > 0.000001f) {
_sun_elevation = elevation;
_set_preset(0);
}
auto azimuth = nk_propertyf(ctx, "Azimuth", -2.f, _sun_azimuth, 2.f, 0.05f, 0.001f);
auto azimuth = ImGui::ValueSliderFloat("Azimuth", _sun_azimuth, -2.f, 2.f);
if(std::abs(azimuth - _sun_azimuth) > 0.000001f) {
_sun_azimuth = azimuth;
_set_preset(0);
......@@ -382,31 +368,30 @@ namespace mirrage {
_sun.get<renderer::Directional_light_comp>().process(
[&](renderer::Directional_light_comp& light) {
auto new_size = nk_propertyf(
ctx, "Size", 0.5f, light.source_radius() / 1_m, 20.f, 0.1f, 0.01f);
auto new_size =
ImGui::ValueSliderFloat("Size", light.source_radius() / 1_m, 0.5f, 20.f);
light.source_radius(new_size * 1_m);
auto new_temp = nk_propertyf(
ctx, "Color", 500.f, _sun_color_temperature, 20000.f, 500.f, 50.f);
auto new_temp =
ImGui::ValueSliderFloat("Color", _sun_color_temperature, 500.f, 20000.f);
if(std::abs(new_temp - _sun_color_temperature) > 0.000001f) {
light.temperature(_sun_color_temperature = new_temp);
_set_preset(0);
}
auto color = util::Rgba{light.color(), light.intensity() / 50'000.f};
if(gui::color_picker(ctx, color, 210.f)) {
ImGui::Spacing();
ImGui::TextUnformatted("Color");
auto color = util::Rgba{light.color(), light.intensity() / 50000.f};
if(ImGui::ColorPicker4("Color", &color.r)) {
light.color({color.r, color.g, color.b});
light.intensity(color.a * 50'000.f);
light.intensity(color.a * 50000.f);
_set_preset(0);
}
});
}
nk_layout_row_dynamic(ctx, 10, 1);
nk_label(ctx, "", NK_TEXT_LEFT);
}
nk_end(ctx);
ImGui::End();
}
void Test_screen::_update_sun_position()
......
......@@ -9,11 +9,8 @@ file(GLOB_RECURSE HEADER_FILES
)
add_library(mirrage_gui STATIC
src/color_picker.cpp
src/debug_ui.cpp
src/gui.cpp
src/menu.cpp
src/text_edit.cpp
${HEADER_FILES}
)
add_library(mirrage::gui ALIAS mirrage_gui)
......@@ -46,7 +43,7 @@ target_link_libraries(mirrage_gui
mirrage::utils
gsl
glm::glm
nuklear
imgui::imgui
mirrage::asset
mirrage::input
sf2
......
......@@ -11,6 +11,8 @@
#include <mirrage/utils/console_command.hpp>
#include <mirrage/utils/messagebus.hpp>
#include <imgui.h>
#include <iostream>
#include <unordered_set>
......@@ -47,24 +49,20 @@ namespace mirrage::gui {
void draw();
private:
static constexpr auto max_command_length = 256;
Gui& _gui;
util::Mailbox_collection _mailbox;
asset::Asset_manager& _assets;
bool _show_console = false;
bool _focus_prompt = false;
bool _show_suggestions = false;
int _selected_suggestion = -1;
std::uint32_t _scroll_x = 0;
std::uint32_t _scroll_y = 0;
bool _scroll_lock = true;
std::array<char, max_command_length> _command_input_buffer{};
int _command_input_length = 0;
util::Console_command_container _commands;
std::unordered_set<std::string> _shown_debug_menus;
std::vector<std::string> _history;
int _current_history_entry = -1;
Gui& _gui;
util::Mailbox_collection _mailbox;
asset::Asset_manager& _assets;
ImGuiTextFilter _text_filter;
bool _show_console = false;
bool _scroll_to_bottom = true;
bool _focus_prompt = true;
std::string _command;
util::Console_command_container _commands;
std::unordered_set<std::string> _shown_debug_menus;
std::vector<std::string> _history;
int _current_history_entry = -1;
void _save_history();
};
......
......@@ -7,34 +7,71 @@
#pragma once
#include <cstdint>
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#include <nuklear.h>
#include <mirrage/utils/maybe.hpp>
#include <mirrage/utils/template_utils.hpp>
#include <mirrage/utils/str_id.hpp>
#include <mirrage/utils/units.hpp>
#include <glm/vec2.hpp>
#include <gsl/gsl>
#include <glm/vec4.hpp>
#include <imgui.h>
#include <cstdint>
#include <memory>
extern nk_size nk_do_progress(nk_flags* state,
struct nk_command_buffer* out,
struct nk_rect bounds,
nk_size value,
nk_size max,
int modifiable,
const struct nk_style_progress* style,
struct nk_input* in);
struct nk_context;
namespace ImGui {
enum class WindowPosition_X { center = 0, left = 1, right = 2 };
enum class WindowPosition_Y { center = 0, top = 1, bottom = 2 };
extern void PositionNextWindow(glm::vec2 size,
WindowPosition_X x,
WindowPosition_Y y,
glm::vec2 offset = {});
struct Column {
const char* header = "";
float size = -1.f;
Column() = default;
/*implicit*/ Column(const char* header, float size = -1) : header(header), size(size) {}
};
extern void BeginTable(const char* id,
std::initializer_list<Column>,
bool first_call,
bool border = true,
bool separator = true);
extern float ValueSliderFloat(const char* label,
float v,
float v_min,
float v_max,
const char* format = "%.3f",
float power = 1.0f);
// ImGui::InputText() with std::string
// Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
IMGUI_API bool InputText(const char* label,
std::string* str,
ImGuiInputTextFlags flags = 0,
ImGuiInputTextCallback callback = nullptr,
void* user_data = nullptr);
IMGUI_API bool InputTextMultiline(const char* label,
std::string* str,
const ImVec2& size = ImVec2(0, 0),
ImGuiInputTextFlags flags = 0,
ImGuiInputTextCallback callback = nullptr,
void* user_data = nullptr);
IMGUI_API bool InputTextWithHint(const char* label,
const char* hint,
std::string* str,
ImGuiInputTextFlags flags = 0,
ImGuiInputTextCallback callback = nullptr,
void* user_data = nullptr);
} // namespace ImGui
struct ImFont;
namespace mirrage {
class Engine;
......@@ -57,13 +94,10 @@ namespace mirrage::gui {
struct Nk_renderer;
}
extern auto nk_interactive_text(struct nk_context* ctx, const char* str, int len, nk_color color) -> int;
struct Gui_vertex {
glm::vec2 position;
glm::vec2 uv;
nk_byte color[4];
glm::vec2 position;
glm::vec2 uv;
std::uint8_t color[4];
};
class Gui_renderer_interface {
......@@ -74,22 +108,26 @@ namespace mirrage::gui {
void draw_gui();
virtual auto load_texture(int width, int height, int channels, const std::uint8_t* data)
-> std::shared_ptr<struct nk_image> = 0;
-> std::shared_ptr<void> = 0;
virtual auto load_texture(const asset::AID&) -> std::shared_ptr<struct nk_image> = 0;
virtual auto load_texture(const asset::AID&) -> std::shared_ptr<void> = 0;
protected:
friend class Gui;
friend struct detail::Nk_renderer;
virtual void prepare_draw(gsl::span<const std::uint16_t> indices,
gsl::span<const Gui_vertex> vertices,
glm::mat4 view_proj) = 0;
virtual void draw_elements(int texture_handle,
using Prepare_data_src = std::function<void(std::uint16_t*, Gui_vertex*)>;
virtual void prepare_draw(std::size_t index_count,
std::size_t vertex_count,
glm::mat4 view_proj,
Prepare_data_src write_data) = 0;
virtual void draw_elements(void* texture_handle,
glm::vec4 clip_rect,
std::uint32_t offset,
std::uint32_t count) = 0;
virtual void finalize_draw() = 0;
std::uint32_t count,
std::uint32_t vertex_offset) = 0;
virtual void finalize_draw() = 0;
private:
template <class>
......@@ -98,10 +136,7 @@ namespace mirrage::gui {
Gui* _gui;
};
// TODO: gamepad input: https://gist.github.com/vurtun/519801825b4ccfad6767
// https://github.com/vurtun/nuklear/issues/50
// TODO: theme support: https://github.com/vurtun/nuklear/blob/master/demo/style.c
// https://github.com/vurtun/nuklear/blob/master/example/skinning.c
class Gui {
public:
Gui(glm::vec4 viewport, asset::Asset_manager& assets, input::Input_manager& input);
......@@ -110,20 +145,14 @@ namespace mirrage::gui {
void draw();
void start_frame();
auto ctx() -> nk_context*;
auto find_font(util::Str_id) const -> util::maybe<ImFont*>;
auto viewport() const noexcept { return _viewport; }
auto virtual_viewport() const noexcept -> glm::vec4;
void viewport(glm::vec4 new_viewport);
struct ::nk_rect centered(int width, int height);
struct ::nk_rect centered_left(int width, int height);
struct ::nk_rect centered_right(int width, int height);
auto ready() const noexcept { return bool(_impl); }
auto load_texture(const asset::AID&) -> std::shared_ptr<struct nk_image>;
auto load_texture(const asset::AID&) -> std::shared_ptr<void>;
private:
template <class>
......@@ -159,32 +188,4 @@ namespace mirrage::gui {
}
};
// widgets
extern bool color_picker(nk_context*, util::Rgb& color, float width, float factor = 1.f);
extern bool color_picker(nk_context*, util::Rgba& color, float width, float factor = 1.f);
extern void begin_menu(nk_context*, int& active);
extern bool menu_button(nk_context*, const char* text, bool enabled = true);
extern void end_menu(nk_context*);
class Text_edit {
public:
Text_edit();
Text_edit(Text_edit&&) = default;
Text_edit& operator=(Text_edit&&) = default;
~Text_edit();
void reset(const std::string&);
void get(std::string&) const;
auto active() const noexcept { return _active; }
void update_and_draw(nk_context*, nk_flags type);
void update_and_draw(nk_context*, nk_flags type, std::string&);
private:
util::maybe<nk_text_edit> _data;
bool _active = false;
};
} // namespace mirrage::gui
#include <mirrage/gui/gui.hpp>
#include <glm/gtx/norm.hpp>
namespace mirrage::gui {
namespace {
bool color_picker(nk_context* ctx, nk_colorf& cf, float width, bool hasAlpha)
{
auto c = nk_color{static_cast<nk_byte>(cf.r * 255),
static_cast<nk_byte>(cf.g * 255),
static_cast<nk_byte>(cf.b * 255),
static_cast<nk_byte>(cf.a * 255)};
if(nk_combo_begin_color(ctx, c, nk_vec2(width, width))) {