diff options
-rw-r--r-- | draw/anim.cpp | 9 | ||||
-rw-r--r-- | draw/anim.hpp | 1 | ||||
-rw-r--r-- | editor/draw.cpp | 11 | ||||
-rw-r--r-- | editor/editor.cpp | 36 | ||||
-rw-r--r-- | editor/editor.hpp | 1 | ||||
-rw-r--r-- | editor/scenery-editor.cpp | 25 | ||||
-rw-r--r-- | editor/scenery-editor.hpp | 8 | ||||
-rw-r--r-- | editor/update.cpp | 44 | ||||
-rw-r--r-- | floormat/main.hpp | 9 | ||||
-rw-r--r-- | main/main-impl.hpp | 1 | ||||
-rw-r--r-- | main/setup.cpp | 5 | ||||
-rw-r--r-- | src/chunk.cpp | 2 | ||||
-rw-r--r-- | src/chunk.hpp | 8 |
13 files changed, 126 insertions, 34 deletions
diff --git a/draw/anim.cpp b/draw/anim.cpp index 82f0d746..951c7f5a 100644 --- a/draw/anim.cpp +++ b/draw/anim.cpp @@ -22,13 +22,11 @@ std::array<UnsignedShort, 6> anim_mesh::make_index_array() }}; } -void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::size_t frame, local_coords xy) +void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::size_t frame, const Vector3& center, float depth) { - const auto center = Vector3(xy.x, xy.y, 0.f) * TILE_SIZE; const auto pos = atlas.frame_quad(center, r, frame); const auto& g = atlas.group(r); const auto texcoords = atlas.texcoords_for_frame(r, frame, !g.mirror_from.isEmpty()); - const float depth = tile_shader::depth_value(xy, .25f); quad_data array; for (std::size_t i = 0; i < 4; i++) array[i] = { pos[i], texcoords[i], depth }; @@ -37,4 +35,9 @@ void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::si shader.draw(_mesh); } +void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::size_t frame, local_coords xy) +{ + draw(shader, atlas, r, frame, Vector3(xy.x, xy.y, 0.f) * TILE_SIZE, tile_shader::depth_value(xy, .25f)); +} + } // namespace floormat diff --git a/draw/anim.hpp b/draw/anim.hpp index 2b88e7af..e11d45ae 100644 --- a/draw/anim.hpp +++ b/draw/anim.hpp @@ -23,6 +23,7 @@ struct anim_mesh final { anim_mesh(); void draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::size_t frame, local_coords xy); + void draw(tile_shader& shader, anim_atlas& atlas, rotation r, std::size_t frame, const Vector3& pos, float depth); private: struct vertex_data final { diff --git a/editor/draw.cpp b/editor/draw.cpp index e0ddc743..dbb34324 100644 --- a/editor/draw.cpp +++ b/editor/draw.cpp @@ -4,6 +4,7 @@ #include "shaders/tile.hpp" #include "main/clickable.hpp" #include "src/anim-atlas.hpp" +#include "draw/anim.hpp" #include <Magnum/Math/Vector3.h> namespace floormat { @@ -11,14 +12,14 @@ namespace floormat { void app::draw_cursor() { constexpr float LINE_WIDTH = 2; + auto& shader = M->shader(); + shader.set_tint({1, 0, 0, 1}); if (const auto [pos, b] = cursor.tile; b && !cursor.in_imgui) { const auto draw = [&, pos = pos](auto& mesh, const auto& size) { const auto pt = pos.to_signed(); const Vector3 center{Vector3i(pt[0], pt[1], 0) * iTILE_SIZE}; - auto& shader = M->shader(); - shader.set_tint({1, 0, 0, 1}); mesh.draw(shader, {center, size, LINE_WIDTH}); }; @@ -34,7 +35,13 @@ void app::draw_cursor() draw(_wireframe_quad, TILE_SIZE2); } else if (const auto* ed = _editor.current_scenery_editor(); ed && ed->is_anything_selected()) + { + const auto& sel = ed->get_selected().proto; draw(_wireframe_quad, TILE_SIZE2); + shader.set_tint({1, 1, 1, 0.75f}); + auto [_f, _w, anim_mesh] = M->meshes(); + anim_mesh.draw(shader, *sel.atlas, sel.frame.r, sel.frame.frame, cursor.tile->local()); + } } } diff --git a/editor/editor.cpp b/editor/editor.cpp index 3400f5af..11d26fdd 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -16,6 +16,14 @@ void editor::on_release() _last_pos = NullOpt; } +void editor::clear_selection() +{ + if (auto* ed = current_tile_editor()) + ed->clear_selection(); + else if (auto* ed = current_scenery_editor()) + ed->clear_selection(); +} + auto editor::get_snap_value(snap_mode snap, int mods) const -> snap_mode { @@ -81,6 +89,7 @@ void editor::on_mouse_move(world& world, global_coords& pos, int mods) void editor::on_click_(world& world, global_coords pos, button b) { if (auto* mode = current_tile_editor(); mode != nullptr) + { if (auto opt = mode->get_selected(); opt || b == button::remove) { switch (b) @@ -90,16 +99,39 @@ void editor::on_click_(world& world, global_coords pos, button b) default: break; } } + } + else if (auto* mode = current_scenery_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(); } void editor::on_click(world& world, global_coords pos, int mods, button b) { - if (auto* mode = current_tile_editor(); mode != nullptr) + if (auto* mode = current_tile_editor()) { _last_pos = { InPlaceInit, pos, pos, mode->check_snap(mods), b }; on_click_(world, pos, b); } + else if (current_scenery_editor()) + { + _last_pos = {}; + on_click_(world, pos, b); + } } editor::editor() = default; @@ -117,7 +149,7 @@ const tile_editor* editor::current_tile_editor() const noexcept case editor_mode::floor: return &_floor; case editor_mode::walls: - return &_wall; // todo + return &_wall; default: return nullptr; } diff --git a/editor/editor.hpp b/editor/editor.hpp index 1bbc3a89..eac544ad 100644 --- a/editor/editor.hpp +++ b/editor/editor.hpp @@ -36,6 +36,7 @@ struct editor final void on_click_(world& world, global_coords pos, button b); void on_mouse_move(world& world, global_coords& pos, int modifiers); void on_release(); + void clear_selection(); editor(); editor(editor&&) noexcept = default; diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp index a6870180..d8f74f7d 100644 --- a/editor/scenery-editor.cpp +++ b/editor/scenery-editor.cpp @@ -2,12 +2,18 @@ #include "src/anim-atlas.hpp" #include "loader/loader.hpp" #include "compat/assert.hpp" +#include "src/world.hpp" namespace floormat { using rotation_ = rotation; using rotation_t = std::underlying_type_t<rotation_>; +scenery_editor::scenery_::operator bool() const noexcept +{ + return proto; +} + scenery_editor::scenery_editor() noexcept { load_atlases(); @@ -29,19 +35,19 @@ rotation_ scenery_editor::rotation() const void scenery_editor::next_rotation() { - if (auto& proto = _selected.proto; proto.atlas) - proto.frame.r = proto.atlas->next_rotation_from(proto.frame.r); + if (_selected) + set_rotation(_selected.proto.atlas->next_rotation_from(_selected.proto.frame.r)); } void scenery_editor::prev_rotation() { - if (auto& proto = _selected.proto; proto.atlas) - proto.frame.r = proto.atlas->prev_rotation_from(proto.frame.r); + if (_selected) + set_rotation(_selected.proto.atlas->next_rotation_from(_selected.proto.frame.r)); } void scenery_editor::select_tile(const scenery_& s) { - const auto rot = is_anything_selected() && s.proto.atlas->check_rotation(_selected.proto.frame.r) + const auto rot = s.proto.atlas && s.proto.atlas->check_rotation(_selected.proto.frame.r) ? _selected.proto.frame.r : s.proto.frame.r; _selected = s; @@ -53,7 +59,7 @@ void scenery_editor::clear_selection() _selected = {}; } -auto scenery_editor::get_selected() -> const scenery_& +auto scenery_editor::get_selected() const -> const scenery_& { return _selected; } @@ -73,4 +79,11 @@ bool scenery_editor::is_anything_selected() const return _selected.proto.atlas != nullptr; } +void scenery_editor::place_tile(world& w, global_coords pos, const scenery_& s) +{ + auto [c, t] = w[pos]; + t.scenery() = s.proto; + c.mark_scenery_modified(); +} + } // namespace floormat diff --git a/editor/scenery-editor.hpp b/editor/scenery-editor.hpp index eb78bb01..8e47a6b8 100644 --- a/editor/scenery-editor.hpp +++ b/editor/scenery-editor.hpp @@ -1,5 +1,5 @@ #pragma once -#include "src/scenery.hpp" +#include "scenery.hpp" #include <map> #include <memory> #include <Corrade/Containers/String.h> @@ -7,12 +7,15 @@ namespace floormat { struct anim_atlas; +struct global_coords; +struct world; struct scenery_editor final { struct scenery_ final { String name, descr; scenery_proto proto; + operator bool() const noexcept; }; scenery_editor() noexcept; @@ -24,10 +27,11 @@ struct scenery_editor final void select_tile(const scenery_& s); void clear_selection(); - const scenery_& get_selected(); + const scenery_& get_selected() const; bool is_atlas_selected(const std::shared_ptr<anim_atlas>& atlas) const; bool is_item_selected(const scenery_& s) const; bool is_anything_selected() const; + void place_tile(world& w, global_coords pos, const scenery_& s); auto cbegin() const noexcept { return _atlases.cbegin(); } auto cend() const noexcept { return _atlases.cend(); } diff --git a/editor/update.cpp b/editor/update.cpp index cc68c4b5..18544a02 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -50,23 +50,33 @@ void app::do_mouse_move(int mods) void app::do_mouse_up_down(std::uint8_t button, bool is_down, int mods) { update_cursor_tile(cursor.pixel); - if (!_editor.current_tile_editor()) - { - if (cursor.tile) - if (auto* s = find_clickable_scenery(*cursor.pixel)) - s->item.activate(s->atlas); - } - else if (cursor.tile && !cursor.in_imgui && is_down) + + if (is_down && cursor.tile && !cursor.in_imgui) { - auto& w = M->world(); - auto pos = *cursor.tile; - switch (button) + switch (_editor.mode()) { - case mouse_button_left: - return _editor.on_click(w, pos, mods, editor::button::place); - case mouse_button_middle: - return _editor.on_click(w, pos, mods, editor::button::remove); - default: break; + default: + case editor_mode::none: + if (button == mouse_button_left) + if (auto* s = find_clickable_scenery(*cursor.pixel)) + return (void)s->item.activate(s->atlas); + break; + case editor_mode::floor: + case editor_mode::walls: + case editor_mode::scenery: + auto& w = M->world(); + auto pos = *cursor.tile; + switch (button) + { + case mouse_button_left: + return _editor.on_click(w, pos, mods, editor::button::place); + case mouse_button_middle: + return _editor.on_click(w, pos, mods, editor::button::remove); + case mouse_button_right: + return _editor.clear_selection(); + default: break; + } + break; } } _editor.on_release(); @@ -81,8 +91,10 @@ void app::do_key(key k, int mods) fm_warn("unhandled key: '%zu'", std::size_t(k)); return; case key_rotate_tile: - if (auto* ed = _editor.current_tile_editor(); ed) + if (auto* ed = _editor.current_tile_editor()) ed->toggle_rotation(); + else if (auto* ed = _editor.current_scenery_editor()) + ed->next_rotation(); return; case key_mode_none: return _editor.set_mode(editor_mode::none); diff --git a/floormat/main.hpp b/floormat/main.hpp index a470f12e..af388de4 100644 --- a/floormat/main.hpp +++ b/floormat/main.hpp @@ -16,10 +16,18 @@ struct world; struct scenery; struct anim_atlas; template<typename Atlas, typename T> struct clickable; +struct floor_mesh; +struct wall_mesh; +struct anim_mesh; struct floormat_main { struct draw_bounds final { std::int16_t minx, maxx, miny, maxy; }; + struct meshes final { + floor_mesh& floor; + wall_mesh& wall; + anim_mesh& anim; + }; floormat_main() noexcept; virtual ~floormat_main() noexcept; @@ -48,6 +56,7 @@ struct floormat_main virtual global_coords pixel_to_tile(Vector2d position) const noexcept = 0; virtual draw_bounds get_draw_bounds() const noexcept = 0; + virtual struct meshes meshes() noexcept = 0; virtual struct world& world() noexcept = 0; virtual SDL_Window* window() noexcept = 0; diff --git a/main/main-impl.hpp b/main/main-impl.hpp index 945b2196..cc17f9bc 100644 --- a/main/main-impl.hpp +++ b/main/main-impl.hpp @@ -58,6 +58,7 @@ struct main_impl final : Platform::Sdl2Application, floormat_main void drawEvent() override; void do_update(); void update_window_state(); + struct meshes meshes() noexcept override; bool is_text_input_active() const noexcept override; void start_text_input() noexcept override; diff --git a/main/setup.cpp b/main/setup.cpp index 3a251451..72bf3550 100644 --- a/main/setup.cpp +++ b/main/setup.cpp @@ -111,4 +111,9 @@ void main_impl::update_window_state() } } +auto main_impl::meshes() noexcept -> struct meshes +{ + return { _floor_mesh, _wall_mesh, _anim_mesh, }; +}; + } // namespace floormat diff --git a/src/chunk.cpp b/src/chunk.cpp index 6a325125..55afe1b9 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -147,11 +147,13 @@ chunk& chunk::operator=(chunk&&) noexcept = default; void chunk::mark_ground_modified() noexcept { _ground_modified = true; } void chunk::mark_walls_modified() noexcept { _walls_modified = true; } +void chunk::mark_scenery_modified() noexcept { _scenery_modified = true; } void chunk::mark_modified() noexcept { mark_ground_modified(); mark_walls_modified(); + mark_scenery_modified(); } } // namespace floormat diff --git a/src/chunk.hpp b/src/chunk.hpp index 16533e5a..9acd5f12 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -41,6 +41,7 @@ struct chunk final void mark_ground_modified() noexcept; void mark_walls_modified() noexcept; + void mark_scenery_modified() noexcept; void mark_modified() noexcept; struct ground_mesh_tuple final { @@ -69,9 +70,10 @@ private: std::array<scenery, TILE_COUNT> _scenery_variants = {}; std::bitset<TILE_COUNT*2> _passability = {}; GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate}; - mutable bool _maybe_empty : 1 = true, - _ground_modified : 1 = true, - _walls_modified : 1 = true; + mutable bool _maybe_empty : 1 = true, + _ground_modified : 1 = true, + _walls_modified : 1 = true, + _scenery_modified : 1 = true; }; } // namespace floormat |