summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/userconfig-you@Clang.cmake13
-rw-r--r--editor/editor.hpp25
-rw-r--r--editor/precomp.hpp5
-rw-r--r--editor/scenery-editor.cpp40
-rw-r--r--editor/scenery-editor.hpp37
-rw-r--r--loader/loader-impl.cpp78
-rw-r--r--main/precomp.hpp2
-rw-r--r--src/anim-atlas.cpp14
-rw-r--r--src/anim-atlas.hpp3
-rw-r--r--src/loader.hpp13
-rw-r--r--src/scenery.hpp11
11 files changed, 181 insertions, 60 deletions
diff --git a/doc/userconfig-you@Clang.cmake b/doc/userconfig-you@Clang.cmake
index 2f9a9987..543b36c7 100644
--- a/doc/userconfig-you@Clang.cmake
+++ b/doc/userconfig-you@Clang.cmake
@@ -1,16 +1,3 @@
-if(FLOORMAT_WITH-COVERAGE)
- set(CMAKE_BUILD_TYPE DEBUG CACHE STRING "" FORCE)
- add_definitions(
- -fprofile-instr-generate
- -fcoverage-mapping
- -mllvm -runtime-counter-relocation=true
- )
- add_link_options(
- -fprofile-instr-generate
- -fcoverage-mapping
- )
-endif()
-
add_compile_options(-emit-llvm)
sets(STRING
CMAKE_C_FLAGS ""
diff --git a/editor/editor.hpp b/editor/editor.hpp
index 94cb7709..b25e6900 100644
--- a/editor/editor.hpp
+++ b/editor/editor.hpp
@@ -6,6 +6,7 @@
#include "scenery.hpp"
#include "editor-enums.hpp"
#include "tile-editor.hpp"
+#include "scenery-editor.hpp"
#include <optional>
#include <map>
@@ -18,30 +19,6 @@ struct world;
struct anim_atlas;
struct tile_atlas;
-struct scenery_editor final
-{
- struct pair final {
- std::shared_ptr<anim_atlas> atlas;
- scenery s;
- };
-
- scenery_editor() noexcept;
-
- void set_rotation(rotation r);
- void rotation() const;
- void next_rotation();
- void prev_rotation();
-
- void select_tile(const std::shared_ptr<anim_atlas>& atlas, enum rotation r, std::uint16_t frame);
- void clear_selection();
-
-private:
- void load_atlases();
-
- std::map<StringView, std::shared_ptr<anim_atlas>> _atlases;
- pair _selected_frame;
-};
-
struct editor final
{
[[nodiscard]] bool dirty() const noexcept { return _dirty; }
diff --git a/editor/precomp.hpp b/editor/precomp.hpp
index f309133a..93ff8164 100644
--- a/editor/precomp.hpp
+++ b/editor/precomp.hpp
@@ -8,6 +8,7 @@
#include <Magnum/Math/Color.h>
#include <Magnum/GL/DebugOutput.h>
#include <Magnum/GL/Renderer.h>
-#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/ImGuiIntegration/Context.h>
-
+#if __has_include(<SDL.h>)
+#include <Magnum/Platform/Sdl2Application.h>
+#endif
diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp
new file mode 100644
index 00000000..c3b29c9d
--- /dev/null
+++ b/editor/scenery-editor.cpp
@@ -0,0 +1,40 @@
+#include "scenery-editor.hpp"
+#include "src/anim-atlas.hpp"
+
+namespace floormat {
+
+using rotation_ = enum rotation;
+using rotation_t = std::underlying_type_t<rotation_>;
+
+scenery_editor::scenery_editor() noexcept
+{
+}
+
+void scenery_editor::set_rotation(enum rotation r)
+{
+ _selected.s.r = r;
+}
+
+rotation scenery_editor::rotation() const
+{
+ return _selected.s.r;
+}
+
+void scenery_editor::next_rotation()
+{
+ auto r_1 = (rotation_t)_selected.s.r + 1;
+ auto rot = (rotation_)r_1;
+ if (rot >= rotation_::COUNT)
+ rot = (rotation_)0;
+ _selected.s.r = rot;
+}
+
+void scenery_editor::prev_rotation()
+{
+ if (_selected.s.r == (rotation_)0)
+ _selected.s.r = (rotation_)((rotation_t)rotation_::COUNT - 1);
+ else
+ _selected.s.r = (rotation_)((rotation_t)_selected.s.r - 1);
+}
+
+} // namespace floormat
diff --git a/editor/scenery-editor.hpp b/editor/scenery-editor.hpp
new file mode 100644
index 00000000..f4b40c66
--- /dev/null
+++ b/editor/scenery-editor.hpp
@@ -0,0 +1,37 @@
+#pragma once
+#include "src/scenery.hpp"
+#include <map>
+#include <memory>
+#include <Corrade/Containers/StringView.h>
+
+namespace floormat {
+
+struct anim_atlas;
+
+struct scenery_editor final
+{
+ struct pair final {
+ std::shared_ptr<anim_atlas> atlas;
+ scenery s;
+ };
+
+ scenery_editor() noexcept;
+
+ void set_rotation(enum rotation r);
+ enum rotation rotation() const;
+ void next_rotation();
+ void prev_rotation();
+
+ void select_tile(const std::shared_ptr<anim_atlas>& atlas, enum rotation r, std::uint16_t frame);
+ void clear_selection();
+ bool is_atlas_selected() const;
+ bool is_item_selected(const std::shared_ptr<anim_atlas>& atlas, enum rotation r, std::uint16_t frame) const;
+
+private:
+ void load_atlases();
+
+ std::map<StringView, std::shared_ptr<anim_atlas>> _atlases;
+ pair _selected;
+};
+
+} // namespace floormat
diff --git a/loader/loader-impl.cpp b/loader/loader-impl.cpp
index 69a5f8ab..29234859 100644
--- a/loader/loader-impl.cpp
+++ b/loader/loader-impl.cpp
@@ -2,11 +2,17 @@
#include "src/tile-atlas.hpp"
#include "compat/assert.hpp"
#include "compat/alloca.hpp"
+#include "src/anim-atlas.hpp"
+#include "serialize/json-helper.hpp"
+#include "serialize/anim.hpp"
#include <filesystem>
#include <unordered_map>
#include <utility>
#include <optional>
+#include <Corrade/Containers/ArrayViewStl.h>
+#include <Corrade/Containers/StringView.h>
#include <Corrade/Containers/StringStlView.h>
+#include <Corrade/Containers/StringStlHash.h>
#include <Corrade/PluginManager/PluginManager.h>
#include <Corrade/Utility/Resource.h>
#include <Corrade/Utility/Path.h>
@@ -21,6 +27,8 @@
using StringView = Corrade::Containers::StringView;
+namespace Path = Corrade::Utility::Path;
+
namespace floormat {
struct loader_impl final : loader_
@@ -32,11 +40,17 @@ struct loader_impl final : loader_
PluginManager::Manager<Trade::AbstractImageConverter> image_converter_plugins;
- std::unordered_map<std::string, std::shared_ptr<struct tile_atlas>> atlas_map;
+ std::unordered_map<std::string, std::shared_ptr<struct tile_atlas>> tile_atlas_map;
+ std::unordered_map<StringView, std::shared_ptr<struct anim_atlas>> anim_atlas_map;
+ std::vector<String> anim_atlases;
StringView shader(StringView filename) override;
Trade::ImageData2D tile_texture(StringView filename) override;
std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size) override;
+ ArrayView<String> anim_atlas_list() override;
+ std::shared_ptr<struct anim_atlas> anim_atlas(StringView name) override;
+
+ void get_anim_atlas_list();
static void set_application_working_directory();
@@ -56,31 +70,31 @@ StringView loader_impl::shader(StringView filename)
std::shared_ptr<tile_atlas> loader_impl::tile_atlas(StringView name, Vector2ub size)
{
- auto it = std::find_if(atlas_map.begin(), atlas_map.end(), [&](const auto& x) {
+ auto it = std::find_if(tile_atlas_map.cbegin(), tile_atlas_map.cend(), [&](const auto& x) {
const auto& [k, v] = x;
return StringView{k} == name;
});
- if (it != atlas_map.end())
+ if (it != tile_atlas_map.cend())
return it->second;
auto image = tile_texture(name);
auto atlas = std::make_shared<struct tile_atlas>(name, image, size);
- atlas_map[name] = atlas;
+ tile_atlas_map[name] = atlas;
return atlas;
}
Trade::ImageData2D loader_impl::tile_texture(StringView filename_)
{
- static_assert(IMAGE_PATH[sizeof(IMAGE_PATH)-2] == '/');
+ static_assert(FM_IMAGE_PATH[sizeof(FM_IMAGE_PATH)-2] == '/');
fm_assert(filename_.size() < 4096);
fm_assert(filename_.find('\\') == filename_.end());
fm_assert(filename_.find('\0') == filename_.end());
fm_assert(tga_importer);
constexpr std::size_t max_extension_length = 16;
- char* const filename = (char*)alloca(filename_.size() + std::size(IMAGE_PATH) + max_extension_length);
+ char* const filename = (char*)alloca(filename_.size() + std::size(FM_IMAGE_PATH) + max_extension_length);
const std::size_t len = fm_begin(
- std::size_t off = std::size(IMAGE_PATH)-1;
- std::memcpy(filename, IMAGE_PATH, off);
+ std::size_t off = std::size(FM_IMAGE_PATH)-1;
+ std::memcpy(filename, FM_IMAGE_PATH, off);
std::memcpy(filename + off, filename_.cbegin(), filename_.size());
return off + filename_.size();
);
@@ -89,7 +103,7 @@ Trade::ImageData2D loader_impl::tile_texture(StringView filename_)
{
std::memcpy(filename + len, extension.data(), extension.size());
filename[len + extension.size()] = '\0';
- if (Utility::Path::exists(filename) && tga_importer->openFile(filename))
+ if (Path::exists(filename) && tga_importer->openFile(filename))
{
auto img = tga_importer->image2D(0);
if (!img)
@@ -102,11 +116,53 @@ Trade::ImageData2D loader_impl::tile_texture(StringView filename_)
fm_warn("can't open '%s'", filename);
}
}
- const auto path = Utility::Path::currentDirectory();
+ const auto path = Path::currentDirectory();
filename[len] = '\0';
fm_abort("can't open tile image '%s' (cwd '%s')", filename, path ? path->data() : "(null)");
}
+ArrayView<String> loader_impl::anim_atlas_list()
+{
+ if (anim_atlases.empty())
+ get_anim_atlas_list();
+ return anim_atlases;
+}
+
+std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name)
+{
+ if (auto it = anim_atlas_map.find(name); it != anim_atlas_map.end())
+ return it->second;
+ else
+ {
+ const auto path = Path::join(FM_ANIM_PATH, name);
+ std::filesystem::path p = std::string_view{path};
+ auto anim_info = json_helper::from_json<Serialize::anim>(p);
+ p.replace_extension({});
+ auto tex = tile_texture(path);
+
+ fm_assert(!anim_info.anim_name.isEmpty() && !anim_info.object_name.isEmpty());
+ fm_assert(anim_info.pixel_size.product() > 0);
+ fm_assert(!anim_info.groups.empty());
+ fm_assert(anim_info.nframes > 0);
+ fm_assert(anim_info.nframes == 1 || anim_info.fps > 0);
+
+ auto atlas = std::make_shared<struct anim_atlas>(p.string(), tex, std::move(anim_info));
+ return anim_atlas_map[atlas->name()] = atlas;
+ }
+}
+
+void loader_impl::get_anim_atlas_list()
+{
+ anim_atlases.clear();
+ anim_atlases.reserve(64);
+ using f = Path::ListFlag;
+ constexpr auto flags = f::SkipDirectories | f::SkipDotAndDotDot | f::SkipSpecial | f::SortAscending;
+ if (const auto list = Path::list(FM_ANIM_PATH, flags); list)
+ for (StringView str : *list)
+ if (str.hasSuffix(".json"))
+ anim_atlases.emplace_back(str.exceptSuffix(std::size(".json")-1));
+}
+
void loader_::destroy()
{
loader.~loader_();
@@ -119,7 +175,7 @@ void loader_impl::set_application_working_directory()
if (once)
return;
once = true;
- const auto location = Utility::Path::executableLocation();
+ const auto location = Path::executableLocation();
if (!location)
return;
std::filesystem::path path((std::string)*location);
diff --git a/main/precomp.hpp b/main/precomp.hpp
index 68e8c965..8940421a 100644
--- a/main/precomp.hpp
+++ b/main/precomp.hpp
@@ -10,9 +10,9 @@
#include <Magnum/GL/Framebuffer.h>
#include <Magnum/GL/Renderbuffer.h>
#include <Magnum/GL/RenderbufferFormat.h>
-#include <Magnum/Platform/Sdl2Application.h>
#if __has_include(<SDL.h>)
+#include <Magnum/Platform/Sdl2Application.h>
#include <SDL_keycode.h>
#include <SDL_events.h>
#endif
diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp
index 65b0038c..1aadab21 100644
--- a/src/anim-atlas.cpp
+++ b/src/anim-atlas.cpp
@@ -1,5 +1,6 @@
#include "anim-atlas.hpp"
#include <Corrade/Containers/StringStlView.h>
+#include <Magnum/GL/TextureFormat.h>
namespace floormat {
@@ -28,10 +29,17 @@ decltype(anim_atlas::_group_indices) anim_atlas::make_group_indices(const anim_i
}
anim_atlas::anim_atlas() noexcept = default;
-anim_atlas::anim_atlas(StringView name, GL::Texture2D&& tex, anim_info info) noexcept :
- _tex{std::move(tex)}, _name{name},
+anim_atlas::anim_atlas(StringView name, const ImageView2D& image, anim_info info) noexcept :
+ _name{name},
_info{std::move(info)}, _group_indices{make_group_indices(_info)}
{
+ _tex.setWrapping(GL::SamplerWrapping::ClampToEdge)
+ .setMagnificationFilter(GL::SamplerFilter::Nearest)
+ .setMinificationFilter(GL::SamplerFilter::Linear)
+ .setMaxAnisotropy(1)
+ .setBorderColor(Color4{1, 0, 0, 1})
+ .setStorage(1, GL::textureFormat(image.format()), image.size())
+ .setSubImage(0, {}, image);
}
anim_atlas::~anim_atlas() noexcept = default;
@@ -74,4 +82,6 @@ auto anim_atlas::frame_texcoords(const anim_frame& frame) const noexcept -> texc
}};
}
+
+
} // namespace floormat
diff --git a/src/anim-atlas.hpp b/src/anim-atlas.hpp
index 4e73f9c8..a7553c5c 100644
--- a/src/anim-atlas.hpp
+++ b/src/anim-atlas.hpp
@@ -5,6 +5,7 @@
#include <array>
#include <Corrade/Containers/String.h>
#include <Magnum/Math/Vector2.h>
+#include <Magnum/ImageView.h>
#include <Magnum/GL/Texture.h>
namespace floormat {
@@ -17,7 +18,7 @@ struct anim_atlas final
using texcoords = std::array<Vector2, 4>;
anim_atlas() noexcept;
- anim_atlas(StringView name, GL::Texture2D&& tex, anim_info info) noexcept;
+ anim_atlas(StringView name, const ImageView2D& tex, anim_info info) noexcept;
~anim_atlas() noexcept;
anim_atlas(anim_atlas&&) noexcept;
diff --git a/src/loader.hpp b/src/loader.hpp
index 9dae4b11..0aaaa42e 100644
--- a/src/loader.hpp
+++ b/src/loader.hpp
@@ -1,20 +1,25 @@
#pragma once
#include <memory>
+#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/StringView.h>
#include <Magnum/Trade/ImageData.h>
-#define IMAGE_PATH "share/floormat/images/"
+#define FM_IMAGE_PATH "share/floormat/images/"
+#define FM_ANIM_PATH "share/floormat/anim/"
namespace floormat {
struct tile_atlas;
+struct anim_atlas;
struct loader_
{
- virtual StringView shader(Containers::StringView filename) = 0;
- virtual Trade::ImageData2D tile_texture(Containers::StringView filename) = 0;
- virtual std::shared_ptr<struct tile_atlas> tile_atlas(Containers::StringView filename, Vector2ub size) = 0;
+ virtual StringView shader(StringView filename) = 0;
+ virtual Trade::ImageData2D tile_texture(StringView filename) = 0;
+ virtual std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size) = 0;
+ virtual ArrayView<String> anim_atlas_list() = 0;
+ virtual std::shared_ptr<struct anim_atlas> anim_atlas(StringView name) = 0;
static void destroy();
loader_(const loader_&) = delete;
diff --git a/src/scenery.hpp b/src/scenery.hpp
index 731b999b..1b0dc673 100644
--- a/src/scenery.hpp
+++ b/src/scenery.hpp
@@ -13,10 +13,17 @@ struct scenery final
{
using frame_t = std::uint16_t;
- frame_t frame : 13 = 0;
- rotation r : 3 = rotation::N;
+ frame_t frame : 12 = (1 << 12) - 1;
+ rotation r : 4 = rotation::N;
+
+ constexpr operator bool() const noexcept;
};
static_assert(sizeof(scenery) == sizeof(std::uint16_t));
+constexpr scenery::operator bool() const noexcept
+{
+ return frame == (1 << 13) - 1;
+}
+
} // namespace floormat