summaryrefslogtreecommitdiffhomepage
path: root/editor
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-05-18 16:26:01 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-05-18 16:26:01 +0200
commitec7be88fbb4062af20b77198007d815c321c2850 (patch)
tree85fbe24dc79d2e8072990939f1e7e8de97a84e84 /editor
parent44c8e45d71e5320aedaa5b4b839e636a0d973f7f (diff)
wip vobj
Diffstat (limited to 'editor')
-rw-r--r--editor/app.hpp1
-rw-r--r--editor/draw.cpp53
-rw-r--r--editor/editor-enums.hpp2
-rw-r--r--editor/editor.cpp32
-rw-r--r--editor/editor.hpp4
-rw-r--r--editor/imgui-editors.cpp72
-rw-r--r--editor/update.cpp2
-rw-r--r--editor/vobj-editor.cpp42
-rw-r--r--editor/vobj-editor.hpp18
9 files changed, 173 insertions, 53 deletions
diff --git a/editor/app.hpp b/editor/app.hpp
index 258225a9..b78037a0 100644
--- a/editor/app.hpp
+++ b/editor/app.hpp
@@ -117,6 +117,7 @@ private:
bool check_inspector_exists(const popup_target& p);
void draw_editor_tile_pane_atlas(tile_editor& ed, StringView name, const std::shared_ptr<tile_atlas>& atlas);
void draw_editor_scenery_pane(scenery_editor& ed);
+ void draw_editor_vobj_pane(vobj_editor& ed);
void set_cursor_from_imgui();
void draw_cursor();
void init_imgui(Vector2i size);
diff --git a/editor/draw.cpp b/editor/draw.cpp
index 4f58e8ec..124ca5d3 100644
--- a/editor/draw.cpp
+++ b/editor/draw.cpp
@@ -59,6 +59,20 @@ void app::draw_cursor()
anim_mesh.draw(shader, *sel.atlas, sel.r, sel.frame, Vector3(pos), 1);
}
}
+ else if (const auto* ed = _editor.current_vobj_editor())
+ {
+ if (!ed->is_anything_selected())
+ shader.set_tint(inactive_color);
+ if (ed->is_anything_selected())
+ {
+ const auto& atlas = ed->get_selected()->factory->atlas();
+ draw(_wireframe_quad, TILE_SIZE2);
+ shader.set_tint({1, 1, 1, 0.75f});
+ auto [_f, _w, anim_mesh] = M->meshes();
+ const auto pos = cursor.tile->to_signed3()*iTILE_SIZE;
+ anim_mesh.draw(shader, *atlas, rotation::N, 0, Vector3(pos), 1);
+ }
+ }
shader.set_tint({1, 1, 1, 1});
}
@@ -79,10 +93,8 @@ void app::draw_collision_boxes()
for (int8_t z = z_min; z <= z_max; z++)
{
- if (z == _z_level)
- shader.set_tint({0, .5f, 1, 1});
- else
- shader.set_tint({.7f, .7f, .7f, .6f});
+ constexpr Vector4 pass_tint = {.7f, .7f, .7f, .6f};
+ const auto tint = z == _z_level ? Vector4{0, .5f, 1, 1} : Vector4{.7f, .7f, .7f, .6f};
for (int16_t y = miny; y <= maxy; y++)
for (int16_t x = minx; x <= maxx; x++)
@@ -99,12 +111,15 @@ void app::draw_collision_boxes()
constexpr float maxf = 1 << 24, max2f[] = { maxf, maxf }, min2f[] = { -maxf, -maxf };
const auto* rtree = c.rtree();
rtree->Search(min2f, max2f, [&](object_id data, const rect_type& rect) {
- [[maybe_unused]] auto x = std::bit_cast<collision_data>(data);
- Vector2 start(rect.m_min[0], rect.m_min[1]), end(rect.m_max[0], rect.m_max[1]);
- auto size = (end - start);
- auto center = Vector3(start + size*.5f, 0.f);
- _wireframe_rect.draw(shader, { center, size, 3 });
- return true;
+ [[maybe_unused]] auto x = std::bit_cast<collision_data>(data);
+ if (x.tag == (uint64_t)collision_type::geometry)
+ return true;
+ Vector2 start(rect.m_min[0], rect.m_min[1]), end(rect.m_max[0], rect.m_max[1]);
+ auto size = (end - start);
+ auto center = Vector3(start + size*.5f, 0.f);
+ shader.set_tint(x.pass == (uint64_t)pass_mode::pass ? pass_tint : tint);
+ _wireframe_rect.draw(shader, { center, size, 3 });
+ return true;
});
}
}
@@ -145,12 +160,14 @@ void app::draw_collision_boxes()
auto t1 = t0+Vector2(1e-4f);
const auto* rtree = c.rtree();
rtree->Search(t0.data(), t1.data(), [&](uint64_t data, const rect_type& rect) {
- [[maybe_unused]] auto x = std::bit_cast<collision_data>(data);
- Vector2 start(rect.m_min[0], rect.m_min[1]), end(rect.m_max[0], rect.m_max[1]);
- auto size = end - start;
- auto center = Vector3(start + size*.5f, 0.f);
- _wireframe_rect.draw(shader, { center, size, 3 });
- return true;
+ [[maybe_unused]] auto x = std::bit_cast<collision_data>(data);
+ if (x.tag == (uint64_t)collision_type::geometry)
+ return true;
+ Vector2 start(rect.m_min[0], rect.m_min[1]), end(rect.m_max[0], rect.m_max[1]);
+ auto size = end - start;
+ auto center = Vector3(start + size*.5f, 0.f);
+ _wireframe_rect.draw(shader, { center, size, 3 });
+ return true;
});
}
}
@@ -163,7 +180,7 @@ void app::draw()
{
if (_render_bboxes)
draw_collision_boxes();
- if (_editor.current_tile_editor() || _editor.current_scenery_editor())
+ if (_editor.current_tile_editor() || _editor.current_scenery_editor() || _editor.current_vobj_editor())
draw_cursor();
draw_ui();
render_menu();
@@ -186,7 +203,7 @@ clickable* app::find_clickable_scenery(const Optional<Vector2i>& pixel)
const auto pos = !c.mirrored ? pos_ : Vector2i(int(c.src.sizeX()) - 1 - pos_[0], pos_[1]);
size_t idx = unsigned(pos.y()) * c.stride + unsigned(pos.x());
fm_assert(idx < c.bitmask.size());
- if (c.bitmask[idx])
+ if (c.bitmask.isEmpty() || c.bitmask[idx])
{
depth = c.depth;
item = &c;
diff --git a/editor/editor-enums.hpp b/editor/editor-enums.hpp
index 3806674f..6480433f 100644
--- a/editor/editor-enums.hpp
+++ b/editor/editor-enums.hpp
@@ -3,7 +3,7 @@
namespace floormat {
enum class editor_mode : unsigned char {
- none, floor, walls, scenery,
+ none, floor, walls, scenery, vobj,
};
enum class editor_wall_rotation : unsigned char {
diff --git a/editor/editor.cpp b/editor/editor.cpp
index 99a3cf96..b744f03c 100644
--- a/editor/editor.cpp
+++ b/editor/editor.cpp
@@ -20,6 +20,8 @@ void editor::clear_selection()
ed->clear_selection();
else if (auto* ed = current_scenery_editor())
ed->clear_selection();
+ else if (auto* vo = current_vobj_editor())
+ vo->clear_selection();
}
auto editor::get_snap_value(snap_mode snap, int mods) const -> snap_mode
@@ -115,6 +117,23 @@ void editor::on_click_(world& world, global_coords pos, button b)
}
}
}
+ else if (auto* mode = current_vobj_editor())
+ {
+ if (const auto* opt = mode->get_selected(); opt || b == button::remove)
+ {
+ switch (b)
+ {
+ default: break;
+ case button::place:
+ if (const auto& sel = mode->get_selected())
+ mode->place_tile(world, pos, sel);
+ break;
+ case button::remove:
+ mode->place_tile(world, pos, {});
+ break;
+ }
+ }
+ }
on_release();
}
@@ -161,6 +180,14 @@ const scenery_editor* editor::current_scenery_editor() const noexcept
return nullptr;
}
+const vobj_editor* editor::current_vobj_editor() const noexcept
+{
+ if (_mode == editor_mode::vobj)
+ return &_vobj;
+ else
+ return nullptr;
+}
+
tile_editor* editor::current_tile_editor() noexcept
{
return const_cast<tile_editor*>(static_cast<const editor&>(*this).current_tile_editor());
@@ -171,4 +198,9 @@ scenery_editor* editor::current_scenery_editor() noexcept
return const_cast<scenery_editor*>(static_cast<const editor&>(*this).current_scenery_editor());
}
+vobj_editor* editor::current_vobj_editor() noexcept
+{
+ return const_cast<vobj_editor*>(static_cast<const editor&>(*this).current_vobj_editor());
+}
+
} // namespace floormat
diff --git a/editor/editor.hpp b/editor/editor.hpp
index 64d92611..868797fd 100644
--- a/editor/editor.hpp
+++ b/editor/editor.hpp
@@ -6,6 +6,7 @@
#include "editor-enums.hpp"
#include "tile-editor.hpp"
#include "scenery-editor.hpp"
+#include "vobj-editor.hpp"
#include <map>
#include <Corrade/Containers/Optional.h>
@@ -28,6 +29,8 @@ struct editor final
const tile_editor* current_tile_editor() const noexcept;
scenery_editor* current_scenery_editor() noexcept;
const scenery_editor* current_scenery_editor() const noexcept;
+ vobj_editor* current_vobj_editor() noexcept;
+ const vobj_editor* current_vobj_editor() const noexcept;
enum class button : unsigned char { none, place, remove, };
@@ -53,6 +56,7 @@ private:
tile_editor _floor{ editor_mode::floor, "floor"_s };
tile_editor _wall { editor_mode::walls, "wall"_s };
scenery_editor _scenery;
+ vobj_editor _vobj;
struct drag_pos final {
global_coords coord, draw_coord;
diff --git a/editor/imgui-editors.cpp b/editor/imgui-editors.cpp
index f5a1634d..0a1f61b0 100644
--- a/editor/imgui-editors.cpp
+++ b/editor/imgui-editors.cpp
@@ -1,5 +1,4 @@
#include "app.hpp"
-#include "scenery-editor.hpp"
#include "imgui-raii.hpp"
#include "anim-atlas.hpp"
#include "loader/loader.hpp"
@@ -10,12 +9,38 @@ namespace floormat {
using namespace floormat::imgui;
-void app::draw_editor_scenery_pane(scenery_editor& ed)
+static StringView scenery_type_to_string(const scenery_editor::scenery_& sc)
+{
+ switch (sc.proto.sc_type)
+ {
+ case scenery_type::none: return "none"_s; break;
+ case scenery_type::generic: return "generic"_s; break;
+ case scenery_type::door: return "door"_s; break;
+ default: return "unknown"_s; break;
+ }
+}
+
+static std::shared_ptr<anim_atlas> get_atlas(const scenery_editor::scenery_& sc)
+{
+ return sc.proto.atlas;
+}
+
+static StringView scenery_type_to_string(const vobj_editor::vobj_& vobj)
+{
+ return vobj.name;
+}
+
+static std::shared_ptr<anim_atlas> get_atlas(const vobj_editor::vobj_& vobj)
+{
+ return vobj.factory->atlas();
+}
+
+template<typename T>
+static void impl_draw_editor_scenery_pane(T& ed, Vector2 dpi)
{
const auto b1 = push_id("scenery-pane");
const auto& style = ImGui::GetStyle();
- const auto dpi = M->dpi_scale();
constexpr ImGuiTableFlags flags = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY;
constexpr int ncolumns = 4;
const auto size = ImGui::GetWindowSize();
@@ -41,12 +66,12 @@ void app::draw_editor_scenery_pane(scenery_editor& ed)
for (const auto& [name, scenery] : ed)
{
- fm_debug_assert(scenery.proto.atlas != nullptr);
+ fm_debug_assert(get_atlas(scenery));
ImGui::TableNextRow(ImGuiTableRowFlags_None, row_height);
if (ImGui::TableSetColumnIndex(0))
{
- auto& atlas = *scenery.proto.atlas;
+ auto& atlas = *get_atlas(scenery);
const auto r = atlas.first_rotation();
const auto& frame = atlas.frame(r, 0);
const auto size = Vector2(frame.size);
@@ -69,18 +94,13 @@ void app::draw_editor_scenery_pane(scenery_editor& ed)
}
if (ImGui::TableSetColumnIndex(2))
{
- switch (scenery.proto.sc_type)
- {
- case scenery_type::none: text("none"); break;
- case scenery_type::generic: text("generic"); break;
- case scenery_type::door: text("door"); break;
- default: text("unknown"); break;
- }
+ text(scenery_type_to_string(scenery));
click_event();
}
if (ImGui::TableSetColumnIndex(3))
{
- StringView name = loader.strip_prefix(scenery.proto.atlas->name());
+ auto& atlas = *get_atlas(scenery);
+ StringView name = loader.strip_prefix(atlas.name());
if (auto last = name.findLast('/'))
name = name.prefix(last.data());
else
@@ -91,11 +111,25 @@ void app::draw_editor_scenery_pane(scenery_editor& ed)
}
}
+template void impl_draw_editor_scenery_pane(scenery_editor&, Vector2);
+template void impl_draw_editor_scenery_pane(vobj_editor&, Vector2);
+
+void app::draw_editor_scenery_pane(scenery_editor& ed)
+{
+ impl_draw_editor_scenery_pane<scenery_editor>(ed, M->dpi_scale());
+}
+
+void app::draw_editor_vobj_pane(vobj_editor& ed)
+{
+ impl_draw_editor_scenery_pane<vobj_editor>(ed, M->dpi_scale());
+}
+
void app::draw_editor_pane(float main_menu_height)
{
auto* ed = _editor.current_tile_editor();
auto* sc = _editor.current_scenery_editor();
- fm_assert(!ed || !sc);
+ auto* vo = _editor.current_vobj_editor();
+ fm_assert(!ed || !sc || !vo);
const auto window_size = M->window_size();
const auto dpi = M->dpi_scale();
@@ -116,13 +150,15 @@ void app::draw_editor_pane(float main_menu_height)
if (main_menu_height > 0)
{
+ constexpr auto igwf = ImGuiWindowFlags_(ImGuiWindowFlags_NoDecoration |
+ ImGuiWindowFlags_NoMove |
+ ImGuiWindowFlags_NoSavedSettings);
const auto b = push_id("editor");
ImGui::SetNextWindowPos({0, main_menu_height+style.WindowPadding.y});
ImGui::SetNextFrameWantCaptureKeyboard(false);
- ImGui::SetNextWindowSize({425 * dpi[0], window_size[1] - main_menu_height - style.WindowPadding.y});
- if (const auto flags = ImGuiWindowFlags_(ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings);
- auto b = begin_window({}, nullptr, flags))
+ ImGui::SetNextWindowSize({425 * dpi[0], window_size[1]-main_menu_height - style.WindowPadding.y});
+ if (auto b = begin_window({}, nullptr, igwf))
{
const auto b2 = push_id("editor-pane");
if (auto b3 = begin_list_box("##atlases", {-FLT_MIN, -1}))
@@ -132,6 +168,8 @@ void app::draw_editor_pane(float main_menu_height)
draw_editor_tile_pane_atlas(*ed, k, v);
else if (sc)
draw_editor_scenery_pane(*sc);
+ else if (vo)
+ draw_editor_vobj_pane(*vo);
}
}
}
diff --git a/editor/update.cpp b/editor/update.cpp
index 64090973..5c6d4319 100644
--- a/editor/update.cpp
+++ b/editor/update.cpp
@@ -140,7 +140,7 @@ void app::do_rotate(bool backward)
void app::do_set_mode(editor_mode mode)
{
if (mode != _editor.mode())
- kill_popups(true);
+ kill_popups(false);
_editor.set_mode(mode);
}
diff --git a/editor/vobj-editor.cpp b/editor/vobj-editor.cpp
index 1c1f1cb3..2693c44a 100644
--- a/editor/vobj-editor.cpp
+++ b/editor/vobj-editor.cpp
@@ -7,10 +7,6 @@
#include <utility>
#include <Corrade/Containers/StringView.h>
-#if defined __clang__ || defined __CLION_IDE__
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#endif
-
namespace floormat {
StringView vobj_factory::name() const { return info().name; }
@@ -19,9 +15,14 @@ std::shared_ptr<anim_atlas> vobj_factory::atlas() const { return info().atlas; }
vobj_factory::vobj_factory() = default;
vobj_factory::~vobj_factory() noexcept = default;
-vobj_editor::vobj_::operator bool() const { return factory != nullptr; }
vobj_editor::vobj_editor() = default;
void vobj_editor::select_tile(const vobj_& type) { _selected = &type; }
+void vobj_editor::clear_selection() { _selected = nullptr; }
+
+auto vobj_editor::get_selected() const -> const vobj_*
+{
+ return _selected;
+}
auto vobj_editor::get_type(StringView name) -> const vobj_*
{
@@ -38,6 +39,33 @@ auto vobj_editor::get_type(StringView name) -> const vobj_*
bool vobj_editor::is_item_selected(const vobj_& x) const { return _selected == &x; }
bool vobj_editor::is_anything_selected() const { return _selected != nullptr; }
+void vobj_editor::place_tile(world& w, global_coords pos, const vobj_* x)
+{
+ if (!x)
+ {
+ // don't regen colliders
+ auto [c, t] = w[pos];
+ const auto px = Vector2(pos.local()) * TILE_SIZE2;
+ const auto es = c.entities();
+ for (auto i = es.size()-1; i != (size_t)-1; i--)
+ {
+ const auto& e = *es[i];
+ if (!e.is_virtual())
+ continue;
+ auto center = Vector2(e.coord.local())*TILE_SIZE2 + Vector2(e.offset) + Vector2(e.bbox_offset),
+ min = center - Vector2(e.bbox_size/2), max = min + Vector2(e.bbox_size);
+ if (px >= min && px <= max)
+ c.remove_entity(i);
+ }
+ }
+ else
+ x->factory->make(w, w.make_id(), pos);
+}
+
+#if defined __clang__ || defined __CLION_IDE__
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
struct light_factory final : vobj_factory
{
entity_type type() const override { return entity_type::light; }
@@ -58,7 +86,7 @@ struct light_factory final : vobj_factory
}
};
-static auto make_vobj_type_map()
+auto vobj_editor::make_vobj_type_map() -> std::map<StringView, vobj_>
{
constexpr auto add = [](auto& m, std::unique_ptr<vobj_factory>&& x) {
StringView name = x->name(), descr = x->descr();
@@ -69,6 +97,4 @@ static auto make_vobj_type_map()
return map;
}
-const std::map<StringView, vobj_editor::vobj_> vobj_editor::_types = make_vobj_type_map();
-
} // namespace floormat
diff --git a/editor/vobj-editor.hpp b/editor/vobj-editor.hpp
index 44688168..634311f2 100644
--- a/editor/vobj-editor.hpp
+++ b/editor/vobj-editor.hpp
@@ -43,27 +43,29 @@ struct vobj_editor final
struct vobj_ final {
StringView name, descr;
std::unique_ptr<vobj_factory> factory;
- operator bool() const;
};
vobj_editor();
void select_tile(const vobj_& type);
void clear_selection();
+ const vobj_* get_selected() const;
- static const vobj_* get_type(StringView name);
+ const vobj_* get_type(StringView name);
bool is_item_selected(const vobj_& x) const;
bool is_anything_selected() const;
- static void place_tile(world& w, global_coords pos, const vobj_& x);
+ static void place_tile(world& w, global_coords pos, const vobj_* x);
- static auto cbegin() noexcept { return _types.cbegin(); }
- static auto cend() noexcept { return _types.cend(); }
- static auto begin() noexcept { return _types.cbegin(); }
- static auto end() noexcept { return _types.cend(); }
+ auto cbegin() const noexcept { return _types.cbegin(); }
+ auto cend() const noexcept { return _types.cend(); }
+ auto begin() const noexcept { return _types.cbegin(); }
+ auto end() const noexcept { return _types.cend(); }
private:
- static const std::map<StringView, vobj_> _types;
+ static std::map<StringView, vobj_> make_vobj_type_map();
+
+ std::map<StringView, vobj_> _types = make_vobj_type_map();
const vobj_* _selected = nullptr;
};