diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-02-22 17:14:48 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-02-22 17:14:48 +0100 |
commit | 384d5c20d85a8ed9a4ccd0ede4457381c7458549 (patch) | |
tree | 3c2a08bd1060b03ee981d6c25c3d4bf51b76f3ba /editor | |
parent | 19652b004e83ca7d460c87a7666ba46083b9222a (diff) |
wip
Diffstat (limited to 'editor')
-rw-r--r-- | editor/inspect.cpp | 124 | ||||
-rw-r--r-- | editor/inspect.hpp | 23 |
2 files changed, 136 insertions, 11 deletions
diff --git a/editor/inspect.cpp b/editor/inspect.cpp index 5a34d906..69734866 100644 --- a/editor/inspect.cpp +++ b/editor/inspect.cpp @@ -1,33 +1,137 @@ #include "inspect.hpp" #include "compat/assert.hpp" +#include "compat/defs.hpp" #include "entity/accessor.hpp" #include "imgui-raii.hpp" +#include <Corrade/Containers/String.h> +#include <Corrade/Containers/StringIterable.h> +#include <Magnum/Math/Vector.h> +#include <Magnum/Math/Vector2.h> +#include <Magnum/Math/Vector3.h> +#include <Magnum/Math/Vector4.h> +#include <algorithm> namespace floormat { +namespace { + +String label_left(StringView label) +{ + float width = ImGui::CalcItemWidth(), x = ImGui::GetCursorPosX(); + ImGui::Text("%s", label.data()); + ImGui::SameLine(); + ImGui::SetCursorPosX(x + width*.5f + ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SetNextItemWidth(-1); + return ""_s.join(StringIterable({ "##"_s, label })); +} + +template<typename T> struct is_magnum_vector_ final : std::false_type {}; +template<std::size_t N, typename T> struct is_magnum_vector_<Math::Vector<N, T>> : std::true_type {}; +template<typename T> struct is_magnum_vector_<Math::Vector2<T>> : std::true_type {}; +template<typename T> struct is_magnum_vector_<Math::Vector3<T>> : std::true_type {}; +template<typename T> struct is_magnum_vector_<Math::Vector4<T>> : std::true_type {}; +template<typename T> constexpr bool is_magnum_vector = is_magnum_vector_<T>::value; + +template<typename T> struct IGDT_; +template<> struct IGDT_<std::uint8_t> : std::integral_constant<int, ImGuiDataType_U8> {}; +template<> struct IGDT_<std::int8_t> : std::integral_constant<int, ImGuiDataType_S8> {}; +template<> struct IGDT_<std::uint16_t> : std::integral_constant<int, ImGuiDataType_U16> {}; +template<> struct IGDT_<std::int16_t> : std::integral_constant<int, ImGuiDataType_S16> {}; +template<> struct IGDT_<std::uint32_t> : std::integral_constant<int, ImGuiDataType_U32> {}; +template<> struct IGDT_<std::int32_t> : std::integral_constant<int, ImGuiDataType_S32> {}; +template<> struct IGDT_<float> : std::integral_constant<int, ImGuiDataType_Float> {}; +template<typename T> constexpr auto IGDT = IGDT_<T>::value; + using namespace imgui; using namespace entities; -template<typename T> -static void do_inspect_field(const void* datum, const erased_accessor& accessor) +template<typename T> void do_inspect_field(void* datum, const erased_accessor& accessor, field_repr repr) { fm_assert(accessor.check_field_name<T>()); - raii_wrapper disabler; + bool should_disable; switch (accessor.is_enabled(datum)) { using enum field_status; case hidden: return; - case readonly: disabler = begin_disabled(); break; - case enabled: break; + case readonly: should_disable = true; break; + case enabled: should_disable = false; break; } + should_disable = should_disable || !accessor.can_write(); + [[maybe_unused]] auto disabler = begin_disabled(should_disable); + bool ret = false; + const auto label = label_left(accessor.field_name); + T value{}; + accessor.read_fun(datum, accessor.reader, &value); + auto orig = value; - auto [min, max] = accessor.get_range(datum).convert<T>(); -} + if constexpr (!is_magnum_vector<T>) + { + auto [min, max] = accessor.get_range(datum).convert<T>(); + constexpr auto igdt = IGDT<T>; + switch (repr) + { + case field_repr::input: ret = ImGui::InputScalar(label.data(), igdt, &value); 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; + } + value = std::clamp(value, min, max); + } + else + { + auto [min_, max_] = accessor.get_range(datum).convert<typename T::Type>(); + Math::Vector<T::Size, typename T::Type> min(min_), max(max_); + constexpr auto igdt = IGDT<typename T::Type>; + switch (repr) + { + case field_repr::input: + ret = ImGui::InputScalarN(label.data(), igdt, &value, T::Size); + break; + case field_repr::drag: + fm_warn_once("can't use imgui input drag mode for vector type"); + [[fallthrough]]; + case field_repr::slider: + ret = ImGui::SliderScalarN(label.data(), igdt, &value, T::Size, &min, &max); + break; + } + } -template<> void inspect_field<int>(const void* datum, const erased_accessor& accessor) -{ - do_inspect_field<int>(datum, accessor); + ImGui::NewLine(); + + if (ret && !should_disable && value != orig) + if (accessor.is_enabled(datum) >= field_status::enabled && accessor.can_write()) + accessor.write_fun(datum, accessor.writer, &value); } +} // 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_REPR(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_SPEC_REPRS(type) \ + MAKE_SPEC_REPR(type, field_repr::input) \ + MAKE_SPEC_REPR(type, field_repr::slider) \ + MAKE_SPEC_REPR(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) + +MAKE_SPEC_REPRS2(std::uint8_t) +MAKE_SPEC_REPRS2(std::int8_t) +MAKE_SPEC_REPRS2(std::uint16_t) +MAKE_SPEC_REPRS2(std::int16_t) +MAKE_SPEC_REPRS2(std::uint32_t) +MAKE_SPEC_REPRS2(std::int32_t) + } // namespace floormat diff --git a/editor/inspect.hpp b/editor/inspect.hpp index feca67d1..d2824f2c 100644 --- a/editor/inspect.hpp +++ b/editor/inspect.hpp @@ -4,6 +4,27 @@ namespace floormat::entities { struct erased_accessor; } namespace floormat { -template<typename T> void inspect_field(const void* datum, const entities::erased_accessor& accessor); +template<typename T, typename Enum, Enum As> +struct field_repr_ final { + field_repr_(T x) : value{x} {} + field_repr_(const field_repr_<T, Enum, As>& other) noexcept = default; + field_repr_& operator=(T x) noexcept { value = x; return *this; } + field_repr_& operator=(const field_repr_<T, Enum, As>& x) noexcept = default; + field_repr_& operator*() const noexcept { return value; } + operator T() const noexcept { return value; } + + using Type = T; + static constexpr Enum Repr = As; +private: + T value; +}; + +enum class field_repr : unsigned char { input, slider, drag, }; + +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> void inspect_field(void* datum, const entities::erased_accessor& accessor); } // namespace floormat |