Mega Region Update.

This commit is contained in:
2026-02-05 21:34:42 -05:00
parent 00bff4a91f
commit 64d6a1d95a
45 changed files with 1590 additions and 205 deletions
+107 -28
View File
@@ -1,11 +1,13 @@
#include "spritesheet.h"
#include <algorithm>
#include <ranges>
#include <vector>
#include "map_.h"
#include "path_.h"
#include "working_directory.h"
#include "xml_.h"
#include "map_.h"
using namespace anm2ed::resource;
using namespace anm2ed::util;
@@ -14,6 +16,31 @@ using namespace tinyxml2;
namespace anm2ed::anm2
{
namespace
{
const char* origin_to_string(Spritesheet::Region::Origin origin)
{
switch (origin)
{
case Spritesheet::Region::TOP_LEFT:
return "TopLeft";
case Spritesheet::Region::ORIGIN_CENTER:
return "Center";
case Spritesheet::Region::CUSTOM:
default:
return nullptr;
}
}
Spritesheet::Region::Origin origin_from_string(const char* originString)
{
if (!originString) return Spritesheet::Region::CUSTOM;
if (std::string(originString) == "TopLeft") return Spritesheet::Region::TOP_LEFT;
if (std::string(originString) == "Center") return Spritesheet::Region::ORIGIN_CENTER;
return Spritesheet::Region::CUSTOM;
}
}
Spritesheet::Spritesheet(XMLElement* element, int& id)
{
if (!element) return;
@@ -31,14 +58,27 @@ namespace anm2ed::anm2
int id{};
child->QueryIntAttribute("Id", &id);
xml::query_string_attribute(child, "Name", &region.name);
child->QueryFloatAttribute("CropX", &region.crop.x);
child->QueryFloatAttribute("CropY", &region.crop.y);
child->QueryFloatAttribute("PivotX", &region.pivot.x);
child->QueryFloatAttribute("PivotY", &region.pivot.y);
child->QueryFloatAttribute("XCrop", &region.crop.x);
child->QueryFloatAttribute("YCrop", &region.crop.y);
child->QueryFloatAttribute("Width", &region.size.x);
child->QueryFloatAttribute("Height", &region.size.y);
region.origin = origin_from_string(child->Attribute("Origin"));
if (region.origin == Spritesheet::Region::TOP_LEFT)
region.pivot = {};
else if (region.origin == Spritesheet::Region::ORIGIN_CENTER)
region.pivot = {(int)(region.size.x / 2.0f), (int)(region.size.y / 2.0f)};
else
{
child->QueryFloatAttribute("XPivot", &region.pivot.x);
child->QueryFloatAttribute("YPivot", &region.pivot.y);
}
regions.emplace(id, std::move(region));
}
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)
@@ -49,32 +89,50 @@ namespace anm2ed::anm2
texture = Texture(this->path);
}
XMLElement* Spritesheet::to_element(XMLDocument& document, int id)
XMLElement* Spritesheet::to_element(XMLDocument& document, int id, Flags flags)
{
auto element = document.NewElement("Spritesheet");
element->SetAttribute("Id", id);
auto pathString = path::to_utf8(path);
element->SetAttribute("Path", pathString.c_str());
for (auto [i, region] : regions)
if (!has_flag(flags, NO_REGIONS))
{
auto regionElement = element->InsertNewChildElement("Region");
regionElement->SetAttribute("Id", i);
regionElement->SetAttribute("Name", region.name.c_str());
regionElement->SetAttribute("CropX", region.crop.x);
regionElement->SetAttribute("CropY", region.crop.y);
regionElement->SetAttribute("PivotX", region.pivot.x);
regionElement->SetAttribute("PivotY", region.pivot.y);
regionElement->SetAttribute("Width", region.size.x);
regionElement->SetAttribute("Height", region.size.y);
if (regionOrder.size() != regions.size())
{
regionOrder.clear();
regionOrder.reserve(regions.size());
for (auto id : regions | std::views::keys)
regionOrder.push_back(id);
}
for (auto id : regionOrder)
{
if (!regions.contains(id)) continue;
auto& region = regions.at(id);
auto regionElement = element->InsertNewChildElement("Region");
regionElement->SetAttribute("Id", id);
regionElement->SetAttribute("Name", region.name.c_str());
regionElement->SetAttribute("XCrop", region.crop.x);
regionElement->SetAttribute("YCrop", region.crop.y);
regionElement->SetAttribute("Width", region.size.x);
regionElement->SetAttribute("Height", region.size.y);
if (auto originString = origin_to_string(region.origin); originString)
regionElement->SetAttribute("Origin", originString);
else
{
regionElement->SetAttribute("XPivot", region.pivot.x);
regionElement->SetAttribute("YPivot", region.pivot.y);
}
}
}
return element;
}
void Spritesheet::serialize(XMLDocument& document, XMLElement* parent, int id)
void Spritesheet::serialize(XMLDocument& document, XMLElement* parent, int id, Flags flags)
{
parent->InsertEndChild(to_element(document, id));
parent->InsertEndChild(to_element(document, id, flags));
}
std::string Spritesheet::to_string(int id)
@@ -93,12 +151,17 @@ namespace anm2ed::anm2
auto& region = regions.at(id);
element->SetAttribute("Id", id);
element->SetAttribute("Name", region.name.c_str());
element->SetAttribute("CropX", region.crop.x);
element->SetAttribute("CropY", region.crop.y);
element->SetAttribute("PivotX", region.pivot.x);
element->SetAttribute("PivotY", region.pivot.y);
element->SetAttribute("XCrop", region.crop.x);
element->SetAttribute("YCrop", region.crop.y);
element->SetAttribute("Width", region.size.x);
element->SetAttribute("Height", region.size.y);
if (auto originString = origin_to_string(region.origin); originString)
element->SetAttribute("Origin", originString);
else
{
element->SetAttribute("XPivot", region.pivot.x);
element->SetAttribute("YPivot", region.pivot.y);
}
document.InsertEndChild(element);
return xml::document_to_string(document);
@@ -118,20 +181,30 @@ namespace anm2ed::anm2
return false;
}
for (auto element = document.FirstChildElement("Region"); element; element = element->NextSiblingElement("Region"))
for (auto element = document.FirstChildElement("Region"); element;
element = element->NextSiblingElement("Region"))
{
Region region{};
element->QueryIntAttribute("Id", &id);
xml::query_string_attribute(element, "Name", &region.name);
element->QueryFloatAttribute("CropX", &region.crop.x);
element->QueryFloatAttribute("CropY", &region.crop.y);
element->QueryFloatAttribute("PivotX", &region.pivot.x);
element->QueryFloatAttribute("PivotY", &region.pivot.y);
element->QueryFloatAttribute("XCrop", &region.crop.x);
element->QueryFloatAttribute("YCrop", &region.crop.y);
element->QueryFloatAttribute("Width", &region.size.x);
element->QueryFloatAttribute("Height", &region.size.y);
region.origin = origin_from_string(element->Attribute("Origin"));
if (region.origin == Spritesheet::Region::TOP_LEFT)
region.pivot = {};
else if (region.origin == Spritesheet::Region::ORIGIN_CENTER)
region.pivot = glm::ivec2(region.size / 2.0f);
else
{
element->QueryFloatAttribute("XPivot", &region.pivot.x);
element->QueryFloatAttribute("YPivot", &region.pivot.y);
}
if (type == merge::APPEND) id = map::next_id_get(regions);
regions[id] = std::move(region);
if (std::find(regionOrder.begin(), regionOrder.end(), id) == regionOrder.end()) regionOrder.push_back(id);
}
return true;
@@ -149,7 +222,13 @@ namespace anm2ed::anm2
return texture.write_png(this->path);
}
void Spritesheet::reload(const std::filesystem::path& directory) { *this = Spritesheet(directory, this->path); }
void Spritesheet::reload(const std::filesystem::path& directory, const std::filesystem::path& path)
{
WorkingDirectory workingDirectory(directory);
this->path = !path.empty() ? path::make_relative(path) : this->path;
this->path = path::lower_case_backslash_handle(this->path);
texture = Texture(this->path);
}
bool Spritesheet::is_valid() { return texture.is_valid(); }
}