summaryrefslogtreecommitdiffhomepage
path: root/editor
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-02-22 17:14:48 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-02-22 17:14:48 +0100
commit384d5c20d85a8ed9a4ccd0ede4457381c7458549 (patch)
tree3c2a08bd1060b03ee981d6c25c3d4bf51b76f3ba /editor
parent19652b004e83ca7d460c87a7666ba46083b9222a (diff)
wip
Diffstat (limited to 'editor')
-rw-r--r--editor/inspect.cpp124
-rw-r--r--editor/inspect.hpp23
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