diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-22 18:46:52 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-22 18:46:52 +0100 |
commit | 51ebc370743b07926ce0a50232a1a65c6b6b27b5 (patch) | |
tree | 9c38ee65e32c6a760065ef33fe078847d7ea2d48 | |
parent | a917bb7c28b383c3c684bf75732188bfff0060bb (diff) |
finally it works
-rw-r--r-- | editor/app.cpp | 1 | ||||
-rw-r--r-- | editor/app.hpp | 10 | ||||
-rw-r--r-- | editor/draw.cpp | 30 | ||||
-rw-r--r-- | editor/update.cpp | 10 | ||||
-rw-r--r-- | floormat/main.hpp | 9 | ||||
-rw-r--r-- | loader/atlas.cpp | 5 | ||||
-rw-r--r-- | main/clickable.hpp | 20 | ||||
-rw-r--r-- | main/draw.cpp | 28 | ||||
-rw-r--r-- | main/main-impl.cpp | 12 | ||||
-rw-r--r-- | main/main-impl.hpp | 19 | ||||
-rw-r--r-- | src/anim-atlas.cpp | 25 |
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; } |