spritesheet hashing, navigation fix, etc.
This commit is contained in:
+1
-1
@@ -39,7 +39,7 @@ namespace anm2ed::anm2
|
||||
|
||||
Spritesheet* spritesheet_get(int);
|
||||
bool spritesheet_add(const std::filesystem::path&, const std::filesystem::path&, int&);
|
||||
bool spritesheet_pack(int);
|
||||
bool spritesheet_pack(int, int);
|
||||
bool regions_trim(int, const std::set<int>&);
|
||||
std::vector<std::string> spritesheet_labels_get();
|
||||
std::vector<int> spritesheet_ids_get();
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace anm2ed::anm2
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Anm2::spritesheet_pack(int id)
|
||||
bool Anm2::spritesheet_pack(int id, int padding)
|
||||
{
|
||||
constexpr int PACKING_PADDING = 1;
|
||||
const int packingPadding = std::max(0, padding);
|
||||
|
||||
struct RectI
|
||||
{
|
||||
@@ -256,8 +256,8 @@ namespace anm2ed::anm2
|
||||
auto minPoint = glm::ivec2(glm::min(region.crop, region.crop + region.size));
|
||||
auto maxPoint = glm::ivec2(glm::max(region.crop, region.crop + region.size));
|
||||
auto size = glm::max(maxPoint - minPoint, glm::ivec2(1));
|
||||
int packWidth = size.x + PACKING_PADDING * 2;
|
||||
int packHeight = size.y + PACKING_PADDING * 2;
|
||||
int packWidth = size.x + packingPadding * 2;
|
||||
int packHeight = size.y + packingPadding * 2;
|
||||
items.push_back({regionID, minPoint.x, minPoint.y, size.x, size.y, packWidth, packHeight});
|
||||
}
|
||||
|
||||
@@ -290,8 +290,8 @@ namespace anm2ed::anm2
|
||||
{
|
||||
int sourceX = item.srcX + x;
|
||||
int sourceY = item.srcY + y;
|
||||
int destinationX = destinationRect.x + PACKING_PADDING + x;
|
||||
int destinationY = destinationRect.y + PACKING_PADDING + y;
|
||||
int destinationX = destinationRect.x + packingPadding + x;
|
||||
int destinationY = destinationRect.y + packingPadding + y;
|
||||
|
||||
if (sourceX < 0 || sourceY < 0 || sourceX >= textureSize.x || sourceY >= textureSize.y) continue;
|
||||
if (destinationX < 0 || destinationY < 0 || destinationX >= packedWidth || destinationY >= packedHeight)
|
||||
@@ -312,7 +312,7 @@ namespace anm2ed::anm2
|
||||
if (packedRects.contains(regionID))
|
||||
{
|
||||
auto& rect = packedRects.at(regionID);
|
||||
region.crop = {rect.x + PACKING_PADDING, rect.y + PACKING_PADDING};
|
||||
region.crop = {rect.x + packingPadding, rect.y + packingPadding};
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "spritesheet.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "map_.h"
|
||||
@@ -52,6 +54,7 @@ namespace anm2ed::anm2
|
||||
path = path::lower_case_backslash_handle(path);
|
||||
texture = Texture(path);
|
||||
|
||||
regionOrder.clear();
|
||||
for (auto child = element->FirstChildElement("Region"); child; child = child->NextSiblingElement("Region"))
|
||||
{
|
||||
Region region{};
|
||||
@@ -73,12 +76,16 @@ namespace anm2ed::anm2
|
||||
child->QueryFloatAttribute("YPivot", ®ion.pivot.y);
|
||||
}
|
||||
regions.emplace(id, std::move(region));
|
||||
regionOrder.push_back(id);
|
||||
}
|
||||
|
||||
regionOrder.clear();
|
||||
regionOrder.reserve(regions.size());
|
||||
for (auto id : regions | std::views::keys)
|
||||
regionOrder.push_back(id);
|
||||
if (regionOrder.size() != regions.size())
|
||||
{
|
||||
regionOrder.clear();
|
||||
regionOrder.reserve(regions.size());
|
||||
for (auto id : regions | std::views::keys)
|
||||
regionOrder.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
Spritesheet::Spritesheet(const std::filesystem::path& directory, const std::filesystem::path& path)
|
||||
@@ -231,4 +238,43 @@ namespace anm2ed::anm2
|
||||
}
|
||||
bool Spritesheet::is_valid() { return texture.is_valid(); }
|
||||
|
||||
uint64_t Spritesheet::hash() const
|
||||
{
|
||||
auto hash_combine = [](std::size_t& seed, std::size_t value)
|
||||
{
|
||||
seed ^= value + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);
|
||||
};
|
||||
|
||||
std::size_t seed{};
|
||||
hash_combine(seed, std::hash<int>{}(texture.size.x));
|
||||
hash_combine(seed, std::hash<int>{}(texture.size.y));
|
||||
hash_combine(seed, std::hash<int>{}(texture.channels));
|
||||
hash_combine(seed, std::hash<int>{}(texture.filter));
|
||||
|
||||
if (!texture.pixels.empty())
|
||||
{
|
||||
std::string_view bytes(reinterpret_cast<const char*>(texture.pixels.data()), texture.pixels.size());
|
||||
hash_combine(seed, std::hash<std::string_view>{}(bytes));
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_combine(seed, 0);
|
||||
}
|
||||
|
||||
for (const auto& [id, region] : regions)
|
||||
{
|
||||
hash_combine(seed, std::hash<int>{}(id));
|
||||
hash_combine(seed, std::hash<std::string>{}(region.name));
|
||||
hash_combine(seed, std::hash<float>{}(region.crop.x));
|
||||
hash_combine(seed, std::hash<float>{}(region.crop.y));
|
||||
hash_combine(seed, std::hash<float>{}(region.size.x));
|
||||
hash_combine(seed, std::hash<float>{}(region.size.y));
|
||||
hash_combine(seed, std::hash<float>{}(region.pivot.x));
|
||||
hash_combine(seed, std::hash<float>{}(region.pivot.y));
|
||||
hash_combine(seed, std::hash<int>{}(static_cast<int>(region.origin)));
|
||||
}
|
||||
|
||||
return static_cast<uint64_t>(seed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <tinyxml2/tinyxml2.h>
|
||||
|
||||
#include "texture.h"
|
||||
@@ -48,5 +49,6 @@ namespace anm2ed::anm2
|
||||
void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int, Flags = 0);
|
||||
void reload(const std::filesystem::path&, const std::filesystem::path& = {});
|
||||
bool is_valid();
|
||||
uint64_t hash() const;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user