summaryrefslogtreecommitdiffhomepage
path: root/editor
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-02-24 07:17:20 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-02-24 07:17:20 +0100
commit87c89034894eae06c68e261f5a48c36b8f676b0d (patch)
tree4af67599ac9bac4faccb7ecdeb5debe0622a6dbe /editor
parentbad2f1a530b82879dab4c4cff065aab6b1f711c8 (diff)
wip
Diffstat (limited to 'editor')
-rw-r--r--editor/imgui-raii.cpp8
-rw-r--r--editor/imgui-raii.hpp1
-rw-r--r--editor/imgui.cpp13
-rw-r--r--editor/inspect-types.cpp28
-rw-r--r--editor/inspect.cpp101
-rw-r--r--editor/inspect.hpp14
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