summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--draw/anim.cpp9
-rw-r--r--draw/anim.hpp1
-rw-r--r--editor/draw.cpp11
-rw-r--r--editor/editor.cpp36
-rw-r--r--editor/editor.hpp1
-rw-r--r--editor/scenery-editor.cpp25
-rw-r--r--editor/scenery-editor.hpp8
-rw-r--r--editor/update.cpp44
-rw-r--r--floormat/main.hpp9
-rw-r--r--main/main-impl.hpp1
-rw-r--r--main/setup.cpp5
-rw-r--r--src/chunk.cpp2
-rw-r--r--src/chunk.hpp8
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