diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2023-02-24 07:17:20 +0100 |
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-02-24 07:17:20 +0100 |
| commit | 87c89034894eae06c68e261f5a48c36b8f676b0d (patch) | |
| tree | 4af67599ac9bac4faccb7ecdeb5debe0622a6dbe /editor | |
| parent | bad2f1a530b82879dab4c4cff065aab6b1f711c8 (diff) | |
wip
Diffstat (limited to 'editor')
| -rw-r--r-- | editor/imgui-raii.cpp | 8 | ||||
| -rw-r--r-- | editor/imgui-raii.hpp | 1 | ||||
| -rw-r--r-- | editor/imgui.cpp | 13 | ||||
| -rw-r--r-- | editor/inspect-types.cpp | 28 | ||||
| -rw-r--r-- | editor/inspect.cpp | 101 | ||||
| -rw-r--r-- | editor/inspect.hpp | 14 |
6 files changed, 139 insertions, 26 deletions
diff --git a/editor/imgui-raii.cpp b/editor/imgui-raii.cpp index 458de973..7a5bc340 100644 --- a/editor/imgui-raii.cpp +++ b/editor/imgui-raii.cpp @@ -73,6 +73,14 @@ raii_wrapper begin_disabled(bool is_disabled) return {&ImGui::EndDisabled}; } +raii_wrapper begin_combo(StringView name, StringView preview, ImGuiComboFlags flags) +{ + if (ImGui::BeginCombo(name.data(), preview.data(), flags)) + return {&ImGui::EndCombo}; + else + return {}; +} + raii_wrapper begin_list_box(Containers::StringView name, ImVec2 size) { if (ImGui::BeginListBox(name.data(), size)) diff --git a/editor/imgui-raii.hpp b/editor/imgui-raii.hpp index 1893ab90..5b20415b 100644 --- a/editor/imgui-raii.hpp +++ b/editor/imgui-raii.hpp @@ -30,6 +30,7 @@ private: [[nodiscard]] raii_wrapper begin_table(const char* id, int ncols, ImGuiTableFlags flags = 0, const ImVec2& outer_size = {}, float inner_width = 0); [[nodiscard]] raii_wrapper tree_node(StringView name, ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None); [[nodiscard]] raii_wrapper begin_disabled(bool is_disabled = true); +[[nodiscard]] raii_wrapper begin_combo(StringView name, StringView preview, ImGuiComboFlags flags = 0); [[nodiscard]] raii_wrapper push_style_var(ImGuiStyleVar_ var, Vector2 value); [[nodiscard]] raii_wrapper push_style_var(ImGuiStyleVar_ var, float value); diff --git a/editor/imgui.cpp b/editor/imgui.cpp index 356caaf4..faeb2229 100644 --- a/editor/imgui.cpp +++ b/editor/imgui.cpp @@ -150,15 +150,26 @@ void app::draw_tile_under_cursor() void app::draw_inspector() { + static Optional<global_coords> tile; + + auto b = push_id("inspector"); auto& w = M->world(); if (cursor.tile) { auto [c, t] = w[*cursor.tile]; if (auto s = t.scenery()) + tile = *cursor.tile; + } + if (tile) + { + auto [c, t] = w[*tile]; + if (auto s = t.scenery()) { + char buf[32]; std::snprintf(buf, sizeof buf, "i_0x%p", (void*)&s); + auto b = push_id(buf); auto dpi = M->dpi_scale(); ImGui::SetNextWindowSize({300*dpi[0], 0}); - auto b = begin_window("inspector"_s); + auto b2 = begin_window("inspector"_s); entities::inspect_type(s); } } diff --git a/editor/inspect-types.cpp b/editor/inspect-types.cpp index 27d61f97..2cecac07 100644 --- a/editor/inspect-types.cpp +++ b/editor/inspect-types.cpp @@ -5,6 +5,7 @@ #include "src/tile-defs.hpp" #include "entity/types.hpp" #include "inspect.hpp" +#include <Corrade/Containers/ArrayViewStl.h> namespace floormat::entities { @@ -21,8 +22,12 @@ template<> struct entity_accessors<scenery_ref> { }, entity::type<Vector2b>::field{"offset"_s, [](const scenery_ref& x) { return x.frame.offset; }, - [](scenery_ref& x, Vector2b value) { x.frame.offset = value; }, - constantly(constraints::range{Vector2b(iTILE_SIZE2/-2), Vector2b(iTILE_SIZE2/2)}) + [](scenery_ref& x, Vector2b value) { x.frame.offset = value; } + //constantly(constraints::range{Vector2b(iTILE_SIZE2/-2), Vector2b(iTILE_SIZE2/2)}) + }, + entity::type<pass_mode>::field{"pass-mode"_s, + [](const scenery_ref& x) { return x.frame.passability; }, + [](scenery_ref& x, pass_mode value) { x.frame.passability = value; } }, // todo pass_mode enum entity::type<bool>::field{"interactive"_s, @@ -34,12 +39,29 @@ template<> struct entity_accessors<scenery_ref> { } }; +using enum_pair = std::pair<StringView, std::size_t>; + +template<typename T> constexpr auto enum_values(); +template<typename T> requires (!std::is_enum_v<T>) constexpr std::array<enum_pair, 0> enum_values(){ return {}; } + +template<> constexpr auto enum_values<pass_mode>() +{ + return std::to_array<enum_pair>({ + { "blocked"_s, (std::size_t)pass_mode::blocked, }, + { "see-through"_s, (std::size_t)pass_mode::see_through, }, + { "shoot-through"_s, (std::size_t)pass_mode::shoot_through, }, + { "pass"_s, (std::size_t)pass_mode::pass }, + }); +} + template<> void inspect_type<scenery_ref>(scenery_ref& x) { visit_tuple([&](const auto& field) { using type = typename std::decay_t<decltype(field)>::FieldType; - inspect_field<type>(&x, field.erased()); + constexpr auto list = enum_values<type>(); + auto view = ArrayView<const enum_pair>{list.data(), list.size()}; + inspect_field<type>(&x, field.erased(), view); }, entity_metadata<scenery_ref>::accessors); } diff --git a/editor/inspect.cpp b/editor/inspect.cpp index 02e658b9..bd1329e0 100644 --- a/editor/inspect.cpp +++ b/editor/inspect.cpp @@ -3,6 +3,7 @@ #include "compat/defs.hpp" #include "entity/accessor.hpp" #include "imgui-raii.hpp" +#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/String.h> #include <Corrade/Containers/StringIterable.h> #include <Magnum/Math/Vector.h> @@ -42,11 +43,32 @@ using namespace entities; template<typename T> requires std::is_integral_v<T> constexpr bool eqv(T a, T b) { return a == b; } inline bool eqv(float a, float b) { return std::fabs(a - b) < 1e-8f; } +inline bool eqv(const String& a, const String& b) { return a == b; } template<typename T, std::size_t N> constexpr bool eqv(const Math::Vector<N, T>& a, const Math::Vector<N, T>& b) { return a == b; } -template<typename T> void do_inspect_field(void* datum, const erased_accessor& accessor, field_repr repr) +int corrade_string_resize_callback(ImGuiInputTextCallbackData* data) { - fm_assert(accessor.check_field_type<T>()); + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + auto* my_str = reinterpret_cast<String*>(data->UserData); + fm_assert(my_str->begin() == data->Buf); + String tmp = std::move(*my_str); + *my_str = String{ValueInit, (std::size_t)data->BufSize}; + auto len = std::min(tmp.size(), my_str->size()); + for (std::size_t i = 0; i < len; i++) + (*my_str)[i] = tmp[i]; + data->Buf = my_str->begin(); + } + return 0; +} + +template<typename T> +void do_inspect_field(void* datum, const erased_accessor& accessor, field_repr repr, + const ArrayView<const std::pair<StringView, std::size_t>>& list) +{ + if (list.isEmpty()) + fm_assert(accessor.check_field_type<T>()); + fm_assert(!list.isEmpty() == (repr == field_repr::cbx)); bool should_disable; @@ -65,7 +87,13 @@ template<typename T> void do_inspect_field(void* datum, const erased_accessor& a accessor.read_fun(datum, accessor.reader, &value); auto orig = value; - if constexpr(std::is_same_v<T, bool>) + if constexpr(std::is_same_v<T, String>) + { + ret = ImGui::InputText(label.data(), value.begin(), value.size(), ImGuiInputTextFlags_CallbackResize, corrade_string_resize_callback, &value); + if (auto max_len = accessor.get_max_length(datum); value.size() > max_len) + value = value.prefix(max_len); + } + else if constexpr(std::is_same_v<T, bool>) ret = ImGui::Checkbox(label.data(), &value); else if constexpr (!is_magnum_vector<T>) { @@ -74,9 +102,33 @@ template<typename T> void do_inspect_field(void* datum, const erased_accessor& a T step = 1, *step_ = !std::is_floating_point_v<T> ? &step : nullptr; switch (repr) { + default: fm_warn_once("invalid repr enum value '%zu'", (std::size_t)repr); break; case field_repr::input: ret = ImGui::InputScalar(label.data(), igdt, &value, &step_); break; case field_repr::slider: ret = ImGui::SliderScalar(label.data(), igdt, &value, &min, &max); break; case field_repr::drag: ret = ImGui::DragScalar(label.data(), igdt, &value, 1, &min, &max); break; + case field_repr::cbx: { + if constexpr(std::is_integral_v<T>) + { + const char* preview = "<invalid>"; + const auto old_value = (std::size_t)static_cast<std::make_unsigned_t<T>>(value); + for (const auto& [str, x] : list) + if (x == old_value) + { + preview = str.data(); + break; + } + for (auto b = begin_combo(label.data(), preview); + const auto& [str, x] : list) + { + const bool is_selected = x == (std::size_t)old_value; + if (ImGui::Selectable(str.data(), is_selected)) + value = T(x); + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + break; + } + } } value = std::clamp(value, min, max); } @@ -88,6 +140,9 @@ template<typename T> void do_inspect_field(void* datum, const erased_accessor& a T step = T(U(1)), *step_ = !std::is_floating_point_v<U> ? &step : nullptr; switch (repr) { + default: + fm_warn_once("invalid repr enum value '%zu'", (std::size_t)repr); + break; case field_repr::input: ret = ImGui::InputScalarN(label.data(), igdt, &value, T::Size, &step_); break; @@ -111,29 +166,34 @@ template<typename T> void do_inspect_field(void* datum, const erased_accessor& a } // namespace -#define MAKE_SPEC(type, repr) \ - template<> \ - void inspect_field<type>(void* datum, const erased_accessor& accessor) { \ - do_inspect_field<type>(datum, accessor, (repr)); \ +#define MAKE_SPEC(type, repr) \ + template<> \ + void inspect_field<type>(void* datum, const erased_accessor& accessor, \ + const ArrayView<const std::pair<StringView, std::size_t>>& list) \ + { \ + do_inspect_field<type>(datum, accessor, (repr), list); \ } -#define MAKE_SPEC2(type, repr) \ - template<> \ - void inspect_field<field_repr_<type, field_repr, repr>>(void* datum, const erased_accessor& accessor) { \ - do_inspect_field<type>(datum, accessor, (repr)); \ +#define MAKE_SPEC2(type, repr) \ + template<> \ + void inspect_field<field_repr_<type, field_repr, repr>>(void* datum, const erased_accessor& accessor, \ + const ArrayView<const std::pair<StringView, std::size_t>>& list) \ + { \ + do_inspect_field<type>(datum, accessor, (repr), list); \ } -#define MAKE_SPEC_REPRS(type) \ - MAKE_SPEC2(type, field_repr::input) \ - MAKE_SPEC2(type, field_repr::slider) \ - MAKE_SPEC2(type, field_repr::drag) \ +#define MAKE_SPEC_REPRS(type) \ + MAKE_SPEC2(type, field_repr::input) \ + MAKE_SPEC2(type, field_repr::slider) \ + MAKE_SPEC2(type, field_repr::drag) \ MAKE_SPEC(type, field_repr::input) -#define MAKE_SPEC_REPRS2(type) \ - MAKE_SPEC_REPRS(Math::Vector2<type>) \ - MAKE_SPEC_REPRS(Math::Vector3<type>) \ - MAKE_SPEC_REPRS(Math::Vector4<type>) \ - MAKE_SPEC_REPRS(type) +#define MAKE_SPEC_REPRS2(type) \ + MAKE_SPEC_REPRS(Math::Vector2<type>) \ + MAKE_SPEC_REPRS(Math::Vector3<type>) \ + MAKE_SPEC_REPRS(Math::Vector4<type>) \ + MAKE_SPEC_REPRS(type) \ + MAKE_SPEC2(type, field_repr::cbx) MAKE_SPEC_REPRS2(std::uint8_t) MAKE_SPEC_REPRS2(std::int8_t) @@ -143,5 +203,6 @@ MAKE_SPEC_REPRS2(std::uint32_t) MAKE_SPEC_REPRS2(std::int32_t) MAKE_SPEC_REPRS2(float) MAKE_SPEC(bool, field_repr::input) +MAKE_SPEC(String, field_repr::input) } // namespace floormat::entities diff --git a/editor/inspect.hpp b/editor/inspect.hpp index 5cb71303..7edfd6d1 100644 --- a/editor/inspect.hpp +++ b/editor/inspect.hpp @@ -1,4 +1,6 @@ #pragma once +#include <cstddef> +#include <utility> namespace floormat::entities { struct erased_accessor; @@ -18,13 +20,21 @@ private: T value; }; -enum class field_repr : unsigned char { input, slider, drag, }; +enum class field_repr : unsigned char { input, slider, drag, cbx, }; template<typename T> using field_repr_input = field_repr_<T, field_repr, field_repr::input>; template<typename T> using field_repr_slider = field_repr_<T, field_repr, field_repr::slider>; template<typename T> using field_repr_drag = field_repr_<T, field_repr, field_repr::drag>; +template<typename T> using field_repr_cbx = field_repr_<T, field_repr, field_repr::cbx>; -template<typename T> void inspect_field(void* datum, const entities::erased_accessor& accessor); +template<typename T> void inspect_field(void* datum, const entities::erased_accessor& accessor, + const ArrayView<const std::pair<StringView, std::size_t>>& list); template<typename T> void inspect_type(T& x); +template<typename T> requires std::is_enum_v<T> void inspect_field(void* datum, const entities::erased_accessor& accessor, + const ArrayView<const std::pair<StringView, std::size_t>>& list) +{ + inspect_field<field_repr_cbx<std::underlying_type_t<T>>>(datum, accessor, list); +} + } // namespace floormat::entities |
