summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-22 18:46:52 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-22 18:46:52 +0100
commit51ebc370743b07926ce0a50232a1a65c6b6b27b5 (patch)
tree9c38ee65e32c6a760065ef33fe078847d7ea2d48
parenta917bb7c28b383c3c684bf75732188bfff0060bb (diff)
finally it works
-rw-r--r--editor/app.cpp1
-rw-r--r--editor/app.hpp10
-rw-r--r--editor/draw.cpp30
-rw-r--r--editor/update.cpp10
-rw-r--r--floormat/main.hpp9
-rw-r--r--loader/atlas.cpp5
-rw-r--r--main/clickable.hpp20
-rw-r--r--main/draw.cpp28
-rw-r--r--main/main-impl.cpp12
-rw-r--r--main/main-impl.hpp19
-rw-r--r--src/anim-atlas.cpp25
11 files changed, 147 insertions, 22 deletions
diff --git a/editor/app.cpp b/editor/app.cpp
index bd7748fb..9f8914f0 100644
--- a/editor/app.cpp
+++ b/editor/app.cpp
@@ -52,6 +52,7 @@ static bool parse_bool(StringView name, const Corrade::Utility::Arguments& args,
return def;
}
+[[maybe_unused]]
static int atoi_(const char* str)
{
bool negative = false;
diff --git a/editor/app.hpp b/editor/app.hpp
index 5bf87552..badca9a9 100644
--- a/editor/app.hpp
+++ b/editor/app.hpp
@@ -31,6 +31,15 @@ struct cursor_state final {
bool in_imgui = false;
};
+template<typename Atlas, typename T> struct clickable;
+using clickable_scenery = clickable<anim_atlas, scenery>;
+
+enum class Cursor: std::uint32_t {
+ Arrow, TextInput, Wait, Crosshair, WaitArrow,
+ ResizeNWSE, ResizeNESW, ResizeWE, ResizeNS, ResizeAll,
+ No, Hand, Hidden, HiddenLocked,
+};
+
struct app final : floormat_app
{
static int run_from_argv(int argc, const char* const* argv);
@@ -76,6 +85,7 @@ private:
void do_camera(float dt, const key_set& cmds, int mods);
void reset_camera_offset();
+ clickable_scenery* find_clickable_scenery();
void do_quicksave();
void do_quickload();
diff --git a/editor/draw.cpp b/editor/draw.cpp
index af4fbdcb..9915a93e 100644
--- a/editor/draw.cpp
+++ b/editor/draw.cpp
@@ -2,6 +2,8 @@
#include "floormat/main.hpp"
#include "floormat/settings.hpp"
#include "shaders/tile.hpp"
+#include "main/clickable.hpp"
+#include "src/anim-atlas.hpp"
#include <Magnum/Math/Vector3.h>
namespace floormat {
@@ -38,4 +40,32 @@ void app::draw()
render_menu();
}
+clickable_scenery* app::find_clickable_scenery()
+{
+ if (cursor.tile)
+ {
+ float depth = -2;
+ clickable_scenery* item = nullptr;
+ auto array = M->clickable_scenery();
+ const auto pixel = Vector2ui(*cursor.pixel);
+ for (clickable_scenery& c : array)
+ {
+ if (c.depth > depth && c.dest.contains(pixel))
+ {
+ const auto pos = pixel - c.dest.min() + c.src.min();
+ const auto stride = c.atlas.info().pixel_size[0];
+ std::size_t idx = pos.y() * stride + pos.x();
+ fm_debug_assert(idx < c.bitmask.size());
+ if (c.bitmask[idx])
+ {
+ depth = c.depth;
+ item = &c;
+ }
+ }
+ }
+ return item;
+ }
+ return nullptr;
+}
+
} // namespace floormat
diff --git a/editor/update.cpp b/editor/update.cpp
index 60d012d2..c68c7517 100644
--- a/editor/update.cpp
+++ b/editor/update.cpp
@@ -29,7 +29,7 @@ void app::maybe_initialize_chunk_(const chunk_coords& pos, chunk& c)
c[{K, K }].wall_west() = { _wall2, 0 };
c[{K, K+1}].wall_north() = { _wall1, 0 };
c[{K+1, K }].wall_west() = { _wall2, 0 };
- c[{K+1, K+1}].scenery() = { scenery::door, rotation::N, _door, false };
+ c[{K+3, K+1}].scenery() = { scenery::door, rotation::N, _door, false };
c.mark_modified();
}
@@ -98,10 +98,18 @@ void app::apply_commands(const key_set& keys)
do_key(k, key_modifiers[i]);
}
+using clickable_scenery = clickable<anim_atlas, scenery>;
+
+
+
void app::update(float dt)
{
apply_commands(keys);
do_camera(dt, keys, get_key_modifiers());
+ if (auto* s = find_clickable_scenery())
+ M->set_cursor(std::uint32_t(Cursor::Hand));
+ else
+ M->set_cursor(std::uint32_t(Cursor::Arrow));
clear_non_repeated_keys();
}
diff --git a/floormat/main.hpp b/floormat/main.hpp
index ee6d9e60..b4e4d536 100644
--- a/floormat/main.hpp
+++ b/floormat/main.hpp
@@ -5,6 +5,7 @@
#include <Magnum/Math/Vector2.h>
struct SDL_Window;
+namespace Corrade::Containers { template<typename T> class ArrayView; }
namespace floormat {
@@ -12,6 +13,9 @@ struct fm_settings;
struct floormat_app;
struct tile_shader;
struct world;
+struct scenery;
+struct anim_atlas;
+template<typename Atlas, typename T> struct clickable;
struct floormat_main
{
@@ -35,6 +39,11 @@ struct floormat_main
virtual void start_text_input() noexcept = 0;
virtual void stop_text_input() noexcept = 0;
+ virtual ArrayView<const clickable<anim_atlas, scenery>> clickable_scenery() const noexcept = 0;
+ virtual ArrayView<clickable<anim_atlas, scenery>> clickable_scenery() noexcept = 0;
+ virtual void set_cursor(std::uint32_t cursor) noexcept = 0;
+ virtual std::uint32_t cursor() const noexcept = 0;
+
virtual global_coords pixel_to_tile(Vector2d position) const noexcept = 0;
virtual struct world& world() noexcept = 0;
diff --git a/loader/atlas.cpp b/loader/atlas.cpp
index 4a5c6cfa..fdafc39e 100644
--- a/loader/atlas.cpp
+++ b/loader/atlas.cpp
@@ -5,6 +5,7 @@
#include "src/anim-atlas.hpp"
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/Pair.h>
+#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Utility/Path.h>
#include <Magnum/Trade/ImageData.h>
@@ -40,6 +41,10 @@ std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name)
fm_assert(!anim_info.groups.empty());
fm_assert(anim_info.nframes > 0);
fm_assert(anim_info.nframes == 1 || anim_info.fps > 0);
+ const auto size = tex.pixels().size();
+ const auto width = size[1], height = size[0];
+ using Vector2uz = Math::Vector2<std::size_t>;
+ fm_assert(Vector2uz{anim_info.pixel_size} == Vector2uz(width, height));
auto atlas = std::make_shared<struct anim_atlas>(path, tex, std::move(anim_info));
return anim_atlas_map[atlas->name()] = atlas;
diff --git a/main/clickable.hpp b/main/clickable.hpp
new file mode 100644
index 00000000..efc1a7fa
--- /dev/null
+++ b/main/clickable.hpp
@@ -0,0 +1,20 @@
+#pragma once
+#include "src/global-coords.hpp"
+#include <Corrade/Containers/BitArrayView.h>
+#include <Magnum/Math/Range.h>
+
+namespace floormat {
+
+template<typename Atlas, typename T>
+struct clickable final {
+
+ Atlas& atlas;
+ T& item;
+ Math::Range2D<UnsignedInt> src, dest;
+ BitArrayView bitmask;
+ float depth = 0;
+ chunk_coords chunk;
+ local_coords pos;
+};
+
+} // namespace floormat
diff --git a/main/draw.cpp b/main/draw.cpp
index 6b6c39a4..ba15b365 100644
--- a/main/draw.cpp
+++ b/main/draw.cpp
@@ -2,6 +2,8 @@
#include "floormat/app.hpp"
#include "src/camera-offset.hpp"
#include "src/anim-atlas.hpp"
+#include "main/clickable.hpp"
+#include <Corrade/Containers/ArrayView.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Renderer.h>
#include <Magnum/Math/Color.h>
@@ -111,17 +113,19 @@ void main_impl::draw_anim() noexcept
const local_coords xy{i};
if (auto [atlas, s] = c[xy].scenery(); atlas)
{
+ _anim_mesh.draw(_shader, *atlas, s.r, s.frame, xy);
const auto& g = atlas->group(s.r);
const auto& f = atlas->frame(s.r, s.frame);
- const auto& mask = atlas->bitmask();
- Vector2 offset;
constexpr Vector2 pixel88 = tile_shader::project(TILE_MAX_DIM*TILE_SIZE20*.5f);
const auto world_pos = TILE_SIZE20 * Vector3(xy.x, xy.y, 0) + Vector3(g.offset);
- offset += (Vector2(_shader.camera_offset()) + Vector2(sz))*.5f;
- //offset += _shader.project(world_pos);
- //offset -= Vector2(f.ground);
- Debug{} << "offset" << offset.x() << offset.y();
- _anim_mesh.draw(_shader, *atlas, s.r, s.frame, xy);
+ const Vector2ui offset((Vector2(_shader.camera_offset()) + Vector2(sz) - pixel88)*.5f
+ + _shader.project(world_pos) - Vector2(f.ground));
+ clickable<anim_atlas, scenery> item = {
+ *atlas, s,
+ { f.offset, f.offset + f.size }, { offset, offset + f.size },
+ atlas->bitmask(), tile_shader::depth_value(xy, 0.25f), pos, xy
+ };
+ _clickable_scenery.push_back(item);
}
}
}
@@ -217,4 +221,14 @@ void main_impl::drawEvent()
timeline.nextFrame();
}
+ArrayView<const clickable<anim_atlas, scenery>> main_impl::clickable_scenery() const noexcept
+{
+ return { _clickable_scenery.data(), _clickable_scenery.size() };
+}
+
+ArrayView<clickable<anim_atlas, scenery>> main_impl::clickable_scenery() noexcept
+{
+ return { _clickable_scenery.data(), _clickable_scenery.size() };
+}
+
} // namespace floormat
diff --git a/main/main-impl.cpp b/main/main-impl.cpp
index dec3948f..0790a0d2 100644
--- a/main/main-impl.cpp
+++ b/main/main-impl.cpp
@@ -1,5 +1,6 @@
#include "main-impl.hpp"
#include "compat/assert.hpp"
+#include <Magnum/Platform/Sdl2Application.h>
namespace floormat {
@@ -33,4 +34,15 @@ floormat_main* floormat_main::create(floormat_app& app, fm_settings&& options)
return ret;
}
+void main_impl::set_cursor(std::uint32_t cursor) noexcept
+{
+ setCursor(Cursor(cursor));
+}
+
+std::uint32_t main_impl::cursor() const noexcept
+{
+ using App = Platform::Sdl2Application;
+ return (std::uint32_t)static_cast<App*>(const_cast<main_impl*>(this))->cursor();
+}
+
} // namespace floormat
diff --git a/main/main-impl.hpp b/main/main-impl.hpp
index d54b7f92..7adaeaec 100644
--- a/main/main-impl.hpp
+++ b/main/main-impl.hpp
@@ -6,6 +6,7 @@
#include "draw/wall.hpp"
#include "draw/anim.hpp"
#include "shaders/tile.hpp"
+#include "main/clickable.hpp"
#include <vector>
#include <Corrade/Containers/String.h>
#include <Magnum/Timeline.h>
@@ -19,13 +20,9 @@
namespace floormat {
struct floormat_app;
-
-struct clickable final {
-
- float depth = 0;
- chunk_coords chunk;
- local_coords pos;
-};
+struct scenery;
+struct anim_atlas;
+template<typename Atlas, typename T> struct clickable;
struct main_impl final : Platform::Sdl2Application, floormat_main
{
@@ -47,6 +44,9 @@ struct main_impl final : Platform::Sdl2Application, floormat_main
global_coords pixel_to_tile(Vector2d position) const noexcept override;
+ ArrayView<const clickable<anim_atlas, scenery>> clickable_scenery() const noexcept override;
+ ArrayView<clickable<anim_atlas, scenery>> clickable_scenery() noexcept override;
+
[[maybe_unused]] void viewportEvent(ViewportEvent& event) override;
[[maybe_unused]] void mousePressEvent(MouseEvent& event) override;
[[maybe_unused]] void mouseReleaseEvent(MouseEvent& event) override;
@@ -68,12 +68,15 @@ struct main_impl final : Platform::Sdl2Application, floormat_main
void debug_callback(unsigned src, unsigned type, unsigned id, unsigned severity, const std::string& str) const;
+ void set_cursor(std::uint32_t cursor) noexcept override;
+ std::uint32_t cursor() const noexcept override;
+
private:
fm_settings s;
[[maybe_unused]] char _dummy = maybe_register_debug_callback(s.gpu_debug);
floormat_app& app; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
tile_shader _shader;
- std::vector<clickable> _clickable_scenery;
+ std::vector<clickable<anim_atlas, scenery>> _clickable_scenery;
struct world _world{};
Magnum::Timeline timeline;
floor_mesh _floor_mesh;
diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp
index 345ca63e..b357a386 100644
--- a/src/anim-atlas.cpp
+++ b/src/anim-atlas.cpp
@@ -3,6 +3,7 @@
#include "shaders/tile.hpp"
#include "tile-defs.hpp"
#include <Corrade/Containers/BitArrayView.h>
+#include <Corrade/Containers/StridedArrayView.h>
#include <Magnum/Math/Color.h>
#include <Magnum/GL/TextureFormat.h>
@@ -35,9 +36,12 @@ anim_atlas::anim_atlas(StringView name, const ImageView2D& image, anim_def info)
_name{name}, _bitmask{make_bit_array(image)},
_info{std::move(info)}, _group_indices{make_group_indices(_info)}
{
+ const Size<3>& size = image.pixels().size();
+ fm_assert(size[0]*size[1] == _info.pixel_size.product());
+ fm_assert(size[2] >= 3 && size[2] <= 4);
_tex.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
- .setMinificationFilter(GL::SamplerFilter::Linear)
+ .setMinificationFilter(GL::SamplerFilter::Nearest)
.setMaxAnisotropy(1)
.setBorderColor(Color4{1, 0, 0, 1})
.setStorage(1, GL::textureFormat(image.format()), image.size())
@@ -102,12 +106,21 @@ auto anim_atlas::frame_quad(const Vector3& center, rotation r, std::size_t i) co
BitArray anim_atlas::make_bit_array(const ImageView2D& tex)
{
+ const auto pixels = tex.pixels();
+ const auto size = pixels.size();
+ const auto width = size[1], height = size[0];
+
+ if (tex.pixelSize() == 3)
+ return BitArray{DirectInit, width*height, true};
+
fm_assert(tex.pixelSize() == 4);
- const auto size = (std::size_t)tex.size().product();
- BitArray array{NoInit, size};
- const char* __restrict data = tex.data().data();
- for (std::size_t i = 0; i < size; i++)
- array.set(i, data[i * 4 + 3] != 0);
+ const auto stride = (std::size_t)pixels.stride()[0];
+ const auto channels = (std::size_t)pixels.stride()[1];
+ BitArray array{NoInit, width*height};
+ const char* __restrict const data = (const char*)tex.pixels().data();
+ for (std::size_t y = 0; y < height; y++)
+ for (std::size_t x = 0; x < width; x++)
+ array.set(y*width + x, data[(height-y-1)*stride + x*channels + 3] != 0);
return array;
}