Friends :)
This commit is contained in:
+35
-10
@@ -91,6 +91,25 @@ namespace anm2ed
|
|||||||
NO_SOUNDS | NO_REGIONS | NO_GROUPS | FRAME_NO_REGION_VALUES | INTERPOLATION_BOOL_ONLY, 0,
|
NO_SOUNDS | NO_REGIONS | NO_GROUPS | FRAME_NO_REGION_VALUES | INTERPOLATION_BOOL_ONLY, 0,
|
||||||
NO_GROUPS | FRAME_NO_REGION_VALUES};
|
NO_GROUPS | FRAME_NO_REGION_VALUES};
|
||||||
|
|
||||||
|
void groups_flatten(Element&);
|
||||||
|
|
||||||
|
bool anm2_document_load(Anm2& anm2, XMLDocument& document, std::string* errorString)
|
||||||
|
{
|
||||||
|
auto rootElement = document.RootElement();
|
||||||
|
if (!rootElement)
|
||||||
|
{
|
||||||
|
if (errorString) *errorString = "No root element.";
|
||||||
|
anm2.isValid = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
anm2.root = element_read(rootElement);
|
||||||
|
groups_flatten(anm2.root);
|
||||||
|
anm2.region_frames_sync(true);
|
||||||
|
anm2.isValid = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Flags flags_for(Compatibility compatibility)
|
Flags flags_for(Compatibility compatibility)
|
||||||
{
|
{
|
||||||
auto index = (std::size_t)compatibility;
|
auto index = (std::size_t)compatibility;
|
||||||
@@ -437,13 +456,18 @@ namespace anm2ed
|
|||||||
return element_to_xml(document, element, ElementType::UNKNOWN, flags);
|
return element_to_xml(document, element, ElementType::UNKNOWN, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string element_to_string(const Element& element, Flags flags)
|
std::string element_to_string(const Element& element, ElementType parentType, Flags flags)
|
||||||
{
|
{
|
||||||
XMLDocument document{};
|
XMLDocument document{};
|
||||||
document.InsertEndChild(element_to_xml(document, element, flags));
|
document.InsertEndChild(element_to_xml(document, element, parentType, flags));
|
||||||
return xml::document_to_string(document);
|
return xml::document_to_string(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string element_to_string(const Element& element, Flags flags)
|
||||||
|
{
|
||||||
|
return element_to_string(element, ElementType::UNKNOWN, flags);
|
||||||
|
}
|
||||||
|
|
||||||
void groups_flatten(Element& element)
|
void groups_flatten(Element& element)
|
||||||
{
|
{
|
||||||
auto container_flatten = [](Element& container, ElementType trackType)
|
auto container_flatten = [](Element& container, ElementType trackType)
|
||||||
@@ -1145,19 +1169,20 @@ namespace anm2ed
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rootElement = document.RootElement();
|
return anm2_document_load(*this, document, errorString);
|
||||||
if (!rootElement)
|
}
|
||||||
|
|
||||||
|
bool Anm2::load_string(std::string_view string, std::string* errorString)
|
||||||
{
|
{
|
||||||
if (errorString) *errorString = "No root element.";
|
XMLDocument document{};
|
||||||
|
if (document.Parse(string.data(), string.size()) != XML_SUCCESS)
|
||||||
|
{
|
||||||
|
if (errorString) *errorString = document.ErrorStr();
|
||||||
isValid = false;
|
isValid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
root = element_read(rootElement);
|
return anm2_document_load(*this, document, errorString);
|
||||||
groups_flatten(root);
|
|
||||||
region_frames_sync(true);
|
|
||||||
isValid = true;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Anm2::save(const std::filesystem::path& path, std::string* errorString, Options options) const
|
bool Anm2::save(const std::filesystem::path& path, std::string* errorString, Options options) const
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
@@ -289,7 +290,9 @@ namespace anm2ed
|
|||||||
Element element_make(ElementType);
|
Element element_make(ElementType);
|
||||||
Element element_read(const tinyxml2::XMLElement*);
|
Element element_read(const tinyxml2::XMLElement*);
|
||||||
std::string element_to_string(const Element&, Flags = 0);
|
std::string element_to_string(const Element&, Flags = 0);
|
||||||
|
std::string element_to_string(const Element&, ElementType, Flags = 0);
|
||||||
tinyxml2::XMLElement* element_to_xml(tinyxml2::XMLDocument&, const Element&, Flags = 0);
|
tinyxml2::XMLElement* element_to_xml(tinyxml2::XMLDocument&, const Element&, Flags = 0);
|
||||||
|
tinyxml2::XMLElement* element_to_xml(tinyxml2::XMLDocument&, const Element&, ElementType, Flags = 0);
|
||||||
Element* element_child_first_get(Element&, ElementType);
|
Element* element_child_first_get(Element&, ElementType);
|
||||||
const Element* element_child_first_get(const Element&, ElementType);
|
const Element* element_child_first_get(const Element&, ElementType);
|
||||||
Element* element_child_id_get(Element&, ElementType, int);
|
Element* element_child_id_get(Element&, ElementType, int);
|
||||||
@@ -301,6 +304,7 @@ namespace anm2ed
|
|||||||
const Element* element_first_get(const Element&, ElementType);
|
const Element* element_first_get(const Element&, ElementType);
|
||||||
Element* animation_item_get(Element&, ItemType, int = -1);
|
Element* animation_item_get(Element&, ItemType, int = -1);
|
||||||
const Element* animation_item_get(const Element&, ItemType, int = -1);
|
const Element* animation_item_get(const Element&, ItemType, int = -1);
|
||||||
|
ElementType item_type_to_track_type_get(ItemType);
|
||||||
Element* track_frame_get(Element&, int);
|
Element* track_frame_get(Element&, int);
|
||||||
const Element* track_frame_get(const Element&, int);
|
const Element* track_frame_get(const Element&, int);
|
||||||
Element frame_generate(const Element&, float);
|
Element frame_generate(const Element&, float);
|
||||||
@@ -325,6 +329,7 @@ namespace anm2ed
|
|||||||
Anm2(const std::filesystem::path&, std::string* = nullptr);
|
Anm2(const std::filesystem::path&, std::string* = nullptr);
|
||||||
|
|
||||||
bool load(const std::filesystem::path&, std::string* = nullptr);
|
bool load(const std::filesystem::path&, std::string* = nullptr);
|
||||||
|
bool load_string(std::string_view, std::string* = nullptr);
|
||||||
bool save(const std::filesystem::path&, std::string* = nullptr, Options = {}) const;
|
bool save(const std::filesystem::path&, std::string* = nullptr, Options = {}) const;
|
||||||
std::string to_string(Options = {}) const;
|
std::string to_string(Options = {}) const;
|
||||||
tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, Options = {}) const;
|
tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, Options = {}) const;
|
||||||
|
|||||||
+32
-6
@@ -385,6 +385,28 @@ namespace anm2ed
|
|||||||
change(SPRITESHEETS);
|
change(SPRITESHEETS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Document::texture_reload(int id)
|
||||||
|
{
|
||||||
|
auto spritesheet = anm2.element_get(ElementType::SPRITESHEET, id);
|
||||||
|
if (!spritesheet) return false;
|
||||||
|
|
||||||
|
util::WorkingDirectory workingDirectory(directory_get());
|
||||||
|
textures[id] = resource::Texture(spritesheet->path);
|
||||||
|
texturePaths[id] = spritesheet->path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Document::sound_reload(int id)
|
||||||
|
{
|
||||||
|
auto sound = anm2.element_get(ElementType::SOUND_ELEMENT, id);
|
||||||
|
if (!sound) return false;
|
||||||
|
|
||||||
|
util::WorkingDirectory workingDirectory(directory_get());
|
||||||
|
sounds[id] = resource::Audio(sound->path);
|
||||||
|
soundPaths[id] = sound->path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Document::assets_sync(ChangeType type)
|
void Document::assets_sync(ChangeType type)
|
||||||
{
|
{
|
||||||
if (type == ALL || type == SPRITESHEETS || type == TEXTURES)
|
if (type == ALL || type == SPRITESHEETS || type == TEXTURES)
|
||||||
@@ -1493,19 +1515,19 @@ namespace anm2ed
|
|||||||
{
|
{
|
||||||
struct LoadedSpritesheet
|
struct LoadedSpritesheet
|
||||||
{
|
{
|
||||||
std::filesystem::path path{};
|
std::filesystem::path relativePath{};
|
||||||
resource::Texture texture{};
|
resource::Texture texture{};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto items = anm2.element_get(ElementType::SPRITESHEETS);
|
auto items = anm2.element_get(ElementType::SPRITESHEETS);
|
||||||
if (!items) return;
|
if (!items) return;
|
||||||
|
auto directory = directory_get();
|
||||||
|
|
||||||
std::vector<LoadedSpritesheet> loaded{};
|
std::vector<LoadedSpritesheet> loaded{};
|
||||||
for (auto& path : paths)
|
for (auto& path : paths)
|
||||||
{
|
{
|
||||||
auto pathCopy = path;
|
auto pathCopy = path;
|
||||||
WorkingDirectory workingDirectory(directory_get());
|
auto loadPath = path::lower_case_backslash_handle(pathCopy);
|
||||||
auto loadPath = path::lower_case_backslash_handle(path);
|
|
||||||
auto texture = resource::Texture(loadPath);
|
auto texture = resource::Texture(loadPath);
|
||||||
if (!texture.is_valid())
|
if (!texture.is_valid())
|
||||||
{
|
{
|
||||||
@@ -1516,7 +1538,8 @@ namespace anm2ed
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded.push_back({.path = pathCopy, .texture = std::move(texture)});
|
loaded.push_back({.relativePath = path::backslash_replace(path::make_relative(loadPath, directory)),
|
||||||
|
.texture = std::move(texture)});
|
||||||
}
|
}
|
||||||
if (loaded.empty()) return;
|
if (loaded.empty()) return;
|
||||||
|
|
||||||
@@ -1528,7 +1551,7 @@ namespace anm2ed
|
|||||||
auto id = element_child_next_id_get(*items, ElementType::SPRITESHEET);
|
auto id = element_child_next_id_get(*items, ElementType::SPRITESHEET);
|
||||||
auto spritesheet = element_make(ElementType::SPRITESHEET);
|
auto spritesheet = element_make(ElementType::SPRITESHEET);
|
||||||
spritesheet.id = id;
|
spritesheet.id = id;
|
||||||
spritesheet.path = path::lower_case_backslash_handle(path::make_relative(loadedSpritesheet.path));
|
spritesheet.path = loadedSpritesheet.relativePath;
|
||||||
auto pathString = path::to_utf8(spritesheet.path);
|
auto pathString = path::to_utf8(spritesheet.path);
|
||||||
items->children.push_back(spritesheet);
|
items->children.push_back(spritesheet);
|
||||||
textures[id] = std::move(loadedSpritesheet.texture);
|
textures[id] = std::move(loadedSpritesheet.texture);
|
||||||
@@ -1553,6 +1576,7 @@ namespace anm2ed
|
|||||||
{
|
{
|
||||||
auto items = anm2.element_get(ElementType::SOUNDS);
|
auto items = anm2.element_get(ElementType::SOUNDS);
|
||||||
if (!items) return;
|
if (!items) return;
|
||||||
|
auto directory = directory_get();
|
||||||
|
|
||||||
std::vector<std::filesystem::path> validPaths{};
|
std::vector<std::filesystem::path> validPaths{};
|
||||||
for (auto& path : paths)
|
for (auto& path : paths)
|
||||||
@@ -1567,9 +1591,11 @@ namespace anm2ed
|
|||||||
auto id = element_child_next_id_get(*items, ElementType::SOUND_ELEMENT);
|
auto id = element_child_next_id_get(*items, ElementType::SOUND_ELEMENT);
|
||||||
auto soundElement = element_make(ElementType::SOUND_ELEMENT);
|
auto soundElement = element_make(ElementType::SOUND_ELEMENT);
|
||||||
soundElement.id = id;
|
soundElement.id = id;
|
||||||
|
auto loadPath = path::lower_case_backslash_handle(path);
|
||||||
|
auto relativePath = path::backslash_replace(path::make_relative(loadPath, directory));
|
||||||
{
|
{
|
||||||
WorkingDirectory workingDirectory(directory_get());
|
WorkingDirectory workingDirectory(directory_get());
|
||||||
soundElement.path = path::lower_case_backslash_handle(path::make_relative(path));
|
soundElement.path = relativePath;
|
||||||
sounds[id] = resource::Audio(soundElement.path);
|
sounds[id] = resource::Audio(soundElement.path);
|
||||||
soundPaths[id] = soundElement.path;
|
soundPaths[id] = soundElement.path;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ namespace anm2ed
|
|||||||
void anm2_change(ChangeType);
|
void anm2_change(ChangeType);
|
||||||
void assets_sync(ChangeType = ALL);
|
void assets_sync(ChangeType = ALL);
|
||||||
void texture_change(int);
|
void texture_change(int);
|
||||||
|
bool texture_reload(int);
|
||||||
|
bool sound_reload(int);
|
||||||
resource::Texture* texture_get(int);
|
resource::Texture* texture_get(int);
|
||||||
const resource::Texture* texture_get(int) const;
|
const resource::Texture* texture_get(int) const;
|
||||||
resource::Audio* sound_get(int);
|
resource::Audio* sound_get(int);
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ namespace anm2ed::imgui::popup
|
|||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemProperties::update(Manager& manager, Settings& settings, Document& document, Reference& reference,
|
bool ItemProperties::update(Manager& manager, Settings& settings, Document& document, Reference& reference)
|
||||||
const std::function<void(int, int)>& referenceSetItem)
|
|
||||||
{
|
{
|
||||||
|
bool isAdded{};
|
||||||
auto& anm2 = document.anm2;
|
auto& anm2 = document.anm2;
|
||||||
auto animation = anm2.element_get(ElementType::ANIMATION, reference.animationIndex);
|
auto animation = anm2.element_get(ElementType::ANIMATION, reference.animationIndex);
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ namespace anm2ed::imgui::popup
|
|||||||
|
|
||||||
if (ImGui::BeginChild("##Content", ImVec2(0, contentHeight), ImGuiChildFlags_Borders))
|
if (ImGui::BeginChild("##Content", ImVec2(0, contentHeight), ImGuiChildFlags_Borders))
|
||||||
{
|
{
|
||||||
auto spaced_pair = [](const std::function<void()>& left, const std::function<void()>& right)
|
auto spaced_pair = [](auto left, auto right)
|
||||||
{
|
{
|
||||||
auto startX = ImGui::GetCursorPosX();
|
auto startX = ImGui::GetCursorPosX();
|
||||||
auto secondX = startX + ImGui::GetContentRegionAvail().x * 0.5f;
|
auto secondX = startX + ImGui::GetContentRegionAvail().x * 0.5f;
|
||||||
@@ -194,7 +194,6 @@ namespace anm2ed::imgui::popup
|
|||||||
auto queuedAddItemName = addItemName;
|
auto queuedAddItemName = addItemName;
|
||||||
auto queuedAddItemSpritesheetID = addItemSpritesheetID;
|
auto queuedAddItemSpritesheetID = addItemSpritesheetID;
|
||||||
auto queuedAddItemIsShowRect = addItemIsShowRect;
|
auto queuedAddItemIsShowRect = addItemIsShowRect;
|
||||||
auto queuedReferenceSetItem = referenceSetItem;
|
|
||||||
|
|
||||||
manager.command_push({manager.selected,
|
manager.command_push({manager.selected,
|
||||||
[=](Manager&, Document& document)
|
[=](Manager&, Document& document)
|
||||||
@@ -213,9 +212,19 @@ namespace anm2ed::imgui::popup
|
|||||||
|
|
||||||
document.anm2_change(Document::ITEMS);
|
document.anm2_change(Document::ITEMS);
|
||||||
|
|
||||||
if (addId != -1) queuedReferenceSetItem((int)queuedType, addId);
|
if (addId != -1)
|
||||||
|
{
|
||||||
|
document.reference = {queuedAnimationIndex, (int)queuedType, addId};
|
||||||
|
document.items.references = {document.reference};
|
||||||
|
document.frames.selection.clear();
|
||||||
|
document.frames.references.clear();
|
||||||
|
if (queuedType == LAYER)
|
||||||
|
if (auto layer = document.anm2.element_get(ElementType::LAYER_ELEMENT, addId))
|
||||||
|
document.spritesheet.reference = layer->spritesheetId;
|
||||||
|
}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
isAdded = true;
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
@@ -229,5 +238,7 @@ namespace anm2ed::imgui::popup
|
|||||||
|
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isAdded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -24,6 +23,6 @@ namespace anm2ed::imgui::popup
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void open();
|
void open();
|
||||||
void update(Manager&, Settings&, Document&, Reference&, const std::function<void(int, int)>&);
|
bool update(Manager&, Settings&, Document&, Reference&);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1041,16 +1041,37 @@ namespace anm2ed::imgui
|
|||||||
auto isZoomOut = isFocused && shortcut(manager.chords[SHORTCUT_ZOOM_OUT], shortcut::GLOBAL);
|
auto isZoomOut = isFocused && shortcut(manager.chords[SHORTCUT_ZOOM_OUT], shortcut::GLOBAL);
|
||||||
|
|
||||||
auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift);
|
auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift);
|
||||||
|
auto useTool = tool;
|
||||||
|
auto step = (float)(isMod ? STEP_FAST : STEP);
|
||||||
|
mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos));
|
||||||
|
auto selected_frame_references_get = [&]()
|
||||||
|
{
|
||||||
|
std::set<Reference> result = document.frames.references;
|
||||||
|
if (result.empty())
|
||||||
|
for (auto frameIndex : frames)
|
||||||
|
result.insert({reference.animationIndex, reference.itemType, reference.itemID, frameIndex});
|
||||||
|
if (result.empty() && reference.itemType != NONE && reference.frameIndex != -1) result.insert(reference);
|
||||||
|
std::erase_if(result,
|
||||||
|
[](const Reference& frameReference)
|
||||||
|
{ return frameReference.itemType == NONE || frameReference.itemType == TRIGGER; });
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
auto selectedFrameReferences = selected_frame_references_get();
|
||||||
|
auto editReference = reference;
|
||||||
|
auto editItemType = referenceItemType;
|
||||||
|
if ((referenceItemType == ItemType::TRIGGER || !selectedFrameReferences.contains(reference)) &&
|
||||||
|
!selectedFrameReferences.empty())
|
||||||
|
{
|
||||||
|
editReference = *selectedFrameReferences.begin();
|
||||||
|
editItemType = static_cast<ItemType>(editReference.itemType);
|
||||||
|
}
|
||||||
|
|
||||||
auto frame =
|
auto frame =
|
||||||
anm2.element_get(reference.animationIndex, referenceItemType, reference.frameIndex, reference.itemID);
|
anm2.element_get(editReference.animationIndex, editItemType, editReference.frameIndex, editReference.itemID);
|
||||||
auto item = anm2.element_get(reference.animationIndex, referenceItemType, reference.itemID);
|
auto item = anm2.element_get(editReference.animationIndex, editItemType, editReference.itemID);
|
||||||
auto useTool = tool;
|
|
||||||
auto step = isMod ? STEP_FAST : STEP;
|
|
||||||
mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos));
|
|
||||||
auto nulls = anm2.element_get(ElementType::NULLS);
|
auto nulls = anm2.element_get(ElementType::NULLS);
|
||||||
auto selectedNull = referenceItemType == ItemType::NULL_ && nulls
|
auto selectedNull = editItemType == ItemType::NULL_ && nulls
|
||||||
? element_child_id_get(*nulls, ElementType::NULL_ELEMENT, reference.itemID)
|
? element_child_id_get(*nulls, ElementType::NULL_ELEMENT, editReference.itemID)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
bool isSelectedNullRect = selectedNull && selectedNull->isShowRect;
|
bool isSelectedNullRect = selectedNull && selectedNull->isShowRect;
|
||||||
auto null_rect_top_left = [](const Element& frame) { return frame.position - (frame.scale * 0.5f); };
|
auto null_rect_top_left = [](const Element& frame) { return frame.position - (frame.scale * 0.5f); };
|
||||||
@@ -1081,19 +1102,37 @@ namespace anm2ed::imgui
|
|||||||
};
|
};
|
||||||
auto frame_change_apply = [&](FrameChange frameChange, ChangeType changeType = ChangeType::ADJUST)
|
auto frame_change_apply = [&](FrameChange frameChange, ChangeType changeType = ChangeType::ADJUST)
|
||||||
{
|
{
|
||||||
auto queuedReference = reference;
|
auto queuedFrameReferences = selectedFrameReferences;
|
||||||
auto queuedReferenceItemType = referenceItemType;
|
|
||||||
auto queuedFrames = frames;
|
|
||||||
manager.command_push({manager.selected,
|
manager.command_push({manager.selected,
|
||||||
[=](Manager&, Document& document)
|
[=](Manager&, Document& document)
|
||||||
{
|
{
|
||||||
auto item = document.anm2.element_get(queuedReference.animationIndex,
|
std::map<Reference, std::set<int>> groupedFrames{};
|
||||||
queuedReferenceItemType,
|
for (auto frameReference : queuedFrameReferences)
|
||||||
queuedReference.itemID);
|
groupedFrames[{frameReference.animationIndex, frameReference.itemType,
|
||||||
if (!item) return;
|
frameReference.itemID, -1}]
|
||||||
frames_change(*item, frameChange, queuedReferenceItemType, changeType, queuedFrames);
|
.insert(frameReference.frameIndex);
|
||||||
|
|
||||||
|
for (auto& [itemReference, itemFrames] : groupedFrames)
|
||||||
|
{
|
||||||
|
auto itemType = static_cast<ItemType>(itemReference.itemType);
|
||||||
|
auto item = document.anm2.element_get(itemReference.animationIndex, itemType,
|
||||||
|
itemReference.itemID);
|
||||||
|
if (!item) continue;
|
||||||
|
frames_change(*item, frameChange, itemType, changeType, itemFrames);
|
||||||
|
}
|
||||||
}});
|
}});
|
||||||
};
|
};
|
||||||
|
auto frame_position_apply = [&](vec2 position)
|
||||||
|
{
|
||||||
|
if (!frame) return;
|
||||||
|
frame_change_apply({.positionX = position.x - frame->position.x, .positionY = position.y - frame->position.y},
|
||||||
|
ChangeType::ADD);
|
||||||
|
};
|
||||||
|
auto frame_scale_apply = [&](vec2 scale)
|
||||||
|
{
|
||||||
|
if (!frame) return;
|
||||||
|
frame_change_apply({.scaleX = scale.x - frame->scale.x, .scaleY = scale.y - frame->scale.y}, ChangeType::ADD);
|
||||||
|
};
|
||||||
auto frames_changed = [&]()
|
auto frames_changed = [&]()
|
||||||
{
|
{
|
||||||
manager.command_push(
|
manager.command_push(
|
||||||
@@ -1103,10 +1142,11 @@ namespace anm2ed::imgui
|
|||||||
{
|
{
|
||||||
topLeft = vec2(ivec2(topLeft));
|
topLeft = vec2(ivec2(topLeft));
|
||||||
rectSize = vec2(ivec2(rectSize));
|
rectSize = vec2(ivec2(rectSize));
|
||||||
frame_change_apply({.positionX = topLeft.x + rectSize.x * 0.5f,
|
frame_change_apply({.positionX = topLeft.x + rectSize.x * 0.5f - frame->position.x,
|
||||||
.positionY = topLeft.y + rectSize.y * 0.5f,
|
.positionY = topLeft.y + rectSize.y * 0.5f - frame->position.y,
|
||||||
.scaleX = rectSize.x,
|
.scaleX = rectSize.x - frame->scale.x,
|
||||||
.scaleY = rectSize.y});
|
.scaleY = rectSize.y - frame->scale.y},
|
||||||
|
ChangeType::ADD);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto& toolInfo = tool::INFO[useTool];
|
auto& toolInfo = tool::INFO[useTool];
|
||||||
@@ -1125,7 +1165,7 @@ namespace anm2ed::imgui
|
|||||||
if (isMouseDown || isMouseMiddleDown) pan += vec2(mouseDelta.x, mouseDelta.y);
|
if (isMouseDown || isMouseMiddleDown) pan += vec2(mouseDelta.x, mouseDelta.y);
|
||||||
break;
|
break;
|
||||||
case tool::MOVE:
|
case tool::MOVE:
|
||||||
if (!item || !frame || frames.empty()) break;
|
if (!item || !frame || selectedFrameReferences.empty()) break;
|
||||||
if (isToolBegin)
|
if (isToolBegin)
|
||||||
{
|
{
|
||||||
frame_snapshot(EDIT_FRAME_POSITION);
|
frame_snapshot(EDIT_FRAME_POSITION);
|
||||||
@@ -1140,10 +1180,10 @@ namespace anm2ed::imgui
|
|||||||
{
|
{
|
||||||
auto position = mousePos - moveOffset;
|
auto position = mousePos - moveOffset;
|
||||||
if (isSelectedNullRect)
|
if (isSelectedNullRect)
|
||||||
frame_change_apply({.positionX = (int)(position.x + frame->scale.x * 0.5f),
|
frame_position_apply(vec2((float)(int)(position.x + frame->scale.x * 0.5f),
|
||||||
.positionY = (int)(position.y + frame->scale.y * 0.5f)});
|
(float)(int)(position.y + frame->scale.y * 0.5f)));
|
||||||
else
|
else
|
||||||
frame_change_apply({.positionX = (int)position.x, .positionY = (int)position.y});
|
frame_position_apply(vec2((float)(int)position.x, (float)(int)position.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLeftPressed) frame_change_apply({.positionX = step}, ChangeType::SUBTRACT);
|
if (isLeftPressed) frame_change_apply({.positionX = step}, ChangeType::SUBTRACT);
|
||||||
@@ -1165,7 +1205,7 @@ namespace anm2ed::imgui
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tool::SCALE:
|
case tool::SCALE:
|
||||||
if (!item || !frame || frames.empty()) break;
|
if (!item || !frame || selectedFrameReferences.empty()) break;
|
||||||
if (isToolBegin)
|
if (isToolBegin)
|
||||||
{
|
{
|
||||||
frame_snapshot(EDIT_FRAME_SCALE);
|
frame_snapshot(EDIT_FRAME_SCALE);
|
||||||
@@ -1192,7 +1232,7 @@ namespace anm2ed::imgui
|
|||||||
{
|
{
|
||||||
auto scale = frame->scale + vec2(mouseDelta.x, mouseDelta.y);
|
auto scale = frame->scale + vec2(mouseDelta.x, mouseDelta.y);
|
||||||
if (isMod) scale = {scale.x, scale.x};
|
if (isMod) scale = {scale.x, scale.x};
|
||||||
frame_change_apply({.scaleX = scale.x, .scaleY = scale.y});
|
frame_scale_apply(scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,9 +1277,9 @@ namespace anm2ed::imgui
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tool::ROTATE:
|
case tool::ROTATE:
|
||||||
if (!item || !frame || frames.empty()) break;
|
if (!item || !frame || selectedFrameReferences.empty()) break;
|
||||||
if (isToolBegin) frame_snapshot(EDIT_FRAME_ROTATION);
|
if (isToolBegin) frame_snapshot(EDIT_FRAME_ROTATION);
|
||||||
if (isToolMouseDown) frame_change_apply({.rotation = (int)mouseDelta.x}, ChangeType::ADD);
|
if (isToolMouseDown) frame_change_apply({.rotation = (float)(int)mouseDelta.x}, ChangeType::ADD);
|
||||||
if (isLeftPressed || isDownPressed) frame_change_apply({.rotation = step}, ChangeType::SUBTRACT);
|
if (isLeftPressed || isDownPressed) frame_change_apply({.rotation = step}, ChangeType::SUBTRACT);
|
||||||
if (isUpPressed || isRightPressed) frame_change_apply({.rotation = step}, ChangeType::ADD);
|
if (isUpPressed || isRightPressed) frame_change_apply({.rotation = step}, ChangeType::ADD);
|
||||||
|
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ namespace anm2ed::imgui
|
|||||||
bool isReferenceLayerOnSpritesheet =
|
bool isReferenceLayerOnSpritesheet =
|
||||||
frame && reference.itemID > -1 && layer && layer->spritesheetId == referenceSpritesheet;
|
frame && reference.itemID > -1 && layer && layer->spritesheetId == referenceSpritesheet;
|
||||||
auto useTool = tool;
|
auto useTool = tool;
|
||||||
auto step = isMod ? STEP_FAST : STEP;
|
auto step = (float)(isMod ? STEP_FAST : STEP);
|
||||||
auto stepX = isGridSnap ? step * gridSize.x : step;
|
auto stepX = isGridSnap ? step * gridSize.x : step;
|
||||||
auto stepY = isGridSnap ? step * gridSize.y : step;
|
auto stepY = isGridSnap ? step * gridSize.y : step;
|
||||||
previousMousePos = mousePos;
|
previousMousePos = mousePos;
|
||||||
@@ -692,10 +692,10 @@ namespace anm2ed::imgui
|
|||||||
if (isMouseDown)
|
if (isMouseDown)
|
||||||
{
|
{
|
||||||
auto frameCrop = ivec2(frame->crop);
|
auto frameCrop = ivec2(frame->crop);
|
||||||
frame_change_apply({.pivotX = (int)(mousePos.x - frameCrop.x),
|
frame_change_apply({.pivotX = (float)(int)(mousePos.x - frameCrop.x),
|
||||||
.pivotY = (int)(mousePos.y - frameCrop.y),
|
.pivotY = (float)(int)(mousePos.y - frameCrop.y),
|
||||||
.cropX = frameCrop.x,
|
.cropX = (float)frameCrop.x,
|
||||||
.cropY = frameCrop.y});
|
.cropY = (float)frameCrop.y});
|
||||||
}
|
}
|
||||||
if (isLeftPressed) frame_change_apply({.pivotX = step}, ChangeType::SUBTRACT);
|
if (isLeftPressed) frame_change_apply({.pivotX = step}, ChangeType::SUBTRACT);
|
||||||
if (isRightPressed) frame_change_apply({.pivotX = step}, ChangeType::ADD);
|
if (isRightPressed) frame_change_apply({.pivotX = step}, ChangeType::ADD);
|
||||||
@@ -703,7 +703,8 @@ namespace anm2ed::imgui
|
|||||||
if (isDownPressed) frame_change_apply({.pivotY = step}, ChangeType::ADD);
|
if (isDownPressed) frame_change_apply({.pivotY = step}, ChangeType::ADD);
|
||||||
|
|
||||||
frame_change_from_current_apply(
|
frame_change_from_current_apply(
|
||||||
[](const Element& frame) { return FrameChange{.pivotX = (int)frame.pivot.x, .pivotY = (int)frame.pivot.y}; });
|
[](const Element& frame)
|
||||||
|
{ return FrameChange{.pivotX = (float)(int)frame.pivot.x, .pivotY = (float)(int)frame.pivot.y}; });
|
||||||
|
|
||||||
if (isDuring)
|
if (isDuring)
|
||||||
{
|
{
|
||||||
@@ -770,7 +771,8 @@ namespace anm2ed::imgui
|
|||||||
if (isMouseClicked)
|
if (isMouseClicked)
|
||||||
{
|
{
|
||||||
cropAnchor = mousePos;
|
cropAnchor = mousePos;
|
||||||
frame_change_apply({.cropX = (int)cropAnchor.x, .cropY = (int)cropAnchor.y, .sizeX = {}, .sizeY = {}});
|
frame_change_apply(
|
||||||
|
{.cropX = (float)(int)cropAnchor.x, .cropY = (float)(int)cropAnchor.y, .sizeX = {}, .sizeY = {}});
|
||||||
}
|
}
|
||||||
if (isMouseDown)
|
if (isMouseDown)
|
||||||
{
|
{
|
||||||
|
|||||||
+120
-70
@@ -973,15 +973,14 @@ namespace anm2ed::imgui
|
|||||||
auto row_drag_references_get = [&](const TimelineItemRow& row)
|
auto row_drag_references_get = [&](const TimelineItemRow& row)
|
||||||
{
|
{
|
||||||
auto clicked = row_reference_get(row);
|
auto clicked = row_reference_get(row);
|
||||||
|
if (clicked.type != LAYER && clicked.type != NULL_) return std::vector<TimelineRowReference>{clicked};
|
||||||
|
|
||||||
auto rows = selected_row_references_get();
|
auto rows = selected_row_references_get();
|
||||||
if (!is_row_reference_selected(clicked)) rows = {clicked};
|
if (!is_row_reference_selected(clicked)) rows = {clicked};
|
||||||
if (rows.empty()) rows = {clicked};
|
if (rows.empty()) rows = {clicked};
|
||||||
|
|
||||||
auto type = rows.front().type;
|
std::erase_if(rows, [&](const TimelineRowReference& rowReference) { return rowReference.type != clicked.type; });
|
||||||
if (type != LAYER && type != NULL_) return std::vector<TimelineRowReference>{clicked};
|
if (rows.empty()) rows = {clicked};
|
||||||
for (auto rowReference : rows)
|
|
||||||
if (rowReference.type != type || (rowReference.type != LAYER && rowReference.type != NULL_))
|
|
||||||
return std::vector<TimelineRowReference>{clicked};
|
|
||||||
return rows;
|
return rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1289,7 +1288,8 @@ namespace anm2ed::imgui
|
|||||||
auto item = item_get(frameReference.itemType, frameReference.itemID);
|
auto item = item_get(frameReference.itemType, frameReference.itemID);
|
||||||
auto frame = item ? track_frame_get(*item, frameReference.frameIndex) : nullptr;
|
auto frame = item ? track_frame_get(*item, frameReference.frameIndex) : nullptr;
|
||||||
if (!frame) continue;
|
if (!frame) continue;
|
||||||
clipboardString += element_to_string(*frame);
|
auto parentType = item_type_to_track_type_get(item_type_get(frameReference.itemType));
|
||||||
|
clipboardString += element_to_string(*frame, parentType);
|
||||||
}
|
}
|
||||||
if (!clipboardString.empty()) clipboard.set(clipboardString);
|
if (!clipboardString.empty()) clipboard.set(clipboardString);
|
||||||
};
|
};
|
||||||
@@ -2334,6 +2334,38 @@ namespace anm2ed::imgui
|
|||||||
return leftMin.x <= rightMax.x && leftMax.x >= rightMin.x && leftMin.y <= rightMax.y &&
|
return leftMin.x <= rightMax.x && leftMax.x >= rightMin.x && leftMin.y <= rightMax.y &&
|
||||||
leftMax.y >= rightMin.y;
|
leftMax.y >= rightMin.y;
|
||||||
};
|
};
|
||||||
|
auto frame_overlay_draw = [&](ImDrawList* drawList, ImVec2 clipMin, ImVec2 clipMax)
|
||||||
|
{
|
||||||
|
if (isFrameBoxSelecting && isFrameBoxClipSet)
|
||||||
|
{
|
||||||
|
auto boxContentMin =
|
||||||
|
ImVec2(std::min(frameBoxStart.x, frameBoxEnd.x), std::min(frameBoxStart.y, frameBoxEnd.y));
|
||||||
|
auto boxContentMax =
|
||||||
|
ImVec2(std::max(frameBoxStart.x, frameBoxEnd.x), std::max(frameBoxStart.y, frameBoxEnd.y));
|
||||||
|
auto boxMin = frame_box_screen_point_get(boxContentMin);
|
||||||
|
auto boxMax = frame_box_screen_point_get(boxContentMax);
|
||||||
|
auto boxClipMin = clipMin;
|
||||||
|
if (isPlayheadLineSet) boxClipMin.y = std::max(boxClipMin.y, playheadLineTopY);
|
||||||
|
drawList->PushClipRect(boxClipMin, clipMax, true);
|
||||||
|
drawList->AddRectFilled(boxMin, boxMax, ImGui::GetColorU32(ImGuiCol_DragDropTargetBg));
|
||||||
|
drawList->AddRect(boxMin, boxMax, ImGui::GetColorU32(ImGuiCol_DragDropTarget));
|
||||||
|
drawList->PopClipRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPlayheadLineSet)
|
||||||
|
{
|
||||||
|
auto lineTopY = std::max(clipMin.y, playheadLineTopY);
|
||||||
|
if (clipMax.y > lineTopY)
|
||||||
|
{
|
||||||
|
auto linePos = ImVec2(playheadLineCenterX - (PLAYHEAD_LINE_THICKNESS * 0.5f), lineTopY);
|
||||||
|
auto lineSize = ImVec2(PLAYHEAD_LINE_THICKNESS * 0.5f, clipMax.y - lineTopY);
|
||||||
|
drawList->PushClipRect(clipMin, clipMax, true);
|
||||||
|
drawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y),
|
||||||
|
ImGui::GetColorU32(playheadLineColor));
|
||||||
|
drawList->PopClipRect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto frame_child = [&](const TimelineItemRow& row, int& index, float width)
|
auto frame_child = [&](const TimelineItemRow& row, int& index, float width)
|
||||||
{
|
{
|
||||||
@@ -2382,7 +2414,40 @@ namespace anm2ed::imgui
|
|||||||
bool isDefaultChild = type == NONE;
|
bool isDefaultChild = type == NONE;
|
||||||
if (isLightTheme && isDefaultChild) ImGui::PushStyleColor(ImGuiCol_ChildBg, TIMELINE_CHILD_BG_COLOR_LIGHT);
|
if (isLightTheme && isDefaultChild) ImGui::PushStyleColor(ImGuiCol_ChildBg, TIMELINE_CHILD_BG_COLOR_LIGHT);
|
||||||
|
|
||||||
if (ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders))
|
bool isFramesChildVisible = ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders);
|
||||||
|
auto drawList = ImGui::GetWindowDrawList();
|
||||||
|
auto clipMax = drawList->GetClipRectMax();
|
||||||
|
auto length = animation ? animation->frameNum : 0;
|
||||||
|
auto frameSize = ImVec2(ImGui::GetTextLineHeight(), ImGui::GetContentRegionAvail().y);
|
||||||
|
auto framesSize = ImVec2(frameSize.x * length, frameSize.y);
|
||||||
|
auto cursorPos = ImGui::GetCursorPos();
|
||||||
|
auto cursorScreenPos = ImGui::GetCursorScreenPos();
|
||||||
|
auto border = glm::max(0.5f, ImGui::GetStyle().FrameBorderSize * 0.5f);
|
||||||
|
auto borderLineLength = frameSize.y / 5;
|
||||||
|
auto frameMin = std::max(0, (int)std::floor(scroll.x / frameSize.x) - 1);
|
||||||
|
auto frameMax = std::min(FRAME_NUM_MAX, (int)std::ceil((scroll.x + clipMax.x) / frameSize.x) + 1);
|
||||||
|
|
||||||
|
if (isFrameBoxSelecting && isFrameBoxClipSet && type != NONE && animation && item)
|
||||||
|
{
|
||||||
|
auto boxMin = ImVec2(std::min(frameBoxStart.x, frameBoxEnd.x), std::min(frameBoxStart.y, frameBoxEnd.y));
|
||||||
|
auto boxMax = ImVec2(std::max(frameBoxStart.x, frameBoxEnd.x), std::max(frameBoxStart.y, frameBoxEnd.y));
|
||||||
|
auto rowMinY = cursorScreenPos.y + scroll.y - frameBoxClipMin.y;
|
||||||
|
auto rowMaxY = rowMinY + childSize.y;
|
||||||
|
float selectionFrameTime{};
|
||||||
|
for (auto [i, frame] : std::views::enumerate(item->children))
|
||||||
|
{
|
||||||
|
auto frameReference = Reference{reference.animationIndex, type, id, (int)i};
|
||||||
|
auto frameStart = type == TRIGGER ? frame.atFrame : selectionFrameTime;
|
||||||
|
auto frameEnd = type == TRIGGER ? frameStart + 1.0f : frameStart + frame.duration;
|
||||||
|
auto frameContentMin = ImVec2(frameStart * frameSize.x, rowMinY);
|
||||||
|
auto frameContentMax = ImVec2(frameEnd * frameSize.x, rowMaxY);
|
||||||
|
if (is_frame_box_overlapping(frameContentMin, frameContentMax, boxMin, boxMax))
|
||||||
|
frameBoxSelection.insert(frameReference);
|
||||||
|
if (type != TRIGGER) selectionFrameTime += frame.duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFramesChildVisible)
|
||||||
{
|
{
|
||||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) &&
|
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) &&
|
||||||
ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_RouteFocused))
|
ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_RouteFocused))
|
||||||
@@ -2396,19 +2461,6 @@ namespace anm2ed::imgui
|
|||||||
reference_clear();
|
reference_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto drawList = ImGui::GetWindowDrawList();
|
|
||||||
auto clipMax = drawList->GetClipRectMax();
|
|
||||||
auto length = animation ? animation->frameNum : 0;
|
|
||||||
auto frameSize = ImVec2(ImGui::GetTextLineHeight(), ImGui::GetContentRegionAvail().y);
|
|
||||||
auto framesSize = ImVec2(frameSize.x * length, frameSize.y);
|
|
||||||
auto cursorPos = ImGui::GetCursorPos();
|
|
||||||
auto cursorScreenPos = ImGui::GetCursorScreenPos();
|
|
||||||
auto border = glm::max(0.5f, ImGui::GetStyle().FrameBorderSize * 0.5f);
|
|
||||||
auto borderLineLength = frameSize.y / 5;
|
|
||||||
auto frameMin = std::max(0, (int)std::floor(scroll.x / frameSize.x) - 1);
|
|
||||||
auto frameMax = std::min(FRAME_NUM_MAX, (int)std::ceil((scroll.x + clipMax.x) / frameSize.x) + 1);
|
|
||||||
pickerLineDrawList = drawList;
|
|
||||||
|
|
||||||
if (type == NONE)
|
if (type == NONE)
|
||||||
{
|
{
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
@@ -2495,7 +2547,7 @@ namespace anm2ed::imgui
|
|||||||
{
|
{
|
||||||
float frameTime{};
|
float frameTime{};
|
||||||
|
|
||||||
if (!isFrameBoxSelecting && !frameMoveDrag.isActive && ImGui::IsWindowHovered() &&
|
if (!isFrameBoxPending && !isFrameBoxSelecting && !frameMoveDrag.isActive && ImGui::IsWindowHovered() &&
|
||||||
(ImGui::IsMouseReleased(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Right)) &&
|
(ImGui::IsMouseReleased(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Right)) &&
|
||||||
!ImGui::IsAnyItemHovered())
|
!ImGui::IsAnyItemHovered())
|
||||||
reference_set_item(type, id);
|
reference_set_item(type, id);
|
||||||
@@ -2515,7 +2567,7 @@ namespace anm2ed::imgui
|
|||||||
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
|
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
|
||||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsAnyItemHovered())
|
ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsAnyItemHovered())
|
||||||
{
|
{
|
||||||
isFrameBoxSelecting = true;
|
isFrameBoxPending = true;
|
||||||
isFrameBoxAdditive = ImGui::IsKeyDown(ImGuiMod_Ctrl);
|
isFrameBoxAdditive = ImGui::IsKeyDown(ImGuiMod_Ctrl);
|
||||||
frameBoxStart = frame_box_content_point_get();
|
frameBoxStart = frame_box_content_point_get();
|
||||||
frameBoxEnd = frameBoxStart;
|
frameBoxEnd = frameBoxStart;
|
||||||
@@ -2595,16 +2647,6 @@ namespace anm2ed::imgui
|
|||||||
auto buttonSize = type == TRIGGER ? frameSize : to_imvec2(vec2(frameSize.x * frame.duration, frameSize.y));
|
auto buttonSize = type == TRIGGER ? frameSize : to_imvec2(vec2(frameSize.x * frame.duration, frameSize.y));
|
||||||
auto frameStart = type == TRIGGER ? frame.atFrame : frameTime;
|
auto frameStart = type == TRIGGER ? frame.atFrame : frameTime;
|
||||||
auto frameEnd = type == TRIGGER ? frameStart + 1.0f : frameStart + frame.duration;
|
auto frameEnd = type == TRIGGER ? frameStart + 1.0f : frameStart + frame.duration;
|
||||||
if (isFrameBoxSelecting && isFrameBoxClipSet)
|
|
||||||
{
|
|
||||||
auto boxMin = ImVec2(std::min(frameBoxStart.x, frameBoxEnd.x), std::min(frameBoxStart.y, frameBoxEnd.y));
|
|
||||||
auto boxMax = ImVec2(std::max(frameBoxStart.x, frameBoxEnd.x), std::max(frameBoxStart.y, frameBoxEnd.y));
|
|
||||||
auto rowMinY = cursorScreenPos.y + scroll.y - frameBoxClipMin.y;
|
|
||||||
auto frameContentMin = ImVec2(frameStart * frameSize.x, rowMinY);
|
|
||||||
auto frameContentMax = ImVec2(frameEnd * frameSize.x, rowMinY + frameSize.y);
|
|
||||||
if (is_frame_box_overlapping(frameContentMin, frameContentMax, boxMin, boxMax))
|
|
||||||
frameBoxSelection.insert(frameReference);
|
|
||||||
}
|
|
||||||
if (frameEnd <= (float)frameMin || frameStart >= (float)frameMax)
|
if (frameEnd <= (float)frameMin || frameStart >= (float)frameMax)
|
||||||
{
|
{
|
||||||
if (type != TRIGGER) frameTime += frame.duration;
|
if (type != TRIGGER) frameTime += frame.duration;
|
||||||
@@ -2692,7 +2734,7 @@ namespace anm2ed::imgui
|
|||||||
|
|
||||||
ImGui::PopStyleColor(4);
|
ImGui::PopStyleColor(4);
|
||||||
|
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Left))
|
if (!isDraggedFrameActive && ImGui::IsItemHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Left))
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left))
|
if (ImGui::IsMouseDown(ImGuiMouseButton_Left))
|
||||||
{
|
{
|
||||||
@@ -2704,6 +2746,8 @@ namespace anm2ed::imgui
|
|||||||
draggedFrameIndex = (int)i;
|
draggedFrameIndex = (int)i;
|
||||||
draggedFrameStart = hoveredTime;
|
draggedFrameStart = hoveredTime;
|
||||||
if (type != TRIGGER) draggedFrameStartDuration = frame.duration;
|
if (type != TRIGGER) draggedFrameStartDuration = frame.duration;
|
||||||
|
draggedFrameStartMouseX = ImGui::GetIO().MousePos.x;
|
||||||
|
draggedFrameWidth = frameSize.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2816,13 +2860,20 @@ namespace anm2ed::imgui
|
|||||||
frameSelectionSnapshotReference = reference;
|
frameSelectionSnapshotReference = reference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDraggedFrameActive)
|
if (isDraggedFrameActive)
|
||||||
{
|
{
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||||
|
auto durationDelta = draggedFrameWidth > 0.0f
|
||||||
|
? static_cast<int>((ImGui::GetIO().MousePos.x - draggedFrameStartMouseX) /
|
||||||
|
draggedFrameWidth)
|
||||||
|
: hoveredTime - draggedFrameStart;
|
||||||
|
auto isDraggedFrameChanged =
|
||||||
|
draggedFrameType == TRIGGER ? hoveredTime != draggedFrameStart : durationDelta != 0;
|
||||||
|
|
||||||
if (!isDraggedFrameSnapshot && hoveredTime != draggedFrameStart)
|
if (!isDraggedFrameSnapshot && isDraggedFrameChanged)
|
||||||
{
|
{
|
||||||
isDraggedFrameSnapshot = true;
|
isDraggedFrameSnapshot = true;
|
||||||
snapshot_command_push(draggedFrameType == TRIGGER ? EDIT_TRIGGER_AT_FRAME : EDIT_FRAME_DURATION);
|
snapshot_command_push(draggedFrameType == TRIGGER ? EDIT_TRIGGER_AT_FRAME : EDIT_FRAME_DURATION);
|
||||||
@@ -2833,9 +2884,9 @@ namespace anm2ed::imgui
|
|||||||
auto targetReference = draggedFrameReference;
|
auto targetReference = draggedFrameReference;
|
||||||
auto targetType = draggedFrameType;
|
auto targetType = draggedFrameType;
|
||||||
auto targetIndex = draggedFrameIndex;
|
auto targetIndex = draggedFrameIndex;
|
||||||
auto targetStart = draggedFrameStart;
|
|
||||||
auto targetStartDuration = draggedFrameStartDuration;
|
auto targetStartDuration = draggedFrameStartDuration;
|
||||||
auto targetHoveredTime = hoveredTime;
|
auto targetHoveredTime = hoveredTime;
|
||||||
|
auto targetDurationDelta = durationDelta;
|
||||||
auto isPlaybackClamp = settings.playbackIsClamp;
|
auto isPlaybackClamp = settings.playbackIsClamp;
|
||||||
auto animationLength = animation ? animation->frameNum : FRAME_NUM_MAX;
|
auto animationLength = animation ? animation->frameNum : FRAME_NUM_MAX;
|
||||||
command_push([=](Manager&, Document& document)
|
command_push([=](Manager&, Document& document)
|
||||||
@@ -2859,8 +2910,8 @@ namespace anm2ed::imgui
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
frame->duration = glm::clamp(targetStartDuration + (targetHoveredTime - targetStart),
|
frame->duration = glm::clamp(targetStartDuration + targetDurationDelta, FRAME_DURATION_MIN,
|
||||||
FRAME_DURATION_MIN, FRAME_DURATION_MAX);
|
FRAME_DURATION_MAX);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2882,6 +2933,8 @@ namespace anm2ed::imgui
|
|||||||
draggedFrameIndex = -1;
|
draggedFrameIndex = -1;
|
||||||
draggedFrameStart = -1;
|
draggedFrameStart = -1;
|
||||||
draggedFrameStartDuration = -1;
|
draggedFrameStartDuration = -1;
|
||||||
|
draggedFrameStartMouseX = 0.0f;
|
||||||
|
draggedFrameWidth = 0.0f;
|
||||||
isDraggedFrameSnapshot = false;
|
isDraggedFrameSnapshot = false;
|
||||||
frameSelectionLocked.clear();
|
frameSelectionLocked.clear();
|
||||||
}
|
}
|
||||||
@@ -2971,11 +3024,21 @@ namespace anm2ed::imgui
|
|||||||
frameBoxClipMin = frameBoxDrawList->GetClipRectMin();
|
frameBoxClipMin = frameBoxDrawList->GetClipRectMin();
|
||||||
frameBoxClipMax = frameBoxDrawList->GetClipRectMax();
|
frameBoxClipMax = frameBoxDrawList->GetClipRectMax();
|
||||||
isFrameBoxClipSet = true;
|
isFrameBoxClipSet = true;
|
||||||
if (isFrameBoxSelecting)
|
if (isFrameBoxPending || isFrameBoxSelecting)
|
||||||
{
|
{
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
auto threshold = ImGui::GetTextLineHeightWithSpacing() * 0.125f;
|
||||||
|
frameBoxEnd = frame_box_content_point_get();
|
||||||
|
auto distance = ImVec2(frameBoxEnd.x - frameBoxStart.x, frameBoxEnd.y - frameBoxStart.y);
|
||||||
|
if (isFrameBoxPending && distance.x * distance.x + distance.y * distance.y >= threshold * threshold)
|
||||||
|
{
|
||||||
|
isFrameBoxPending = false;
|
||||||
|
isFrameBoxSelecting = true;
|
||||||
|
}
|
||||||
auto edgeSize = ImGui::GetTextLineHeightWithSpacing();
|
auto edgeSize = ImGui::GetTextLineHeightWithSpacing();
|
||||||
auto scrollStep = edgeSize * 0.5f;
|
auto scrollStep = edgeSize * 0.5f;
|
||||||
|
if (isFrameBoxSelecting)
|
||||||
|
{
|
||||||
if (io.MousePos.x < frameBoxClipMin.x + edgeSize)
|
if (io.MousePos.x < frameBoxClipMin.x + edgeSize)
|
||||||
scroll.x -= scrollStep;
|
scroll.x -= scrollStep;
|
||||||
else if (io.MousePos.x > frameBoxClipMax.x - edgeSize)
|
else if (io.MousePos.x > frameBoxClipMax.x - edgeSize)
|
||||||
@@ -2989,6 +3052,7 @@ namespace anm2ed::imgui
|
|||||||
frameBoxEnd = frame_box_content_point_get();
|
frameBoxEnd = frame_box_content_point_get();
|
||||||
frameBoxSelection.clear();
|
frameBoxSelection.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int index{};
|
int index{};
|
||||||
|
|
||||||
@@ -3016,42 +3080,26 @@ namespace anm2ed::imgui
|
|||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImDrawList* windowDrawList = ImGui::GetWindowDrawList();
|
if (isFrameBoxClipSet)
|
||||||
ImDrawList* foregroundDrawList = ImGui::GetForegroundDrawList();
|
|
||||||
auto lineBottomY = ImGui::GetWindowPos().y + ImGui::GetWindowSize().y;
|
|
||||||
if (isHorizontalScroll) lineBottomY -= ImGui::GetStyle().ScrollbarSize;
|
|
||||||
|
|
||||||
auto rectMin = windowDrawList->GetClipRectMin();
|
|
||||||
auto rectMax = windowDrawList->GetClipRectMax();
|
|
||||||
if (isFrameBoxSelecting && isFrameBoxClipSet)
|
|
||||||
{
|
{
|
||||||
auto boxContentMin =
|
auto overlayCursor = ImGui::GetCursorScreenPos();
|
||||||
ImVec2(std::min(frameBoxStart.x, frameBoxEnd.x), std::min(frameBoxStart.y, frameBoxEnd.y));
|
auto overlayPos = ImGui::GetWindowPos();
|
||||||
auto boxContentMax =
|
auto overlaySize = ImGui::GetWindowSize();
|
||||||
ImVec2(std::max(frameBoxStart.x, frameBoxEnd.x), std::max(frameBoxStart.y, frameBoxEnd.y));
|
ImGui::SetCursorScreenPos(overlayPos);
|
||||||
auto boxMin = frame_box_screen_point_get(boxContentMin);
|
if (ImGui::BeginChild("##Frames Overlay Child", overlaySize, ImGuiChildFlags_None,
|
||||||
auto boxMax = frame_box_screen_point_get(boxContentMax);
|
ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground |
|
||||||
auto boxClipMin = rectMin;
|
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
|
||||||
if (isPlayheadLineSet) boxClipMin.y = std::max(boxClipMin.y, playheadLineTopY);
|
ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoNavInputs))
|
||||||
foregroundDrawList->PushClipRect(boxClipMin, rectMax, true);
|
frame_overlay_draw(ImGui::GetWindowDrawList(), frameBoxClipMin, frameBoxClipMax);
|
||||||
foregroundDrawList->AddRectFilled(boxMin, boxMax, ImGui::GetColorU32(ImGuiCol_DragDropTargetBg));
|
ImGui::EndChild();
|
||||||
foregroundDrawList->AddRect(boxMin, boxMax, ImGui::GetColorU32(ImGuiCol_DragDropTarget));
|
ImGui::SetCursorScreenPos(overlayCursor);
|
||||||
foregroundDrawList->PopClipRect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pickerLineDrawList && isPlayheadLineSet && lineBottomY > playheadLineTopY)
|
if (isFrameBoxPending || isFrameBoxSelecting)
|
||||||
{
|
|
||||||
auto linePos = ImVec2(playheadLineCenterX - (PLAYHEAD_LINE_THICKNESS * 0.5f), playheadLineTopY);
|
|
||||||
auto lineSize = ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f), std::max(0.0f, lineBottomY - playheadLineTopY));
|
|
||||||
foregroundDrawList->PushClipRect(rectMin, rectMax, true);
|
|
||||||
foregroundDrawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y),
|
|
||||||
ImGui::GetColorU32(playheadLineColor));
|
|
||||||
foregroundDrawList->PopClipRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFrameBoxSelecting)
|
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
if (isFrameBoxSelecting)
|
||||||
{
|
{
|
||||||
group_selection_reset();
|
group_selection_reset();
|
||||||
if (isFrameBoxAdditive)
|
if (isFrameBoxAdditive)
|
||||||
@@ -3063,6 +3111,8 @@ namespace anm2ed::imgui
|
|||||||
document.items.references.insert(item_reference_from_frame_get(frameReference));
|
document.items.references.insert(item_reference_from_frame_get(frameReference));
|
||||||
if (!document.frames.references.empty()) reference = *document.frames.references.begin();
|
if (!document.frames.references.empty()) reference = *document.frames.references.begin();
|
||||||
frames_selection_sync_for(document);
|
frames_selection_sync_for(document);
|
||||||
|
}
|
||||||
|
isFrameBoxPending = false;
|
||||||
isFrameBoxSelecting = false;
|
isFrameBoxSelecting = false;
|
||||||
frameBoxSelection.clear();
|
frameBoxSelection.clear();
|
||||||
}
|
}
|
||||||
@@ -3240,7 +3290,7 @@ namespace anm2ed::imgui
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
itemProperties.update(manager, settings, document, reference, reference_set_item);
|
if (itemProperties.update(manager, settings, document, reference)) group_selection_reset();
|
||||||
group_properties_update();
|
group_properties_update();
|
||||||
|
|
||||||
bakePopup.trigger();
|
bakePopup.trigger();
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace anm2ed::imgui
|
|||||||
popup::ItemProperties itemProperties{};
|
popup::ItemProperties itemProperties{};
|
||||||
PopupHelper bakePopup{PopupHelper(LABEL_TIMELINE_BAKE_POPUP, POPUP_SMALL_NO_HEIGHT)};
|
PopupHelper bakePopup{PopupHelper(LABEL_TIMELINE_BAKE_POPUP, POPUP_SMALL_NO_HEIGHT)};
|
||||||
int hoveredTime{};
|
int hoveredTime{};
|
||||||
|
bool isFrameBoxPending{};
|
||||||
bool isFrameBoxSelecting{};
|
bool isFrameBoxSelecting{};
|
||||||
bool isFrameBoxAdditive{};
|
bool isFrameBoxAdditive{};
|
||||||
ImVec2 frameBoxStart{};
|
ImVec2 frameBoxStart{};
|
||||||
@@ -75,6 +76,8 @@ namespace anm2ed::imgui
|
|||||||
int draggedFrameIndex{-1};
|
int draggedFrameIndex{-1};
|
||||||
int draggedFrameStart{-1};
|
int draggedFrameStart{-1};
|
||||||
int draggedFrameStartDuration{-1};
|
int draggedFrameStartDuration{-1};
|
||||||
|
float draggedFrameStartMouseX{};
|
||||||
|
float draggedFrameWidth{};
|
||||||
bool isDraggedFrameSnapshot{};
|
bool isDraggedFrameSnapshot{};
|
||||||
bool frameFocusRequested{};
|
bool frameFocusRequested{};
|
||||||
int frameFocusIndex{-1};
|
int frameFocusIndex{-1};
|
||||||
@@ -87,7 +90,6 @@ namespace anm2ed::imgui
|
|||||||
bool isFrameSelectionAnchorSet{};
|
bool isFrameSelectionAnchorSet{};
|
||||||
std::vector<TimelineRowReference> rowDragReferences{};
|
std::vector<TimelineRowReference> rowDragReferences{};
|
||||||
glm::vec2 scroll{};
|
glm::vec2 scroll{};
|
||||||
ImDrawList* pickerLineDrawList{};
|
|
||||||
ImGuiStyle style{};
|
ImGuiStyle style{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ namespace anm2ed::imgui
|
|||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar |
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar |
|
||||||
ImGuiWindowFlags_NoScrollWithMouse))
|
ImGuiWindowFlags_NoScrollWithMouse))
|
||||||
{
|
{
|
||||||
|
|
||||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE);
|
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE);
|
||||||
ImGui::TextUnformatted(localize.get(LABEL_APPLICATION_NAME));
|
ImGui::TextUnformatted(localize.get(LABEL_APPLICATION_NAME));
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|||||||
@@ -292,8 +292,8 @@ namespace anm2ed::imgui
|
|||||||
|
|
||||||
std::filesystem::path window_asset_path_get(Document& document, const std::filesystem::path& path)
|
std::filesystem::path window_asset_path_get(Document& document, const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
WorkingDirectory workingDirectory(document.directory_get());
|
auto loadPath = path::lower_case_backslash_handle(path);
|
||||||
return path::lower_case_backslash_handle(path::make_relative(path));
|
return path::backslash_replace(path::make_relative(loadPath, document.directory_get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_directory_open(Dialog& dialog, Document& document, const std::filesystem::path& path)
|
void window_directory_open(Dialog& dialog, Document& document, const std::filesystem::path& path)
|
||||||
@@ -1900,7 +1900,12 @@ namespace anm2ed::imgui
|
|||||||
window.reload = [](Window& window, Manager&, Settings&, Document& document, Clipboard&)
|
window.reload = [](Window& window, Manager&, Settings&, Document& document, Clipboard&)
|
||||||
{
|
{
|
||||||
auto selected = document.spritesheet.selection;
|
auto selected = document.spritesheet.selection;
|
||||||
window_edit(window, document, localize.get(EDIT_RELOAD_SPRITESHEETS), []() {});
|
window_edit(window, document, localize.get(EDIT_RELOAD_SPRITESHEETS),
|
||||||
|
[&]()
|
||||||
|
{
|
||||||
|
for (auto& id : selected)
|
||||||
|
document.texture_reload(id);
|
||||||
|
});
|
||||||
|
|
||||||
for (auto& id : selected)
|
for (auto& id : selected)
|
||||||
{
|
{
|
||||||
@@ -2286,6 +2291,7 @@ namespace anm2ed::imgui
|
|||||||
auto spritesheet = document.anm2.element_get(ElementType::SPRITESHEET, id);
|
auto spritesheet = document.anm2.element_get(ElementType::SPRITESHEET, id);
|
||||||
if (!spritesheet) return;
|
if (!spritesheet) return;
|
||||||
spritesheet->path = window_asset_path_get(document, dialogPath);
|
spritesheet->path = window_asset_path_get(document, dialogPath);
|
||||||
|
document.texture_reload(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
window_edit(document, Document::SPRITESHEETS, localize.get(EDIT_REPLACE_SPRITESHEET),
|
window_edit(document, Document::SPRITESHEETS, localize.get(EDIT_REPLACE_SPRITESHEET),
|
||||||
@@ -2544,6 +2550,7 @@ namespace anm2ed::imgui
|
|||||||
{
|
{
|
||||||
auto sound = window_element_get(window, document.anm2, id);
|
auto sound = window_element_get(window, document.anm2, id);
|
||||||
if (!sound) continue;
|
if (!sound) continue;
|
||||||
|
document.sound_reload(id);
|
||||||
auto pathString = path::to_utf8(sound->path);
|
auto pathString = path::to_utf8(sound->path);
|
||||||
toasts.push(std::vformat(localize.get(TOAST_RELOAD_SOUND), std::make_format_args(id, pathString)));
|
toasts.push(std::vformat(localize.get(TOAST_RELOAD_SOUND), std::make_format_args(id, pathString)));
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -2850,6 +2857,7 @@ namespace anm2ed::imgui
|
|||||||
auto sound = document.anm2.element_get(ElementType::SOUND_ELEMENT, id);
|
auto sound = document.anm2.element_get(ElementType::SOUND_ELEMENT, id);
|
||||||
if (!sound) return;
|
if (!sound) return;
|
||||||
sound->path = window_asset_path_get(document, dialogPath);
|
sound->path = window_asset_path_get(document, dialogPath);
|
||||||
|
document.sound_reload(id);
|
||||||
auto pathString = path::to_utf8(sound->path);
|
auto pathString = path::to_utf8(sound->path);
|
||||||
toasts.push(std::vformat(localize.get(TOAST_REPLACE_SOUND), std::make_format_args(id, pathString)));
|
toasts.push(std::vformat(localize.get(TOAST_REPLACE_SOUND), std::make_format_args(id, pathString)));
|
||||||
logger.info(std::vformat(localize.get(TOAST_REPLACE_SOUND, anm2ed::ENGLISH),
|
logger.info(std::vformat(localize.get(TOAST_REPLACE_SOUND, anm2ed::ENGLISH),
|
||||||
|
|||||||
+244
-26
@@ -1,23 +1,35 @@
|
|||||||
#include "about.hpp"
|
#include "about.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cfloat>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <imgui.h>
|
#include <format>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "log.hpp"
|
||||||
|
#include "math.hpp"
|
||||||
#include "strings.hpp"
|
#include "strings.hpp"
|
||||||
|
|
||||||
using namespace anm2ed::resource;
|
using namespace anm2ed::resource;
|
||||||
|
using namespace anm2ed::util;
|
||||||
|
using namespace glm;
|
||||||
|
|
||||||
namespace anm2ed::imgui::wizard
|
namespace anm2ed::imgui::wizard
|
||||||
{
|
{
|
||||||
static constexpr auto CREDIT_DELAY = 1.0f;
|
static constexpr float CREDIT_DELAY = 0.66f;
|
||||||
static constexpr auto CREDIT_SCROLL_SPEED = 25.0f;
|
static constexpr float CREDIT_SCROLL_SPEED = 33.0f;
|
||||||
|
static constexpr float FRIEND_HEIGHT_MULTIPLIER = 2.0f;
|
||||||
|
static constexpr float FRIEND_PADDING_RATIO = 0.15f;
|
||||||
|
static constexpr int FRIEND_ROW_SLOT_COUNT = 5;
|
||||||
|
static constexpr int FRIEND_ORDER_LEFT[] = {resource::friends::MEAT_BOY, resource::friends::ISAAC};
|
||||||
|
static constexpr int FRIEND_ORDER_RIGHT[] = {resource::friends::STACY, resource::friends::ASH};
|
||||||
|
|
||||||
static constexpr About::Credit CREDITS[] = {
|
static constexpr About::Credit CREDITS[] = {
|
||||||
{"Anm2Ed", font::BOLD},
|
{"Anm2Ed", font::BOLD},
|
||||||
{"License: GPLv3"},
|
{"License: GPLv3"},
|
||||||
{""},
|
{""},
|
||||||
{"Designer", font::BOLD},
|
{"Design/Programming", font::BOLD},
|
||||||
{"Shweet"},
|
{"Shweet"},
|
||||||
{"OpenAI Codex"},
|
{"OpenAI Codex"},
|
||||||
{""},
|
{""},
|
||||||
@@ -30,7 +42,7 @@ namespace anm2ed::imgui::wizard
|
|||||||
{"CxRedix (Chinese)"},
|
{"CxRedix (Chinese)"},
|
||||||
{"sawalk/사왈이 (Korean)"},
|
{"sawalk/사왈이 (Korean)"},
|
||||||
{""},
|
{""},
|
||||||
{"Based on the work of:", font::BOLD},
|
{"Based on the work of", font::BOLD},
|
||||||
{"Adrian Gavrilita"},
|
{"Adrian Gavrilita"},
|
||||||
{"Simon Parzer"},
|
{"Simon Parzer"},
|
||||||
{"Matt Kapuszczak"},
|
{"Matt Kapuszczak"},
|
||||||
@@ -41,6 +53,9 @@ namespace anm2ed::imgui::wizard
|
|||||||
{"https://www.newgrounds.com/audio/listen/1565433"},
|
{"https://www.newgrounds.com/audio/listen/1565433"},
|
||||||
{"License: CC0"},
|
{"License: CC0"},
|
||||||
{""},
|
{""},
|
||||||
|
{"Dancing Characters", font::BOLD},
|
||||||
|
{"Shweet"},
|
||||||
|
{""},
|
||||||
{"Libraries", font::BOLD},
|
{"Libraries", font::BOLD},
|
||||||
{"Dear ImGui"},
|
{"Dear ImGui"},
|
||||||
{"https://github.com/ocornut/imgui"},
|
{"https://github.com/ocornut/imgui"},
|
||||||
@@ -89,46 +104,250 @@ namespace anm2ed::imgui::wizard
|
|||||||
{""},
|
{""},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
{"enjoy the jams :)"},
|
{"enjoy the jams :)"},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
{""},
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
{""},
|
|
||||||
};
|
};
|
||||||
static constexpr auto CREDIT_COUNT = (int)(sizeof(CREDITS) / sizeof(About::Credit));
|
static constexpr auto CREDIT_COUNT = (int)(sizeof(CREDITS) / sizeof(About::Credit));
|
||||||
|
|
||||||
|
const Element* friend_animation_get(const About::FriendState& state)
|
||||||
|
{
|
||||||
|
auto animations = state.anm2.element_get(ElementType::ANIMATIONS);
|
||||||
|
if (!animations) return nullptr;
|
||||||
|
|
||||||
|
if (!animations->defaultAnimation.empty())
|
||||||
|
for (const auto& child : animations->children)
|
||||||
|
if (child.type == ElementType::ANIMATION && child.name == animations->defaultAnimation) return &child;
|
||||||
|
|
||||||
|
for (const auto& child : animations->children)
|
||||||
|
if (child.type == ElementType::ANIMATION) return &child;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void friend_state_load(About::FriendState& state, const resource::friends::Info& info)
|
||||||
|
{
|
||||||
|
if (!state.canvas) state.canvas = std::make_unique<Canvas>(vec2(1.0f, 1.0f));
|
||||||
|
|
||||||
|
state.anm2 = Anm2{};
|
||||||
|
state.textures.clear();
|
||||||
|
state.rect = vec4(-1.0f);
|
||||||
|
state.time = 0.0f;
|
||||||
|
state.fps = 30.0f;
|
||||||
|
state.isLoaded = false;
|
||||||
|
|
||||||
|
std::string errorString{};
|
||||||
|
if (!state.anm2.load_string(info.anm2, &errorString))
|
||||||
|
{
|
||||||
|
logger.error(std::format("Unable to load friend animation {}: {}", info.name, errorString));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto anm2Info = state.anm2.element_get(ElementType::INFO))
|
||||||
|
if (anm2Info->fps > 0) state.fps = (float)anm2Info->fps;
|
||||||
|
|
||||||
|
if (auto spritesheets = state.anm2.element_get(ElementType::SPRITESHEETS))
|
||||||
|
for (auto& spritesheet : spritesheets->children)
|
||||||
|
if (spritesheet.type == ElementType::SPRITESHEET)
|
||||||
|
state.textures[spritesheet.id] = Texture(info.png, info.pngSize);
|
||||||
|
|
||||||
|
auto animation = friend_animation_get(state);
|
||||||
|
if (!animation)
|
||||||
|
{
|
||||||
|
logger.error(std::format("Friend animation {} has no animation.", info.name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.rect = state.anm2.animation_rect(*animation, true);
|
||||||
|
state.isLoaded = state.rect != vec4(-1.0f) && !state.textures.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void friend_state_tick(About::FriendState& state, float delta)
|
||||||
|
{
|
||||||
|
if (!state.isLoaded) return;
|
||||||
|
|
||||||
|
auto animation = friend_animation_get(state);
|
||||||
|
if (!animation || animation->frameNum <= 0) return;
|
||||||
|
|
||||||
|
state.time = std::fmod(state.time + delta * state.fps, (float)animation->frameNum);
|
||||||
|
if (state.time < 0.0f) state.time += (float)animation->frameNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 friend_size_get(const About::FriendState& state, float height)
|
||||||
|
{
|
||||||
|
auto width = height;
|
||||||
|
if (state.rect.w > 0.0f && state.rect.z > 0.0f) width = height * (state.rect.z / state.rect.w);
|
||||||
|
return ImVec2(std::max(width, 1.0f), std::max(height, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void friend_layer_draw(About::FriendState& state, Resources& resources, const mat4& baseTransform,
|
||||||
|
const Element& layerAnimation, const Element& rootFrame)
|
||||||
|
{
|
||||||
|
if (layerAnimation.type == ElementType::GROUP)
|
||||||
|
{
|
||||||
|
for (auto& child : layerAnimation.children)
|
||||||
|
friend_layer_draw(state, resources, baseTransform, child, rootFrame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerAnimation.type != ElementType::LAYER_ANIMATION || !layerAnimation.isVisible) return;
|
||||||
|
|
||||||
|
auto layer = state.anm2.element_get(ElementType::LAYER_ELEMENT, layerAnimation.layerId);
|
||||||
|
if (!layer) return;
|
||||||
|
|
||||||
|
auto textureIt = state.textures.find(layer->spritesheetId);
|
||||||
|
if (textureIt == state.textures.end() || !textureIt->second.is_valid()) return;
|
||||||
|
|
||||||
|
auto frame = state.anm2.frame_effective(layerAnimation.layerId, frame_generate(layerAnimation, state.time));
|
||||||
|
if (!frame.isVisible || frame.size == vec2()) return;
|
||||||
|
|
||||||
|
auto& texture = textureIt->second;
|
||||||
|
auto textureSize = vec2(texture.size);
|
||||||
|
if (textureSize.x <= 0.0f || textureSize.y <= 0.0f) return;
|
||||||
|
|
||||||
|
auto transform = baseTransform * math::quad_model_get(frame.size, frame.position, frame.pivot,
|
||||||
|
math::percent_to_unit(frame.scale), frame.rotation);
|
||||||
|
auto uvVertices = math::uv_vertices_get(frame.crop / textureSize, (frame.crop + frame.size) / textureSize);
|
||||||
|
auto tint = frame.tint * rootFrame.tint;
|
||||||
|
auto colorOffset = frame.colorOffset + rootFrame.colorOffset;
|
||||||
|
|
||||||
|
state.canvas->texture_render(resources.shaders[shader::TEXTURE], texture.id, transform, tint, colorOffset,
|
||||||
|
uvVertices.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void friend_canvas_draw(About::FriendState& state, Resources& resources, ImVec2 displaySize)
|
||||||
|
{
|
||||||
|
if (!state.isLoaded || !state.canvas) return;
|
||||||
|
|
||||||
|
auto canvasSize = vec2(std::max(displaySize.x, 1.0f), std::max(displaySize.y, 1.0f));
|
||||||
|
state.canvas->size_set(canvasSize);
|
||||||
|
state.canvas->bind();
|
||||||
|
state.canvas->viewport_set();
|
||||||
|
state.canvas->clear(vec4(0.0f));
|
||||||
|
|
||||||
|
auto animation = friend_animation_get(state);
|
||||||
|
if (!animation)
|
||||||
|
{
|
||||||
|
state.canvas->unbind();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float zoom = 100.0f;
|
||||||
|
vec2 pan{};
|
||||||
|
auto rect = state.rect;
|
||||||
|
auto padding = std::max(2.0f, std::max(rect.z, rect.w) * FRIEND_PADDING_RATIO);
|
||||||
|
rect.x -= padding;
|
||||||
|
rect.y -= padding;
|
||||||
|
rect.z += padding * 2.0f;
|
||||||
|
rect.w += padding * 2.0f;
|
||||||
|
state.canvas->set_to_rect(zoom, pan, rect);
|
||||||
|
|
||||||
|
auto transform = state.canvas->transform_get(zoom, pan);
|
||||||
|
Element rootFrame{};
|
||||||
|
if (auto root = animation_item_get(*animation, ItemType::ROOT))
|
||||||
|
{
|
||||||
|
rootFrame = frame_generate(*root, state.time);
|
||||||
|
transform *= math::quad_model_parent_get(rootFrame.position, {}, math::percent_to_unit(rootFrame.scale),
|
||||||
|
rootFrame.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto layerAnimations = element_child_first_get(*animation, ElementType::LAYER_ANIMATIONS))
|
||||||
|
for (auto& layerAnimation : layerAnimations->children)
|
||||||
|
friend_layer_draw(state, resources, transform, layerAnimation, rootFrame);
|
||||||
|
|
||||||
|
state.canvas->unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void friend_row_draw(About& about, Resources& resources, const char* titleLabel, ImVec2 size)
|
||||||
|
{
|
||||||
|
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE);
|
||||||
|
auto titleSize = ImGui::CalcTextSize(titleLabel);
|
||||||
|
ImGui::PopFont();
|
||||||
|
|
||||||
|
auto slotWidth = std::max(size.x / (float)FRIEND_ROW_SLOT_COUNT, 1.0f);
|
||||||
|
float friendHeight = titleSize.y * FRIEND_HEIGHT_MULTIPLIER;
|
||||||
|
float maxAspect{};
|
||||||
|
for (auto index : FRIEND_ORDER_LEFT)
|
||||||
|
maxAspect = std::max(maxAspect, about.friendStates[index].rect.w > 0.0f
|
||||||
|
? about.friendStates[index].rect.z / about.friendStates[index].rect.w
|
||||||
|
: 1.0f);
|
||||||
|
for (auto index : FRIEND_ORDER_RIGHT)
|
||||||
|
maxAspect = std::max(maxAspect, about.friendStates[index].rect.w > 0.0f
|
||||||
|
? about.friendStates[index].rect.z / about.friendStates[index].rect.w
|
||||||
|
: 1.0f);
|
||||||
|
if (maxAspect > 0.0f) friendHeight = std::min(friendHeight, slotWidth / maxAspect);
|
||||||
|
friendHeight = std::max(friendHeight, 1.0f);
|
||||||
|
|
||||||
|
std::array<ImVec2, resource::friends::COUNT> friendSizes{};
|
||||||
|
for (auto index : FRIEND_ORDER_LEFT)
|
||||||
|
friendSizes[index] = friend_size_get(about.friendStates[index], friendHeight);
|
||||||
|
for (auto index : FRIEND_ORDER_RIGHT)
|
||||||
|
friendSizes[index] = friend_size_get(about.friendStates[index], friendHeight);
|
||||||
|
|
||||||
|
for (auto index : FRIEND_ORDER_LEFT)
|
||||||
|
friend_canvas_draw(about.friendStates[index], resources, friendSizes[index]);
|
||||||
|
for (auto index : FRIEND_ORDER_RIGHT)
|
||||||
|
friend_canvas_draw(about.friendStates[index], resources, friendSizes[index]);
|
||||||
|
|
||||||
|
auto rowHeight = std::max(titleSize.y, friendHeight);
|
||||||
|
auto rowMin = ImGui::GetCursorScreenPos();
|
||||||
|
auto rowMax = ImVec2(rowMin.x + size.x, rowMin.y + rowHeight);
|
||||||
|
auto drawList = ImGui::GetWindowDrawList();
|
||||||
|
auto textColor = ImGui::GetColorU32(ImGuiCol_Text);
|
||||||
|
|
||||||
|
auto slot_center_x_get = [&](int slot)
|
||||||
|
{
|
||||||
|
auto offset = slotWidth * ((float)slot + 0.5f);
|
||||||
|
return std::min(rowMin.x + offset, rowMax.x - slotWidth * 0.5f);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto image_draw = [&](int slot, int index)
|
||||||
|
{
|
||||||
|
auto centerX = slot_center_x_get(slot);
|
||||||
|
auto size = friendSizes[index];
|
||||||
|
auto min = ImVec2(centerX - size.x * 0.5f, rowMin.y + (rowHeight - size.y) * 0.5f);
|
||||||
|
auto max = ImVec2(min.x + size.x, min.y + size.y);
|
||||||
|
drawList->AddImage((ImTextureID)(intptr_t)about.friendStates[index].canvas->texture, min, max);
|
||||||
|
};
|
||||||
|
|
||||||
|
drawList->PushClipRect(rowMin, rowMax, true);
|
||||||
|
image_draw(0, resource::friends::MEAT_BOY);
|
||||||
|
image_draw(1, resource::friends::ISAAC);
|
||||||
|
|
||||||
|
auto titleCenterX = slot_center_x_get(2);
|
||||||
|
auto titlePos = ImVec2(titleCenterX - titleSize.x * 0.5f, rowMin.y + (rowHeight - titleSize.y) * 0.5f);
|
||||||
|
drawList->AddText(resources.fonts[font::BOLD].get(), (float)font::SIZE_LARGE, titlePos, textColor, titleLabel);
|
||||||
|
|
||||||
|
image_draw(3, resource::friends::STACY);
|
||||||
|
image_draw(4, resource::friends::ASH);
|
||||||
|
drawList->PopClipRect();
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(size.x, rowHeight));
|
||||||
|
}
|
||||||
|
|
||||||
void About::reset(Resources& resources)
|
void About::reset(Resources& resources)
|
||||||
{
|
{
|
||||||
resources.music_track().play(true);
|
resources.music_track().play(true);
|
||||||
creditsState = {};
|
creditsState = {};
|
||||||
creditsState.spawnTimer = CREDIT_DELAY;
|
creditsState.spawnTimer = CREDIT_DELAY;
|
||||||
|
|
||||||
|
for (int i = 0; i < resource::friends::COUNT; ++i)
|
||||||
|
friend_state_load(friendStates[i], resource::friends::FRIENDS[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void About::update(Resources& resources)
|
void About::update(Resources& resources)
|
||||||
{
|
{
|
||||||
auto size = ImGui::GetContentRegionAvail();
|
auto size = ImGui::GetContentRegionAvail();
|
||||||
auto applicationLabel = localize.get(LABEL_APPLICATION_NAME);
|
auto titleLabel = localize.get(LABEL_APPLICATION_NAME);
|
||||||
auto versionLabel = localize.get(LABEL_APPLICATION_VERSION);
|
auto delta = ImGui::GetIO().DeltaTime;
|
||||||
|
|
||||||
ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE);
|
for (auto& friendState : friendStates)
|
||||||
|
friend_state_tick(friendState, delta);
|
||||||
|
|
||||||
ImGui::SetCursorPosX((size.x - ImGui::CalcTextSize(applicationLabel).x) / 2);
|
friend_row_draw(*this, resources, titleLabel, size);
|
||||||
ImGui::TextUnformatted(applicationLabel);
|
|
||||||
|
|
||||||
ImGui::SetCursorPosX((size.x - ImGui::CalcTextSize(versionLabel).x) / 2);
|
|
||||||
ImGui::TextUnformatted(versionLabel);
|
|
||||||
|
|
||||||
ImGui::PopFont();
|
|
||||||
|
|
||||||
auto creditRegionPos = ImGui::GetCursorScreenPos();
|
auto creditRegionPos = ImGui::GetCursorScreenPos();
|
||||||
auto creditRegionSize = ImGui::GetContentRegionAvail();
|
auto creditRegionSize = ImGui::GetContentRegionAvail();
|
||||||
@@ -140,7 +359,6 @@ namespace anm2ed::imgui::wizard
|
|||||||
auto clipMax = ImVec2(creditRegionPos.x + creditRegionSize.x, creditRegionPos.y + creditRegionSize.y);
|
auto clipMax = ImVec2(creditRegionPos.x + creditRegionSize.x, creditRegionPos.y + creditRegionSize.y);
|
||||||
drawList->PushClipRect(creditRegionPos, clipMax, true);
|
drawList->PushClipRect(creditRegionPos, clipMax, true);
|
||||||
|
|
||||||
auto delta = ImGui::GetIO().DeltaTime;
|
|
||||||
creditsState.spawnTimer -= delta;
|
creditsState.spawnTimer -= delta;
|
||||||
auto maxVisible = std::max(1, (int)std::floor(creditRegionSize.y / (float)fontSize));
|
auto maxVisible = std::max(1, (int)std::floor(creditRegionSize.y / (float)fontSize));
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../../anm2/anm2.hpp"
|
||||||
|
#include "../../canvas.hpp"
|
||||||
|
#include "../../resource/friends.hpp"
|
||||||
#include "../../resources.hpp"
|
#include "../../resources.hpp"
|
||||||
|
|
||||||
namespace anm2ed::imgui::wizard
|
namespace anm2ed::imgui::wizard
|
||||||
@@ -26,8 +34,20 @@ namespace anm2ed::imgui::wizard
|
|||||||
int nextIndex{};
|
int nextIndex{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FriendState
|
||||||
|
{
|
||||||
|
Anm2 anm2{};
|
||||||
|
std::unique_ptr<Canvas> canvas{};
|
||||||
|
std::unordered_map<int, resource::Texture> textures{};
|
||||||
|
glm::vec4 rect{-1.0f};
|
||||||
|
float time{};
|
||||||
|
float fps{30.0f};
|
||||||
|
bool isLoaded{};
|
||||||
|
};
|
||||||
|
|
||||||
int creditsIndex{};
|
int creditsIndex{};
|
||||||
CreditsState creditsState{};
|
CreditsState creditsState{};
|
||||||
|
std::array<FriendState, resource::friends::COUNT> friendStates{};
|
||||||
|
|
||||||
void reset(Resources& resources);
|
void reset(Resources& resources);
|
||||||
void update(Resources& resources);
|
void update(Resources& resources);
|
||||||
|
|||||||
@@ -0,0 +1,648 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace anm2ed::resource::friends
|
||||||
|
{
|
||||||
|
inline constexpr unsigned char MEAT_BOY_PNG[] = {
|
||||||
|
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||||
|
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x31,
|
||||||
|
0x08, 0x06, 0x00, 0x00, 0x00, 0x64, 0xbe, 0xd1, 0xd5, 0x00, 0x00, 0x02,
|
||||||
|
0x56, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x63, 0x18, 0x49, 0x80, 0x11,
|
||||||
|
0x8f, 0x67, 0xff, 0x0f, 0x60, 0x40, 0x30, 0xd2, 0xc2, 0x6e, 0x6c, 0x86,
|
||||||
|
0xfe, 0x1f, 0x44, 0xb1, 0x4d, 0x55, 0x4f, 0xa3, 0x1b, 0x06, 0xf7, 0x68,
|
||||||
|
0x1a, 0x83, 0x10, 0x43, 0x8a, 0xc8, 0x3b, 0xba, 0xfb, 0x7b, 0xce, 0x1b,
|
||||||
|
0x21, 0x86, 0x59, 0x0c, 0x28, 0xf6, 0x52, 0xcd, 0xc3, 0xc8, 0x06, 0x81,
|
||||||
|
0x3d, 0x3a, 0x50, 0x9e, 0x44, 0x0f, 0x55, 0x34, 0x4f, 0x53, 0xc5, 0xc3,
|
||||||
|
0x18, 0x9e, 0x3d, 0x25, 0x32, 0x78, 0x12, 0xb1, 0xd9, 0x1b, 0xb8, 0x5b,
|
||||||
|
0xa8, 0xe2, 0x59, 0x26, 0xa8, 0x71, 0xf0, 0x58, 0x1d, 0x4c, 0xa5, 0x33,
|
||||||
|
0x28, 0x95, 0x21, 0xbb, 0x8f, 0x52, 0xb7, 0x31, 0x8d, 0xa4, 0xaa, 0x87,
|
||||||
|
0x28, 0xcf, 0x82, 0xf2, 0x0f, 0x28, 0x49, 0xc1, 0x30, 0x88, 0x4f, 0x49,
|
||||||
|
0x20, 0x51, 0xdb, 0x3c, 0x62, 0xdd, 0x82, 0xd7, 0xb3, 0x30, 0x47, 0xa1,
|
||||||
|
0x95, 0x8e, 0xe0, 0xd2, 0x12, 0xe4, 0x71, 0x52, 0x3d, 0x4d, 0x6d, 0xf3,
|
||||||
|
0x48, 0x0d, 0x70, 0x9c, 0x9e, 0x85, 0x95, 0x86, 0xff, 0xff, 0xff, 0x67,
|
||||||
|
0x00, 0x61, 0x6c, 0x06, 0x83, 0x02, 0x81, 0x58, 0x0f, 0x53, 0xdb, 0x3c,
|
||||||
|
0x72, 0x52, 0x16, 0x4e, 0xcf, 0xa2, 0xc7, 0x26, 0x2e, 0xc3, 0x07, 0x4a,
|
||||||
|
0x1d, 0xd5, 0x3c, 0x8b, 0x1c, 0x5b, 0x8c, 0x8c, 0x8c, 0x0c, 0x20, 0x8c,
|
||||||
|
0xcf, 0x70, 0x42, 0xb1, 0x4b, 0x6d, 0xf3, 0xc8, 0x2d, 0x2f, 0x98, 0x70,
|
||||||
|
0x25, 0x4f, 0x52, 0x0c, 0x24, 0x14, 0xbb, 0xc4, 0xc6, 0x3e, 0xcc, 0x4e,
|
||||||
|
0x52, 0xd5, 0x13, 0xeb, 0x56, 0x16, 0x6c, 0x0a, 0xa9, 0xdd, 0xb0, 0x18,
|
||||||
|
0x2c, 0x0d, 0x15, 0x16, 0x72, 0x92, 0x04, 0x52, 0xcb, 0x86, 0xdc, 0x14,
|
||||||
|
0xc5, 0x30, 0x10, 0x01, 0xc0, 0xc2, 0x40, 0x01, 0x68, 0x68, 0x68, 0x00,
|
||||||
|
0xeb, 0xae, 0xaf, 0xaf, 0x27, 0x68, 0x4a, 0x63, 0x63, 0x23, 0x58, 0x0d,
|
||||||
|
0x4c, 0x0f, 0xc3, 0x00, 0x80, 0x11, 0xd5, 0x82, 0x82, 0x35, 0xb0, 0x49,
|
||||||
|
0xea, 0xf1, 0x60, 0xe9, 0x86, 0x91, 0x14, 0x4f, 0xc4, 0xf6, 0xac, 0xa8,
|
||||||
|
0xdd, 0xf3, 0x21, 0x2b, 0x66, 0x29, 0xed, 0xe7, 0x0e, 0x44, 0x3f, 0x19,
|
||||||
|
0x14, 0x1b, 0x64, 0x27, 0x63, 0x50, 0x01, 0x83, 0xd4, 0x2b, 0x21, 0x2a,
|
||||||
|
0x66, 0x41, 0xea, 0x07, 0xb2, 0x64, 0xa6, 0x28, 0xcf, 0x82, 0x62, 0x88,
|
||||||
|
0x18, 0x4f, 0xc3, 0x3c, 0x39, 0x50, 0x31, 0x0a, 0x8b, 0x09, 0x16, 0x6a,
|
||||||
|
0x14, 0x8a, 0x20, 0x4f, 0xa4, 0xe0, 0x35, 0xe8, 0x1d, 0xc3, 0x60, 0x00,
|
||||||
|
0x2c, 0xd4, 0x74, 0x04, 0xb6, 0x66, 0xe3, 0x40, 0xc7, 0x26, 0xb2, 0xff,
|
||||||
|
0xa8, 0xea, 0xd9, 0xc1, 0xe4, 0x31, 0x6c, 0x91, 0x38, 0x3a, 0x52, 0xc1,
|
||||||
|
0x30, 0x4c, 0xc1, 0x68, 0xcc, 0x8e, 0xc6, 0xec, 0x30, 0x08, 0x81, 0x11,
|
||||||
|
0x3b, 0x23, 0x00, 0x8a, 0x3b, 0x94, 0xb9, 0x9e, 0x81, 0x8a, 0x4c, 0x7a,
|
||||||
|
0xcc, 0xf5, 0xc0, 0xfc, 0x36, 0x62, 0x66, 0xf1, 0x90, 0x23, 0x73, 0xd8,
|
||||||
|
0xcd, 0xcf, 0x32, 0x8c, 0x82, 0x61, 0x1a, 0x02, 0x38, 0x27, 0xa3, 0xf1,
|
||||||
|
0xf8, 0x17, 0x65, 0x74, 0x83, 0x40, 0xb8, 0xe0, 0x9a, 0x6a, 0x24, 0x26,
|
||||||
|
0x8b, 0x10, 0x33, 0x4d, 0x49, 0x92, 0x39, 0x18, 0x55, 0x0f, 0x0d, 0x22,
|
||||||
|
0x95, 0x9c, 0x00, 0x85, 0x39, 0x03, 0x9f, 0x87, 0x49, 0x29, 0x53, 0xc0,
|
||||||
|
0xe6, 0x90, 0x34, 0x06, 0x85, 0x3c, 0x26, 0x44, 0x68, 0x1c, 0x09, 0xc7,
|
||||||
|
0xf8, 0x11, 0xd1, 0xf3, 0xc0, 0x48, 0xd5, 0x0f, 0x36, 0x0f, 0x93, 0x65,
|
||||||
|
0x0e, 0x4a, 0xdb, 0x98, 0x50, 0x17, 0x0d, 0x59, 0x9e, 0x14, 0xb5, 0x83,
|
||||||
|
0xa5, 0x08, 0x60, 0x19, 0x08, 0x87, 0x10, 0xd3, 0xef, 0x9d, 0xf5, 0x86,
|
||||||
|
0xb0, 0xcb, 0x48, 0x35, 0x67, 0xb4, 0xd7, 0x43, 0xeb, 0xd8, 0x26, 0x65,
|
||||||
|
0xd6, 0x0f, 0x9f, 0x5b, 0x48, 0x35, 0x07, 0xa5, 0x80, 0x22, 0x66, 0x98,
|
||||||
|
0x13, 0x36, 0xcf, 0x43, 0x8a, 0x5a, 0xa0, 0x83, 0x49, 0xa9, 0xae, 0xd0,
|
||||||
|
0xfd, 0x87, 0xb3, 0x80, 0x22, 0x31, 0x52, 0x18, 0xe9, 0x9d, 0x8c, 0x19,
|
||||||
|
0x49, 0x75, 0x20, 0x0e, 0xf5, 0x64, 0x99, 0x83, 0xe2, 0x59, 0x52, 0x92,
|
||||||
|
0x05, 0x05, 0x49, 0x91, 0x11, 0x1a, 0xd3, 0xc4, 0xd0, 0xf8, 0xc2, 0x86,
|
||||||
|
0x64, 0x73, 0x06, 0xa2, 0x51, 0x31, 0x60, 0x35, 0x11, 0x39, 0xad, 0x1b,
|
||||||
|
0x52, 0xf2, 0x1f, 0x23, 0xc3, 0x28, 0x18, 0x98, 0x10, 0x00, 0x00, 0xea,
|
||||||
|
0xf7, 0xc9, 0xdf, 0x52, 0x09, 0xa7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x49,
|
||||||
|
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::string_view MEAT_BOY_ANM2 = R"ANM2ED_FRIEND(
|
||||||
|
<AnimatedActor>
|
||||||
|
<Info CreatedBy="robot" CreatedOn="05/21/2026 11:07:19 PM" Fps="30" Version="0"/>
|
||||||
|
<Content>
|
||||||
|
<Spritesheets>
|
||||||
|
<Spritesheet Id="0" Path="meatboy.png">
|
||||||
|
<Region Id="0" Name="Head" XCrop="1" YCrop="1" Width="41" Height="33" Origin="Center"/>
|
||||||
|
<Region Id="1" Name="Arms" XCrop="1" YCrop="36" Width="24" Height="12" Origin="Center"/>
|
||||||
|
<Region Id="2" Name="Legs" XCrop="27" YCrop="36" Width="31" Height="9" Origin="Center"/>
|
||||||
|
</Spritesheet>
|
||||||
|
</Spritesheets>
|
||||||
|
<Layers>
|
||||||
|
<Layer Id="0" Name="Head" SpritesheetId="0"/>
|
||||||
|
<Layer Id="1" Name="Arms" SpritesheetId="0"/>
|
||||||
|
<Layer Id="2" Name="Legs" SpritesheetId="0"/>
|
||||||
|
</Layers>
|
||||||
|
<Nulls/>
|
||||||
|
<Events/>
|
||||||
|
</Content>
|
||||||
|
<Animations DefaultAnimation="Main">
|
||||||
|
<Animation Name="Main" FrameNum="14" Loop="true">
|
||||||
|
<RootAnimation>
|
||||||
|
<Frame XPosition="0" YPosition="0" Delay="14" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="false"/>
|
||||||
|
</RootAnimation>
|
||||||
|
<LayerAnimations>
|
||||||
|
<LayerAnimation LayerId="2" Visible="true">
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="4" XCrop="27" YCrop="36" Width="31" Height="9" XPosition="1" YPosition="-5" Delay="7" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="-1" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="4" XCrop="27" YCrop="36" Width="31" Height="9" XPosition="1" YPosition="-5" Delay="6" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="1" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="4" XCrop="27" YCrop="36" Width="31" Height="9" XPosition="1" YPosition="-5" Delay="1" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
<LayerAnimation LayerId="0" Visible="true">
|
||||||
|
<Frame RegionId="0" XPivot="20" YPivot="16" XCrop="1" YCrop="1" Width="41" Height="33" XPosition="2" YPosition="-23" Delay="7" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="0" XPivot="20" YPivot="16" XCrop="1" YCrop="1" Width="41" Height="33" XPosition="0" YPosition="-23" Delay="6" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="0" XPivot="20" YPivot="16" XCrop="1" YCrop="1" Width="41" Height="33" XPosition="2" YPosition="-23" Delay="1" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
<LayerAnimation LayerId="1" Visible="true">
|
||||||
|
<Frame RegionId="1" XPivot="12" YPivot="6" XCrop="1" YCrop="36" Width="24" Height="12" XPosition="-12" YPosition="-14" Delay="3" Visible="true" XScale="95" YScale="95" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="8" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="12" YPivot="6" XCrop="1" YCrop="36" Width="24" Height="12" XPosition="0" YPosition="-16" Delay="4" Visible="true" XScale="125" YScale="125" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="12" YPivot="6" XCrop="1" YCrop="36" Width="24" Height="12" XPosition="12" YPosition="-14" Delay="3" Visible="true" XScale="95" YScale="95" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="-8" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="12" YPivot="6" XCrop="1" YCrop="36" Width="24" Height="12" XPosition="0" YPosition="-16" Delay="3" Visible="true" XScale="125" YScale="125" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="12" YPivot="6" XCrop="1" YCrop="36" Width="24" Height="12" XPosition="-12" YPosition="-14" Delay="1" Visible="true" XScale="95" YScale="95" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="8" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
</LayerAnimations>
|
||||||
|
<NullAnimations/>
|
||||||
|
<Triggers/>
|
||||||
|
</Animation>
|
||||||
|
</Animations>
|
||||||
|
</AnimatedActor>
|
||||||
|
|
||||||
|
)ANM2ED_FRIEND";
|
||||||
|
|
||||||
|
inline constexpr unsigned char ISAAC_PNG[] = {
|
||||||
|
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||||
|
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x47,
|
||||||
|
0x08, 0x06, 0x00, 0x00, 0x00, 0x5b, 0x19, 0x24, 0x70, 0x00, 0x00, 0x05,
|
||||||
|
0x6d, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x63, 0x18, 0x69, 0x80, 0x91,
|
||||||
|
0x0c, 0x0f, 0xff, 0x27, 0xa0, 0x87, 0x71, 0x30, 0x07, 0x22, 0x29, 0x8e,
|
||||||
|
0xfb, 0x4f, 0xa2, 0x47, 0x06, 0xa5, 0xc7, 0x89, 0x71, 0x14, 0x8a, 0x47,
|
||||||
|
0x3b, 0x23, 0xa3, 0x19, 0x9c, 0x1d, 0xec, 0xb0, 0xfa, 0x7d, 0xef, 0x81,
|
||||||
|
0x43, 0x0c, 0xe5, 0xcb, 0x97, 0xa2, 0xcb, 0x0d, 0x2a, 0x8f, 0x13, 0x72,
|
||||||
|
0x0c, 0xdc, 0xb3, 0xf8, 0x3c, 0x8a, 0xee, 0x43, 0x2c, 0x1e, 0x1f, 0x34,
|
||||||
|
0x9e, 0xc6, 0xe7, 0x10, 0x8c, 0x24, 0x4c, 0x8c, 0xa7, 0x71, 0xc4, 0x32,
|
||||||
|
0x28, 0x4c, 0x06, 0x85, 0xa7, 0x71, 0x39, 0x02, 0xec, 0xd9, 0xff, 0xff,
|
||||||
|
0x21, 0x7e, 0x66, 0x64, 0x44, 0x28, 0x3b, 0x33, 0x73, 0x26, 0xde, 0xac,
|
||||||
|
0x6c, 0x92, 0x9e, 0xce, 0x80, 0x4d, 0x1f, 0x54, 0xd3, 0x80, 0x7b, 0x9a,
|
||||||
|
0x09, 0x8b, 0xeb, 0xff, 0xd3, 0xb0, 0x94, 0xfd, 0x3f, 0x18, 0x4b, 0x70,
|
||||||
|
0x90, 0xa3, 0xfe, 0x27, 0x19, 0x5b, 0x80, 0x69, 0xa0, 0x03, 0xe1, 0x34,
|
||||||
|
0x48, 0x0c, 0x18, 0xc3, 0x18, 0xe2, 0x30, 0x35, 0x20, 0x39, 0x5c, 0xfa,
|
||||||
|
0x90, 0xcc, 0x19, 0x50, 0x3f, 0xa3, 0x27, 0x31, 0x70, 0x0c, 0x10, 0xca,
|
||||||
|
0xab, 0xa0, 0x64, 0x5b, 0x5f, 0x5f, 0xcf, 0xd0, 0xd0, 0xd0, 0x00, 0x76,
|
||||||
|
0x3c, 0x88, 0x6e, 0x6c, 0x6c, 0x64, 0xc0, 0x97, 0xdc, 0xd1, 0xf2, 0xf6,
|
||||||
|
0x80, 0x25, 0x6d, 0xac, 0x1e, 0x26, 0x26, 0x9f, 0x62, 0x8b, 0x26, 0x12,
|
||||||
|
0xf4, 0x0d, 0x98, 0x87, 0x91, 0xf3, 0x30, 0x3c, 0x76, 0x09, 0xa5, 0x39,
|
||||||
|
0x50, 0x0a, 0x40, 0x57, 0x83, 0x4d, 0x0c, 0x8f, 0x9a, 0x01, 0xcb, 0xcb,
|
||||||
|
0xc8, 0x21, 0x8d, 0xe2, 0x08, 0x42, 0xb1, 0x45, 0x6a, 0x46, 0x04, 0x65,
|
||||||
|
0x03, 0x34, 0x3d, 0x03, 0x12, 0xcb, 0x2c, 0x50, 0x47, 0x80, 0x3d, 0x0b,
|
||||||
|
0xf3, 0x24, 0x28, 0xbf, 0x81, 0x1c, 0x48, 0x2d, 0x4f, 0x83, 0xcc, 0x42,
|
||||||
|
0x2e, 0x17, 0xa0, 0x9e, 0x07, 0xd9, 0x49, 0x77, 0x4f, 0x63, 0xab, 0x96,
|
||||||
|
0xe0, 0x4d, 0x47, 0x2c, 0xb1, 0xc2, 0x40, 0x6e, 0xcc, 0xe2, 0x6a, 0x8e,
|
||||||
|
0xd2, 0xbb, 0xc8, 0x46, 0xf1, 0x30, 0x28, 0x66, 0x61, 0x0e, 0x80, 0xc5,
|
||||||
|
0x2e, 0x25, 0x9e, 0x86, 0xe9, 0x45, 0x4e, 0x29, 0xc8, 0x76, 0x0c, 0x44,
|
||||||
|
0xfd, 0x84, 0x91, 0x87, 0xd1, 0xab, 0x24, 0x6c, 0x8e, 0x26, 0xc6, 0xa1,
|
||||||
|
0xb8, 0x3c, 0x8b, 0xd4, 0xb9, 0x18, 0x90, 0x3c, 0x8c, 0x1c, 0xc3, 0x60,
|
||||||
|
0x07, 0x80, 0x1c, 0x84, 0x2b, 0xa6, 0x89, 0x89, 0x1d, 0x58, 0xfe, 0x07,
|
||||||
|
0x05, 0x0a, 0x7a, 0xcc, 0x0e, 0xb4, 0x67, 0x41, 0x6e, 0xc2, 0x16, 0xca,
|
||||||
|
0x58, 0x1b, 0x1f, 0xb0, 0x18, 0x23, 0xb6, 0x7b, 0x38, 0x18, 0x3d, 0x8b,
|
||||||
|
0xcb, 0xc3, 0x20, 0x71, 0x82, 0x9e, 0xc6, 0x96, 0xac, 0x61, 0x31, 0x38,
|
||||||
|
0x58, 0x3d, 0x8b, 0xcf, 0xc3, 0x38, 0x3d, 0x0d, 0x92, 0xc0, 0x95, 0xb4,
|
||||||
|
0xd1, 0x4b, 0xe2, 0xc1, 0xd2, 0x9c, 0x44, 0x8e, 0x1c, 0x42, 0x05, 0x07,
|
||||||
|
0x51, 0x6d, 0x6b, 0x6c, 0xb1, 0x3d, 0x18, 0x3d, 0x4b, 0x28, 0x86, 0x61,
|
||||||
|
0xfe, 0x20, 0xd9, 0xd3, 0x83, 0xd5, 0xb3, 0xc4, 0x7a, 0x18, 0x9e, 0xbc,
|
||||||
|
0x89, 0x6d, 0x79, 0x21, 0xd5, 0xdd, 0x03, 0xd6, 0x49, 0xc0, 0x55, 0x75,
|
||||||
|
0x32, 0x31, 0x8c, 0x30, 0x40, 0x8c, 0x87, 0x89, 0xee, 0x45, 0xc1, 0xc2,
|
||||||
|
0x0e, 0xa9, 0xe7, 0x34, 0xe8, 0x46, 0x38, 0x88, 0x8e, 0x61, 0x52, 0xda,
|
||||||
|
0xc2, 0x83, 0xa5, 0xdd, 0x8c, 0x2d, 0xf1, 0x8e, 0x26, 0x69, 0xb4, 0x50,
|
||||||
|
0x21, 0x39, 0x39, 0x0f, 0xf6, 0x64, 0x4d, 0x54, 0x3d, 0x8c, 0x5c, 0x3a,
|
||||||
|
0x4f, 0x9b, 0x35, 0x9f, 0x61, 0xde, 0xd9, 0x13, 0x58, 0x8b, 0x3a, 0xe0,
|
||||||
|
0x00, 0x1e, 0x43, 0x56, 0x5a, 0x22, 0x5c, 0x6e, 0x30, 0x96, 0xd6, 0x24,
|
||||||
|
0x27, 0x69, 0x75, 0x35, 0x65, 0xf4, 0x86, 0x0b, 0x3c, 0xd0, 0xd0, 0xe4,
|
||||||
|
0x06, 0x65, 0xf9, 0x4f, 0x94, 0x87, 0xc9, 0xe9, 0xc3, 0x0e, 0x74, 0xbf,
|
||||||
|
0x17, 0x57, 0x68, 0x13, 0xd3, 0x30, 0xc0, 0x55, 0xb5, 0x30, 0x62, 0xcb,
|
||||||
|
0xef, 0x58, 0x2c, 0x1a, 0x54, 0x8d, 0x0f, 0x62, 0x1d, 0x83, 0xee, 0x69,
|
||||||
|
0x5c, 0xfa, 0x88, 0x55, 0xc7, 0x30, 0x0a, 0x46, 0x43, 0x80, 0x36, 0x21,
|
||||||
|
0x40, 0x6a, 0xfe, 0x22, 0xd4, 0x54, 0xa4, 0x55, 0x7e, 0xa5, 0x9a, 0xbd,
|
||||||
|
0xe4, 0xe6, 0x61, 0x42, 0xc1, 0x4f, 0x2d, 0x8f, 0x93, 0xda, 0x16, 0x67,
|
||||||
|
0xa4, 0xd4, 0x61, 0x28, 0x16, 0xd2, 0x71, 0xb9, 0x03, 0xcd, 0xec, 0xc5,
|
||||||
|
0x17, 0x22, 0x70, 0x4b, 0xe9, 0xbc, 0xdc, 0x81, 0xa6, 0xf6, 0xe2, 0xad,
|
||||||
|
0x5e, 0x48, 0xf1, 0x28, 0x7a, 0x52, 0x22, 0x73, 0xd4, 0x03, 0xde, 0x76,
|
||||||
|
0x27, 0xb7, 0xc7, 0x45, 0xc8, 0x5e, 0x6c, 0x1e, 0xa6, 0xd8, 0x52, 0x98,
|
||||||
|
0xe7, 0x49, 0xf4, 0x34, 0x5d, 0xec, 0x65, 0xc4, 0xd6, 0x5a, 0xa2, 0x24,
|
||||||
|
0x66, 0xc9, 0x8c, 0x69, 0xaa, 0x79, 0x96, 0x50, 0x60, 0xe3, 0x9d, 0x4c,
|
||||||
|
0xa3, 0x46, 0x4d, 0x38, 0x50, 0x03, 0x07, 0xb8, 0xec, 0x25, 0x6b, 0x42,
|
||||||
|
0x9c, 0xd4, 0x80, 0x20, 0x30, 0xe4, 0x43, 0x76, 0x9f, 0x9b, 0x90, 0x3b,
|
||||||
|
0xb0, 0xd9, 0x8b, 0x11, 0xc3, 0x2e, 0xd0, 0x55, 0x76, 0xd4, 0x6c, 0x41,
|
||||||
|
0xb8, 0xe0, 0x58, 0xb9, 0x87, 0xec, 0x60, 0x62, 0xd4, 0x10, 0x1b, 0xd0,
|
||||||
|
0x30, 0xb7, 0x63, 0x33, 0x13, 0xe6, 0x61, 0x70, 0x28, 0x83, 0x3a, 0xf0,
|
||||||
|
0x30, 0x43, 0xff, 0x53, 0xb9, 0x65, 0x87, 0x64, 0x36, 0xb2, 0xd1, 0x18,
|
||||||
|
0xf6, 0x52, 0xc3, 0x5a, 0x64, 0x0b, 0xd0, 0xed, 0x65, 0x41, 0xb6, 0x00,
|
||||||
|
0xd4, 0x81, 0x9f, 0x8a, 0x65, 0x44, 0x83, 0x1a, 0x85, 0x18, 0x78, 0x70,
|
||||||
|
0x00, 0xc7, 0x48, 0x09, 0x35, 0x06, 0x0e, 0xf6, 0x62, 0x59, 0xe7, 0x09,
|
||||||
|
0xf2, 0x2c, 0xba, 0xbd, 0x18, 0x49, 0x1a, 0x34, 0x7c, 0x03, 0x5a, 0x49,
|
||||||
|
0x07, 0x5b, 0x4d, 0x07, 0x0a, 0x10, 0x2c, 0x0b, 0x46, 0x19, 0x06, 0x1b,
|
||||||
|
0x00, 0xb9, 0x11, 0xdd, 0xdd, 0xd8, 0x86, 0xa2, 0x46, 0xf6, 0xa8, 0x25,
|
||||||
|
0x2c, 0x26, 0x41, 0x6b, 0x2b, 0x91, 0xd7, 0x57, 0x52, 0x23, 0x36, 0x6f,
|
||||||
|
0xde, 0xba, 0x8b, 0xd3, 0x18, 0x7c, 0x72, 0xa4, 0xd8, 0x8d, 0xcd, 0xdd,
|
||||||
|
0xe8, 0xa9, 0x13, 0x96, 0x87, 0x41, 0x05, 0x1b, 0xbc, 0x00, 0x41, 0x4f,
|
||||||
|
0x0a, 0xc8, 0x85, 0x19, 0xba, 0x03, 0xb0, 0xe5, 0x1d, 0xe4, 0x3c, 0x0f,
|
||||||
|
0x2b, 0x31, 0x91, 0xcc, 0x44, 0xae, 0x00, 0xc0, 0xf6, 0x82, 0xe4, 0xb2,
|
||||||
|
0x19, 0x12, 0x19, 0xe0, 0x8e, 0x00, 0x5a, 0x42, 0xc8, 0x5c, 0x74, 0x77,
|
||||||
|
0x80, 0xdc, 0x88, 0xcd, 0xdd, 0xe8, 0xf6, 0x22, 0x5b, 0x0e, 0xaf, 0x0f,
|
||||||
|
0x41, 0xc5, 0x39, 0xb1, 0xa5, 0x34, 0xae, 0xd5, 0xb3, 0xb0, 0xa1, 0x5d,
|
||||||
|
0x90, 0x05, 0x7b, 0x50, 0x0b, 0x14, 0x9c, 0xad, 0x3b, 0x64, 0x7b, 0x09,
|
||||||
|
0x99, 0x4b, 0x28, 0xe6, 0x71, 0xd9, 0x8b, 0x5c, 0x4a, 0x83, 0x03, 0x18,
|
||||||
|
0x94, 0x04, 0xce, 0x22, 0xd5, 0x9b, 0xe8, 0xab, 0x78, 0xc8, 0x29, 0xb1,
|
||||||
|
0x09, 0xac, 0xed, 0xc0, 0x6a, 0x2f, 0x31, 0x49, 0x19, 0x5b, 0x2a, 0x40,
|
||||||
|
0x1e, 0x43, 0xc7, 0x66, 0x2f, 0xd6, 0x42, 0x0b, 0x14, 0x23, 0xc8, 0x16,
|
||||||
|
0x82, 0x16, 0x8f, 0xc2, 0x4a, 0x40, 0x90, 0x21, 0xa0, 0x40, 0x40, 0x0e,
|
||||||
|
0x08, 0x7c, 0x79, 0x1e, 0xdd, 0x2c, 0x7c, 0x1e, 0x41, 0x57, 0x8b, 0xcb,
|
||||||
|
0x5c, 0x98, 0xfd, 0xc8, 0x25, 0x33, 0x6c, 0xa1, 0x2b, 0xcc, 0x7c, 0x5c,
|
||||||
|
0xf6, 0xa2, 0x7b, 0x98, 0x11, 0x56, 0x0d, 0xc1, 0xc6, 0x95, 0x41, 0x31,
|
||||||
|
0x0a, 0x32, 0x0c, 0x66, 0x39, 0xc8, 0xe3, 0xc8, 0x86, 0x63, 0xcb, 0xdf,
|
||||||
|
0xb0, 0x26, 0x1d, 0x09, 0xbd, 0x25, 0xac, 0xf6, 0x62, 0xcb, 0xa7, 0x30,
|
||||||
|
0x31, 0x58, 0x24, 0xc0, 0xdc, 0x05, 0xe2, 0x13, 0x63, 0x2f, 0x23, 0x8e,
|
||||||
|
0x10, 0x87, 0xe7, 0x67, 0x50, 0x23, 0x9c, 0xd4, 0x02, 0x84, 0x01, 0xb3,
|
||||||
|
0xd0, 0x61, 0x64, 0x20, 0x0e, 0xa0, 0xd8, 0x8b, 0x4b, 0x0b, 0x3e, 0xf7,
|
||||||
|
0x90, 0xd3, 0x1f, 0x06, 0xd9, 0x83, 0x52, 0x66, 0x0d, 0xd1, 0x11, 0x0f,
|
||||||
|
0x90, 0x3f, 0x30, 0x02, 0x1a, 0x5b, 0xc8, 0x83, 0x3d, 0x0b, 0xca, 0xfc,
|
||||||
|
0xc8, 0xf9, 0x14, 0x96, 0x74, 0x71, 0x35, 0x03, 0x41, 0x75, 0x29, 0x96,
|
||||||
|
0x96, 0x0d, 0xb1, 0x31, 0x8b, 0x1e, 0x99, 0x28, 0x01, 0x0e, 0x6f, 0x22,
|
||||||
|
0x62, 0x89, 0x72, 0x58, 0x1d, 0x8e, 0x6c, 0x37, 0x9a, 0xdb, 0xf1, 0xba,
|
||||||
|
0x01, 0x64, 0xd1, 0x7f, 0xa0, 0x06, 0x30, 0x06, 0x9a, 0xff, 0x1f, 0x18,
|
||||||
|
0xbb, 0x60, 0x31, 0x10, 0x9b, 0x44, 0xcc, 0x40, 0x21, 0x20, 0xd9, 0x5e,
|
||||||
|
0x98, 0x5b, 0x91, 0xdd, 0x0f, 0x75, 0x33, 0xdc, 0x29, 0x18, 0xf5, 0x30,
|
||||||
|
0xf2, 0xa2, 0x52, 0x42, 0x49, 0x19, 0x94, 0x02, 0x90, 0xab, 0x01, 0x1a,
|
||||||
|
0x4c, 0x8f, 0xc2, 0x53, 0x1b, 0xcc, 0xc5, 0xe8, 0x76, 0xa2, 0x07, 0x2a,
|
||||||
|
0x2c, 0x0f, 0x63, 0x59, 0x1c, 0x0b, 0xf6, 0x2b, 0xd6, 0x6a, 0x09, 0x64,
|
||||||
|
0x28, 0xa9, 0x9e, 0x85, 0x95, 0xea, 0x0c, 0x34, 0x00, 0xc8, 0x66, 0xa3,
|
||||||
|
0x67, 0x35, 0x74, 0xeb, 0x40, 0x85, 0x2c, 0xc8, 0xed, 0xe8, 0xed, 0x07,
|
||||||
|
0x98, 0x3a, 0xf4, 0xf4, 0x4d, 0x54, 0x29, 0x89, 0x1e, 0xca, 0x64, 0x8e,
|
||||||
|
0x50, 0x12, 0x1b, 0x34, 0x58, 0xdd, 0x44, 0x6c, 0x4c, 0x43, 0x2d, 0x81,
|
||||||
|
0xfb, 0x13, 0xef, 0x98, 0x16, 0xb6, 0x58, 0x23, 0xe0, 0x59, 0x06, 0x5a,
|
||||||
|
0x01, 0x6c, 0xab, 0x7c, 0xb1, 0xc5, 0x22, 0xcc, 0xcd, 0xc4, 0x8c, 0x69,
|
||||||
|
0x61, 0xb8, 0x15, 0xdd, 0x12, 0x5c, 0xf9, 0x05, 0x56, 0xe1, 0x33, 0xd0,
|
||||||
|
0x10, 0x80, 0xec, 0x20, 0xd6, 0x3d, 0xf8, 0x9c, 0x81, 0xb3, 0xd0, 0x02,
|
||||||
|
0x69, 0xc2, 0x95, 0x0f, 0x90, 0x0d, 0x1c, 0x88, 0x42, 0x8b, 0x50, 0xb8,
|
||||||
|
0xe2, 0x73, 0xd3, 0xe8, 0xb2, 0x25, 0x58, 0xe8, 0x21, 0xe5, 0x5f, 0x50,
|
||||||
|
0x2a, 0xc0, 0x86, 0x51, 0x02, 0x9a, 0x5e, 0xa5, 0x34, 0x92, 0xa5, 0x38,
|
||||||
|
0xdd, 0x85, 0xcf, 0x2d, 0x58, 0x4b, 0x69, 0xb4, 0x24, 0x83, 0xaf, 0xa5,
|
||||||
|
0x82, 0xad, 0xdb, 0xcc, 0x48, 0xe5, 0xac, 0x4c, 0xaa, 0x1d, 0x78, 0xd5,
|
||||||
|
0x63, 0x73, 0xdc, 0x7f, 0xb4, 0x50, 0x24, 0xe4, 0x7e, 0x52, 0xd5, 0x93,
|
||||||
|
0x13, 0x1e, 0x83, 0xd1, 0x4d, 0x0c, 0x43, 0x02, 0x00, 0x00, 0x30, 0x26,
|
||||||
|
0x02, 0xcf, 0x40, 0xc8, 0xf9, 0x54, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
|
||||||
|
0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::string_view ISAAC_ANM2 = R"ANM2ED_FRIEND(
|
||||||
|
<AnimatedActor>
|
||||||
|
<Info CreatedBy="robot" CreatedOn="05/21/2026 11:54:09 PM" Fps="30" Version="0"/>
|
||||||
|
<Content>
|
||||||
|
<Spritesheets>
|
||||||
|
<Spritesheet Id="0" Path="isaac.png">
|
||||||
|
<Region Id="0" Name="1" XCrop="1" YCrop="36" Width="28" Height="34" XPivot="14" YPivot="34"/>
|
||||||
|
<Region Id="1" Name="2" XCrop="1" YCrop="1" Width="30" Height="33" XPivot="15" YPivot="33"/>
|
||||||
|
<Region Id="2" Name="3" XCrop="31" YCrop="36" Width="28" Height="34" XPivot="15" YPivot="34"/>
|
||||||
|
</Spritesheet>
|
||||||
|
</Spritesheets>
|
||||||
|
<Layers>
|
||||||
|
<Layer Id="0" Name="Main" SpritesheetId="0"/>
|
||||||
|
</Layers>
|
||||||
|
<Nulls/>
|
||||||
|
<Events/>
|
||||||
|
</Content>
|
||||||
|
<Animations DefaultAnimation="Main">
|
||||||
|
<Animation Name="Main" FrameNum="14" Loop="true">
|
||||||
|
<RootAnimation>
|
||||||
|
<Frame XPosition="0" YPosition="0" Delay="14" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="false"/>
|
||||||
|
</RootAnimation>
|
||||||
|
<LayerAnimations>
|
||||||
|
<LayerAnimation LayerId="0" Visible="true">
|
||||||
|
<Frame RegionId="0" XPivot="14" YPivot="34" XCrop="1" YCrop="36" Width="28" Height="34" XPosition="2" YPosition="0" Delay="5" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="15" YPivot="33" XCrop="1" YCrop="1" Width="30" Height="33" XPosition="2" YPosition="0" Delay="2" Visible="true" XScale="110" YScale="90" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="34" XCrop="31" YCrop="36" Width="28" Height="34" XPosition="2" YPosition="0" Delay="5" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="15" YPivot="33" XCrop="1" YCrop="1" Width="30" Height="33" XPosition="2" YPosition="0" Delay="2" Visible="true" XScale="110" YScale="90" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
</LayerAnimations>
|
||||||
|
<NullAnimations/>
|
||||||
|
<Triggers/>
|
||||||
|
</Animation>
|
||||||
|
</Animations>
|
||||||
|
</AnimatedActor>
|
||||||
|
|
||||||
|
)ANM2ED_FRIEND";
|
||||||
|
|
||||||
|
inline constexpr unsigned char STACY_PNG[] = {
|
||||||
|
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||||
|
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x44,
|
||||||
|
0x08, 0x06, 0x00, 0x00, 0x00, 0x35, 0x0d, 0xe3, 0xf5, 0x00, 0x00, 0x05,
|
||||||
|
0xe9, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x63, 0x18, 0x05, 0x90, 0x10,
|
||||||
|
0x60, 0xa4, 0x20, 0x20, 0xfe, 0x23, 0xe9, 0x65, 0x1c, 0x80, 0x00, 0xfd,
|
||||||
|
0x4f, 0xc0, 0x4e, 0x92, 0xdc, 0x84, 0xac, 0x98, 0x14, 0x8f, 0xa1, 0x3b,
|
||||||
|
0x82, 0x5e, 0x01, 0xf1, 0x9f, 0xcc, 0x00, 0x27, 0xe8, 0x3e, 0x5c, 0x01,
|
||||||
|
0x01, 0xb2, 0x0f, 0x97, 0x66, 0xb0, 0x63, 0x3c, 0x3d, 0x3d, 0x19, 0xb6,
|
||||||
|
0x6f, 0xdf, 0x0e, 0x73, 0x17, 0x3d, 0x02, 0x02, 0x25, 0x10, 0x54, 0x54,
|
||||||
|
0x54, 0xf0, 0x86, 0xc9, 0x9d, 0x3b, 0x77, 0xd0, 0xe5, 0xf1, 0xba, 0x91,
|
||||||
|
0x09, 0x5d, 0x35, 0xc8, 0x83, 0x50, 0xb1, 0xff, 0x48, 0x34, 0x88, 0x0d,
|
||||||
|
0xc3, 0x0c, 0x33, 0x66, 0xcc, 0xa0, 0x77, 0x4e, 0x00, 0xbb, 0x05, 0xe4,
|
||||||
|
0x79, 0x18, 0x26, 0xe4, 0x00, 0x2c, 0x6a, 0xf1, 0xa6, 0x26, 0x26, 0x6c,
|
||||||
|
0x06, 0x22, 0x79, 0x14, 0xab, 0xe6, 0x8c, 0x8c, 0x0c, 0x72, 0x03, 0x02,
|
||||||
|
0x39, 0x40, 0xff, 0x33, 0x0c, 0x22, 0xc0, 0x82, 0xcd, 0x2d, 0x30, 0x8f,
|
||||||
|
0x82, 0x52, 0x87, 0xbf, 0xbf, 0x3f, 0x86, 0x92, 0x8d, 0x1b, 0x37, 0x22,
|
||||||
|
0x67, 0x0b, 0x62, 0xbc, 0x43, 0x35, 0x4f, 0xab, 0xaa, 0xaa, 0x92, 0x14,
|
||||||
|
0x7c, 0xb7, 0x6f, 0xdf, 0x26, 0x4a, 0x3d, 0x72, 0x8a, 0x00, 0xe7, 0x21,
|
||||||
|
0x58, 0xbe, 0xc7, 0x15, 0x08, 0xa0, 0x40, 0x02, 0xa9, 0x41, 0xca, 0x42,
|
||||||
|
0xf8, 0x2c, 0x82, 0x67, 0x27, 0x90, 0x22, 0x58, 0x4a, 0x43, 0xca, 0xdf,
|
||||||
|
0xc4, 0x04, 0x10, 0x3c, 0x5b, 0x90, 0x1a, 0x08, 0x20, 0x3b, 0x41, 0x7a,
|
||||||
|
0x88, 0xb1, 0x8f, 0x05, 0x97, 0x2f, 0xb0, 0xa5, 0x04, 0x64, 0xb5, 0x20,
|
||||||
|
0x79, 0x10, 0x86, 0xa6, 0x1e, 0xbc, 0x1e, 0x82, 0x05, 0x00, 0x48, 0x2d,
|
||||||
|
0xc8, 0x51, 0x20, 0xc7, 0x61, 0x29, 0xcc, 0xf0, 0xc6, 0x5c, 0x49, 0x49,
|
||||||
|
0x09, 0x8a, 0x3c, 0x28, 0x55, 0xe2, 0xd3, 0x80, 0xee, 0x7e, 0x42, 0xd9,
|
||||||
|
0x19, 0x6b, 0x40, 0x80, 0x62, 0x1b, 0xa6, 0x11, 0xbd, 0x60, 0x24, 0xa5,
|
||||||
|
0xa0, 0x44, 0x4e, 0x55, 0xc8, 0x81, 0xc0, 0x40, 0x05, 0x40, 0x28, 0xa2,
|
||||||
|
0x48, 0xb5, 0x02, 0x6b, 0x61, 0x89, 0xcd, 0x12, 0xe4, 0x10, 0x45, 0x8f,
|
||||||
|
0x0d, 0x90, 0x87, 0x41, 0x01, 0x04, 0xc2, 0xc8, 0x59, 0x06, 0x94, 0x85,
|
||||||
|
0x40, 0x6a, 0xa9, 0x1d, 0x08, 0x84, 0x52, 0x03, 0x28, 0x10, 0x88, 0x51,
|
||||||
|
0x83, 0x1c, 0x58, 0x4c, 0xb8, 0x42, 0x0e, 0xe6, 0x31, 0x64, 0x79, 0x90,
|
||||||
|
0x87, 0x40, 0x18, 0x16, 0x50, 0x20, 0x36, 0x7a, 0x59, 0x02, 0x92, 0x43,
|
||||||
|
0x0e, 0x10, 0x58, 0x99, 0x43, 0x62, 0xfe, 0x46, 0xa9, 0xae, 0xd1, 0xdd,
|
||||||
|
0x88, 0xd4, 0x7e, 0xc1, 0x19, 0xf1, 0x78, 0xd4, 0x60, 0x35, 0x1b, 0x6b,
|
||||||
|
0xd6, 0x00, 0x85, 0x26, 0xc8, 0x43, 0xc8, 0xb5, 0x03, 0x7a, 0x96, 0x00,
|
||||||
|
0xc9, 0xe1, 0xcb, 0x26, 0xb0, 0x32, 0x04, 0x66, 0x06, 0xa8, 0xf4, 0x26,
|
||||||
|
0x32, 0x30, 0x30, 0xca, 0x1b, 0xe4, 0x54, 0x46, 0x4a, 0x4c, 0xc3, 0xfc,
|
||||||
|
0x01, 0x0a, 0x2d, 0xb4, 0x06, 0x20, 0x2c, 0x00, 0x41, 0x76, 0x81, 0x2b,
|
||||||
|
0x09, 0x6c, 0xad, 0x2d, 0xb8, 0x43, 0xa8, 0xd5, 0x70, 0x82, 0x05, 0x06,
|
||||||
|
0xac, 0xa0, 0x04, 0xb9, 0x02, 0x47, 0xab, 0x14, 0x6c, 0x37, 0xb2, 0xbd,
|
||||||
|
0xa0, 0x54, 0x87, 0xce, 0x07, 0xe9, 0x27, 0xe4, 0x36, 0x6c, 0x65, 0x1c,
|
||||||
|
0x2e, 0xb3, 0x80, 0xe6, 0x31, 0x62, 0xcb, 0x1a, 0xf0, 0xc0, 0xa1, 0xa0,
|
||||||
|
0xe1, 0x84, 0x92, 0x64, 0x41, 0xa9, 0x03, 0x14, 0x23, 0xa0, 0x9a, 0x02,
|
||||||
|
0x94, 0x32, 0xa8, 0xd1, 0x34, 0xc7, 0x97, 0x32, 0x48, 0x2d, 0x1f, 0x40,
|
||||||
|
0x8e, 0xc5, 0x59, 0x7d, 0xc2, 0x92, 0x13, 0xb6, 0x72, 0x80, 0x81, 0x0c,
|
||||||
|
0x00, 0x2b, 0x57, 0x88, 0xc9, 0xdf, 0xc4, 0x44, 0x00, 0xc8, 0x1c, 0x62,
|
||||||
|
0xcc, 0x42, 0x77, 0x2a, 0x2e, 0xb3, 0x99, 0x08, 0xf9, 0x09, 0x94, 0x04,
|
||||||
|
0xa9, 0x55, 0x55, 0xc1, 0x52, 0x06, 0x1e, 0x3b, 0xb1, 0x76, 0x8c, 0x60,
|
||||||
|
0x31, 0x4c, 0x4e, 0x4c, 0x13, 0xa1, 0x17, 0x67, 0x19, 0x01, 0x72, 0x27,
|
||||||
|
0x4a, 0x5e, 0x45, 0x0f, 0x45, 0x62, 0xcb, 0x0e, 0x5c, 0xfa, 0x90, 0xc4,
|
||||||
|
0x89, 0xe9, 0xb5, 0x62, 0x6b, 0xac, 0x11, 0xdb, 0xdb, 0x25, 0x5a, 0x2f,
|
||||||
|
0xb6, 0x14, 0x01, 0x6f, 0xd2, 0x82, 0x42, 0x04, 0xe4, 0xe8, 0xff, 0xff,
|
||||||
|
0xff, 0x33, 0x80, 0x30, 0x2c, 0x26, 0x89, 0x49, 0xba, 0xf8, 0xf4, 0x91,
|
||||||
|
0xd8, 0xc4, 0x46, 0xf7, 0x34, 0x29, 0x5d, 0x7e, 0xa2, 0xf5, 0xe2, 0xcc,
|
||||||
|
0x1a, 0xe4, 0xb4, 0xeb, 0x89, 0x2d, 0x3a, 0xc8, 0x30, 0x1b, 0xe4, 0x21,
|
||||||
|
0x18, 0x26, 0xb5, 0x84, 0x22, 0x4a, 0x2f, 0x0b, 0x31, 0xa6, 0x32, 0x32,
|
||||||
|
0x92, 0x37, 0xee, 0x42, 0xae, 0x3e, 0x86, 0x01, 0x00, 0x44, 0x15, 0x96,
|
||||||
|
0xe8, 0xee, 0x22, 0xa6, 0x8c, 0xc0, 0xa6, 0x86, 0x84, 0x76, 0x09, 0xde,
|
||||||
|
0x96, 0x25, 0x2d, 0xc2, 0x09, 0x67, 0x8a, 0x40, 0xee, 0xc7, 0x93, 0xdb,
|
||||||
|
0xb0, 0xc2, 0xa5, 0x8f, 0xc0, 0x18, 0x01, 0x7a, 0x01, 0x07, 0x6f, 0xfd,
|
||||||
|
0xd1, 0x32, 0xa1, 0xe0, 0x4a, 0xf3, 0x60, 0xc7, 0x60, 0x1b, 0x93, 0x80,
|
||||||
|
0x15, 0x94, 0xe4, 0xb4, 0xec, 0x40, 0x1e, 0xd9, 0x88, 0x3a, 0xa8, 0x83,
|
||||||
|
0x6e, 0x3f, 0xd6, 0x96, 0x25, 0x34, 0x00, 0x18, 0x69, 0x19, 0x10, 0x78,
|
||||||
|
0xb3, 0x06, 0x7a, 0xcc, 0x61, 0x0b, 0x04, 0x90, 0x18, 0x32, 0x86, 0x39,
|
||||||
|
0x16, 0x16, 0x50, 0xe8, 0x35, 0x0c, 0xb1, 0x23, 0x46, 0x30, 0x73, 0xb0,
|
||||||
|
0x8c, 0xa1, 0xd2, 0x24, 0x3c, 0x70, 0x05, 0x04, 0x38, 0xf4, 0x41, 0x4d,
|
||||||
|
0x62, 0x7c, 0x8d, 0x18, 0x98, 0x27, 0x41, 0x8e, 0x85, 0x39, 0x18, 0x5f,
|
||||||
|
0xd5, 0x0a, 0x32, 0x0b, 0x69, 0x40, 0x86, 0xa8, 0x18, 0x46, 0x6b, 0x84,
|
||||||
|
0xfd, 0xa7, 0x55, 0xaa, 0xc0, 0xe7, 0x18, 0x78, 0x7b, 0x02, 0x54, 0xdd,
|
||||||
|
0x21, 0x77, 0xbd, 0x91, 0x1d, 0x83, 0x9e, 0x45, 0xd0, 0x03, 0x02, 0x26,
|
||||||
|
0x0f, 0x0a, 0x04, 0x50, 0x6a, 0x20, 0x10, 0x10, 0x38, 0xb3, 0x24, 0x81,
|
||||||
|
0x2c, 0x45, 0x71, 0xf8, 0x10, 0x8a, 0x15, 0x94, 0xc0, 0x00, 0xd9, 0x46,
|
||||||
|
0x6a, 0x73, 0x1b, 0x96, 0xa2, 0x88, 0x08, 0x04, 0x98, 0x67, 0x70, 0x06,
|
||||||
|
0x46, 0x4f, 0x4f, 0x0f, 0x03, 0xda, 0x10, 0x1f, 0xd5, 0xca, 0x0d, 0x62,
|
||||||
|
0x0c, 0xc2, 0x08, 0x0c, 0x98, 0x8b, 0x71, 0x05, 0x0a, 0x7a, 0x76, 0x22,
|
||||||
|
0x21, 0x10, 0xf0, 0x06, 0x06, 0x96, 0x54, 0x05, 0x52, 0x4f, 0x95, 0xc0,
|
||||||
|
0x20, 0xd6, 0x10, 0x78, 0xde, 0x44, 0x1e, 0x53, 0x20, 0x94, 0x1e, 0xd1,
|
||||||
|
0x02, 0x80, 0x54, 0x47, 0x63, 0x8d, 0x00, 0xf4, 0xc2, 0x16, 0x98, 0x42,
|
||||||
|
0xe8, 0x1a, 0x10, 0x20, 0x4f, 0x60, 0x14, 0x54, 0xd8, 0x02, 0x05, 0x8b,
|
||||||
|
0xe7, 0x61, 0xe1, 0x45, 0x8e, 0x83, 0x51, 0xec, 0xc4, 0x36, 0xcd, 0x37,
|
||||||
|
0x10, 0x01, 0x81, 0x92, 0x6c, 0x49, 0x28, 0x9d, 0x28, 0x8d, 0x31, 0x42,
|
||||||
|
0x35, 0x05, 0xdd, 0x53, 0x04, 0x36, 0xbf, 0xe3, 0x72, 0x24, 0xad, 0x1a,
|
||||||
|
0x3f, 0xd8, 0xec, 0xa3, 0x95, 0x5d, 0x0c, 0xa3, 0x60, 0x24, 0x87, 0x00,
|
||||||
|
0x25, 0xc9, 0x0a, 0x39, 0x99, 0x0e, 0xf9, 0xe4, 0x89, 0xdc, 0xfb, 0x24,
|
||||||
|
0xc5, 0x63, 0xff, 0x87, 0x5b, 0xea, 0xc1, 0xd5, 0xd7, 0xc0, 0xe7, 0x51,
|
||||||
|
0xb0, 0x1c, 0xf2, 0xa4, 0xcb, 0x70, 0x08, 0x94, 0xa1, 0xb2, 0x62, 0x86,
|
||||||
|
0xe6, 0x61, 0x3d, 0xba, 0x62, 0x06, 0x1a, 0xc4, 0x43, 0x6e, 0xc5, 0x0c,
|
||||||
|
0xad, 0x92, 0xc6, 0x50, 0x58, 0x31, 0x43, 0x97, 0x22, 0x08, 0xe7, 0x08,
|
||||||
|
0x15, 0xa1, 0xee, 0x36, 0x6c, 0xfa, 0x1f, 0xea, 0x4a, 0x50, 0x01, 0x8a,
|
||||||
|
0x0d, 0x83, 0xa5, 0x41, 0x63, 0x12, 0x20, 0x0c, 0x1a, 0xab, 0x20, 0xa5,
|
||||||
|
0xd3, 0x46, 0xcf, 0x42, 0x78, 0xc8, 0xae, 0x98, 0xa1, 0x76, 0x20, 0x61,
|
||||||
|
0x4d, 0x11, 0xd8, 0x52, 0x03, 0x28, 0x36, 0x71, 0xcd, 0x23, 0x82, 0xaa,
|
||||||
|
0x52, 0x58, 0xac, 0xd3, 0x63, 0xc5, 0x0c, 0x2d, 0x52, 0x0a, 0x7a, 0x8b,
|
||||||
|
0x10, 0xdc, 0x46, 0x40, 0x1f, 0x7e, 0x43, 0x1b, 0x26, 0x63, 0x40, 0x1e,
|
||||||
|
0x98, 0xc5, 0x36, 0xd2, 0x0d, 0x72, 0x28, 0xba, 0x1e, 0xf4, 0x76, 0x07,
|
||||||
|
0x9d, 0x57, 0xed, 0x12, 0x0c, 0x3b, 0xac, 0x01, 0x01, 0xf3, 0x1c, 0xb2,
|
||||||
|
0x67, 0x60, 0x1e, 0x01, 0x79, 0x00, 0x14, 0x10, 0x20, 0x39, 0x62, 0x86,
|
||||||
|
0xed, 0x60, 0x66, 0xa0, 0x97, 0x0d, 0x83, 0x3d, 0x20, 0x40, 0x21, 0x07,
|
||||||
|
0x6f, 0x55, 0x62, 0x1b, 0x92, 0x9f, 0x41, 0xc6, 0xf2, 0x63, 0x6c, 0x81,
|
||||||
|
0x31, 0x14, 0x02, 0x02, 0x6b, 0x60, 0x50, 0x9a, 0x2f, 0x91, 0x03, 0x83,
|
||||||
|
0xd4, 0x21, 0x7d, 0x7a, 0xd4, 0x1e, 0xcc, 0x38, 0x2c, 0x69, 0x00, 0x89,
|
||||||
|
0x83, 0xb2, 0xc3, 0x84, 0x09, 0x13, 0x18, 0xfe, 0xfe, 0xfd, 0xcb, 0xa0,
|
||||||
|
0xa1, 0xa1, 0x41, 0x91, 0x7b, 0x40, 0xfa, 0x41, 0xe6, 0x9c, 0x3a, 0x75,
|
||||||
|
0x0a, 0xd9, 0x9c, 0x46, 0x86, 0x41, 0x02, 0x08, 0xce, 0x86, 0xcf, 0xa0,
|
||||||
|
0xe2, 0x4a, 0x7c, 0x52, 0x96, 0x0f, 0xd1, 0x3b, 0x7c, 0x70, 0x8d, 0x23,
|
||||||
|
0xa0, 0xd4, 0x1e, 0xb8, 0x26, 0x6d, 0x08, 0x39, 0x16, 0x97, 0x3e, 0x24,
|
||||||
|
0xf1, 0x41, 0x33, 0x8e, 0x81, 0xad, 0x1d, 0x01, 0x0e, 0x04, 0xd8, 0x88,
|
||||||
|
0x31, 0xbe, 0x95, 0x2f, 0xf8, 0x02, 0x82, 0x8a, 0x2b, 0x66, 0xe8, 0x92,
|
||||||
|
0x38, 0x86, 0xca, 0x8a, 0x19, 0x9a, 0x07, 0x06, 0x13, 0x31, 0x36, 0x80,
|
||||||
|
0x56, 0xbe, 0xa0, 0xaf, 0x7e, 0x41, 0x9f, 0xcd, 0x42, 0x36, 0x07, 0x26,
|
||||||
|
0x87, 0x4d, 0x1f, 0xc3, 0x20, 0x05, 0x34, 0x29, 0x2c, 0x61, 0xcb, 0x8f,
|
||||||
|
0x19, 0x86, 0x10, 0xc0, 0x99, 0x22, 0x70, 0xad, 0x63, 0x00, 0xe5, 0xfd,
|
||||||
|
0x0c, 0x22, 0xb6, 0x32, 0xe1, 0x53, 0x47, 0xea, 0x1a, 0x09, 0x7a, 0x84,
|
||||||
|
0x27, 0xde, 0x5a, 0x03, 0xbd, 0x1f, 0x01, 0x0b, 0x00, 0xe4, 0x2a, 0x15,
|
||||||
|
0x5f, 0x8d, 0x82, 0x4d, 0xfd, 0x46, 0xfc, 0x2b, 0x66, 0x06, 0x2c, 0x0d,
|
||||||
|
0x91, 0xb4, 0x62, 0x06, 0xdd, 0x95, 0x30, 0x8f, 0x82, 0x02, 0x8c, 0x98,
|
||||||
|
0x85, 0x22, 0x20, 0xfd, 0x83, 0x31, 0x35, 0x80, 0xdc, 0x85, 0xaf, 0x1e,
|
||||||
|
0x87, 0x8f, 0x56, 0x23, 0x77, 0xae, 0xd0, 0x53, 0x80, 0x27, 0xd2, 0xfe,
|
||||||
|
0x4f, 0x4f, 0xd4, 0xbd, 0xa0, 0xe0, 0x70, 0x43, 0x4e, 0x3d, 0x83, 0x35,
|
||||||
|
0x35, 0x10, 0x15, 0x10, 0xb0, 0x5e, 0x23, 0x7a, 0x4f, 0x13, 0x39, 0x40,
|
||||||
|
0x88, 0xe9, 0x9c, 0x61, 0x59, 0xdb, 0x30, 0xa8, 0x26, 0x85, 0xf0, 0xd5,
|
||||||
|
0x1a, 0x20, 0x87, 0xfe, 0x87, 0x75, 0x90, 0x60, 0x55, 0x22, 0x2c, 0x40,
|
||||||
|
0x60, 0x43, 0x6f, 0xd8, 0x32, 0x35, 0x7a, 0x2a, 0x80, 0x65, 0x89, 0xc1,
|
||||||
|
0xd8, 0xd9, 0x82, 0xb9, 0x9f, 0x98, 0x58, 0x81, 0xb7, 0x34, 0xd1, 0x97,
|
||||||
|
0x0e, 0x83, 0x02, 0x05, 0x5b, 0x61, 0x49, 0x85, 0x15, 0x33, 0x74, 0x2f,
|
||||||
|
0x34, 0x89, 0x4d, 0x9e, 0xf0, 0x31, 0x0a, 0x3a, 0xae, 0x98, 0xa1, 0x6b,
|
||||||
|
0x60, 0x90, 0x92, 0x4f, 0x31, 0xa6, 0x01, 0xe9, 0xb0, 0x62, 0x86, 0x6e,
|
||||||
|
0x81, 0x41, 0x4e, 0x81, 0x45, 0xea, 0x04, 0xf0, 0x90, 0x98, 0x29, 0xa7,
|
||||||
|
0xd4, 0x91, 0xb8, 0x02, 0x65, 0x48, 0x78, 0x9e, 0x61, 0x14, 0x60, 0x86,
|
||||||
|
0x00, 0x00, 0x8b, 0xc8, 0xee, 0x62, 0x10, 0xf4, 0x2e, 0x3b, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::string_view STACY_ANM2 = R"ANM2ED_FRIEND(
|
||||||
|
<AnimatedActor>
|
||||||
|
<Info CreatedBy="robot" CreatedOn="05/21/2026 10:34:48 PM" Fps="30" Version="0"/>
|
||||||
|
<Content>
|
||||||
|
<Spritesheets>
|
||||||
|
<Spritesheet Id="0" Path="stacy.png">
|
||||||
|
<Region Id="0" Name="Head" XCrop="1" YCrop="1" Width="32" Height="32" Origin="Center"/>
|
||||||
|
<Region Id="1" Name="HeadAlt" XCrop="1" YCrop="35" Width="32" Height="32" Origin="Center"/>
|
||||||
|
<Region Id="2" Name="Body" XCrop="35" YCrop="1" Width="30" Height="18" Origin="Center"/>
|
||||||
|
<Region Id="3" Name="Tail" XCrop="35" YCrop="21" Width="13" Height="12" Origin="Center"/>
|
||||||
|
</Spritesheet>
|
||||||
|
</Spritesheets>
|
||||||
|
<Layers>
|
||||||
|
<Layer Id="0" Name="Head" SpritesheetId="0"/>
|
||||||
|
<Layer Id="1" Name="Body" SpritesheetId="0"/>
|
||||||
|
<Layer Id="2" Name="Tail" SpritesheetId="0"/>
|
||||||
|
</Layers>
|
||||||
|
<Nulls/>
|
||||||
|
<Events/>
|
||||||
|
</Content>
|
||||||
|
<Animations DefaultAnimation="Main">
|
||||||
|
<Animation Name="Main" FrameNum="9" Loop="true">
|
||||||
|
<RootAnimation>
|
||||||
|
<Frame XPosition="0" YPosition="0" Delay="9" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="false"/>
|
||||||
|
</RootAnimation>
|
||||||
|
<LayerAnimations>
|
||||||
|
<LayerAnimation LayerId="2" Visible="true">
|
||||||
|
<Frame RegionId="3" XPivot="6" YPivot="6" XCrop="35" YCrop="21" Width="13" Height="12" XPosition="-12" YPosition="-10" Delay="4" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="3" XPivot="6" YPivot="6" XCrop="35" YCrop="21" Width="13" Height="12" XPosition="-12" YPosition="-11" Delay="4" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="4" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="3" XPivot="6" YPivot="6" XCrop="35" YCrop="21" Width="13" Height="12" XPosition="-12" YPosition="-10" Delay="1" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
<LayerAnimation LayerId="1" Visible="true">
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="9" XCrop="35" YCrop="1" Width="30" Height="18" XPosition="0" YPosition="-7" Delay="4" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="9" XCrop="35" YCrop="1" Width="30" Height="18" XPosition="0" YPosition="-8" Delay="4" Visible="true" XScale="95" YScale="105" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="2" XPivot="15" YPivot="9" XCrop="35" YCrop="1" Width="30" Height="18" XPosition="0" YPosition="-7" Delay="1" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
<LayerAnimation LayerId="0" Visible="true">
|
||||||
|
<Frame RegionId="0" XPivot="16" YPivot="16" XCrop="1" YCrop="1" Width="32" Height="32" XPosition="-1" YPosition="-24" Delay="4" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="16" YPivot="16" XCrop="1" YCrop="35" Width="32" Height="32" XPosition="-1" YPosition="-26" Delay="4" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="0" XPivot="16" YPivot="16" XCrop="1" YCrop="1" Width="32" Height="32" XPosition="-1" YPosition="-24" Delay="1" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
</LayerAnimations>
|
||||||
|
<NullAnimations/>
|
||||||
|
<Triggers/>
|
||||||
|
</Animation>
|
||||||
|
</Animations>
|
||||||
|
</AnimatedActor>
|
||||||
|
|
||||||
|
)ANM2ED_FRIEND";
|
||||||
|
|
||||||
|
inline constexpr unsigned char ASH_PNG[] = {
|
||||||
|
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||||
|
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x50,
|
||||||
|
0x08, 0x06, 0x00, 0x00, 0x00, 0x52, 0xe8, 0x86, 0x9a, 0x00, 0x00, 0x05,
|
||||||
|
0x56, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x63, 0x18, 0xae, 0x80, 0x91,
|
||||||
|
0x46, 0x1e, 0xfb, 0x4f, 0xc0, 0x5c, 0x46, 0x5a, 0x07, 0x28, 0xb5, 0x2c,
|
||||||
|
0xf8, 0x4f, 0xa1, 0x43, 0xa9, 0xee, 0x51, 0x4a, 0x0d, 0xc4, 0xea, 0x21,
|
||||||
|
0x1e, 0x1e, 0x1e, 0x06, 0x31, 0x31, 0x31, 0xac, 0x7e, 0x7d, 0xf5, 0xea,
|
||||||
|
0x15, 0xc3, 0x97, 0x2f, 0x5f, 0x70, 0x85, 0x03, 0xd5, 0x3c, 0x48, 0xae,
|
||||||
|
0x41, 0x28, 0x1e, 0xc2, 0xe7, 0x11, 0x42, 0x31, 0x89, 0xc3, 0xa3, 0x14,
|
||||||
|
0x7b, 0x90, 0x1c, 0x03, 0xe0, 0x9e, 0xa2, 0xc4, 0x43, 0xe8, 0x1e, 0xc6,
|
||||||
|
0xe2, 0x41, 0x8a, 0x3c, 0x47, 0xaa, 0x66, 0xb0, 0xa7, 0xa8, 0xe9, 0x21,
|
||||||
|
0x02, 0x1e, 0x24, 0xdb, 0x73, 0xa4, 0x68, 0xa4, 0xb9, 0xa7, 0x60, 0x9e,
|
||||||
|
0x44, 0x8b, 0x3d, 0xb2, 0x3c, 0x47, 0xac, 0x26, 0xba, 0x79, 0x8a, 0x5a,
|
||||||
|
0x9e, 0x23, 0xc6, 0x63, 0x74, 0xf7, 0x14, 0x35, 0x3c, 0x47, 0xc8, 0x63,
|
||||||
|
0x03, 0xe6, 0x29, 0x4a, 0x3d, 0x87, 0xcf, 0x63, 0x03, 0xee, 0x29, 0x4a,
|
||||||
|
0x3c, 0xc7, 0x84, 0xa3, 0x9e, 0x21, 0xd9, 0x53, 0x65, 0x65, 0x65, 0x0c,
|
||||||
|
0x77, 0xef, 0xde, 0x05, 0x63, 0x06, 0x2a, 0x03, 0x50, 0x65, 0x0f, 0x2a,
|
||||||
|
0x89, 0xa1, 0xc6, 0x12, 0xd5, 0xca, 0x61, 0x22, 0xd5, 0x0d, 0xb8, 0x1c,
|
||||||
|
0x9f, 0x9e, 0x9e, 0x4e, 0xb2, 0x77, 0x90, 0x03, 0x03, 0x66, 0x2e, 0x88,
|
||||||
|
0x06, 0x89, 0x53, 0x1a, 0x36, 0xd8, 0x3c, 0x06, 0x0f, 0x11, 0x5c, 0xcd,
|
||||||
|
0x22, 0x90, 0xa5, 0x20, 0x07, 0x80, 0x68, 0x98, 0xe3, 0x60, 0x0e, 0x99,
|
||||||
|
0x39, 0x73, 0x26, 0x51, 0x6e, 0x02, 0xe9, 0xc7, 0x15, 0x18, 0x20, 0x71,
|
||||||
|
0x98, 0xf9, 0x30, 0xc3, 0xd0, 0xdc, 0x42, 0x30, 0xd6, 0x58, 0x70, 0xb9,
|
||||||
|
0x02, 0x29, 0xea, 0x51, 0x94, 0x28, 0x2b, 0x2b, 0xc3, 0x93, 0x1b, 0xba,
|
||||||
|
0xe5, 0x20, 0x39, 0x62, 0x7c, 0x45, 0x6c, 0x8c, 0x80, 0xd4, 0x75, 0x75,
|
||||||
|
0x75, 0xc1, 0x8d, 0x04, 0xb9, 0x09, 0x4f, 0x3b, 0x13, 0xc5, 0x6a, 0xf4,
|
||||||
|
0x18, 0x23, 0x2a, 0xb6, 0xb0, 0xc5, 0x0a, 0xb1, 0x9e, 0x02, 0xd9, 0x4e,
|
||||||
|
0x6c, 0xb2, 0x45, 0x57, 0x47, 0x4a, 0xac, 0x61, 0xcd, 0x63, 0xb8, 0x62,
|
||||||
|
0x0b, 0x16, 0x24, 0xe8, 0x16, 0x12, 0x9b, 0xfc, 0x18, 0xa8, 0x00, 0x08,
|
||||||
|
0xb9, 0x0d, 0x66, 0x05, 0xb2, 0xc7, 0x08, 0xa6, 0x5b, 0xf4, 0xfc, 0x84,
|
||||||
|
0xcb, 0xa3, 0x0c, 0x54, 0x02, 0x44, 0x04, 0x18, 0x4e, 0x37, 0x63, 0xc4,
|
||||||
|
0x18, 0xbe, 0x06, 0x2e, 0x72, 0x4c, 0x81, 0x2c, 0x45, 0x4e, 0x7e, 0xe8,
|
||||||
|
0xf9, 0x0d, 0x9f, 0xdf, 0x08, 0x39, 0x18, 0x66, 0x36, 0x72, 0xfe, 0x82,
|
||||||
|
0x99, 0x87, 0x56, 0xf4, 0xe3, 0xb4, 0x86, 0x89, 0x9c, 0xc0, 0x05, 0x59,
|
||||||
|
0x0c, 0xb3, 0x94, 0x94, 0xbc, 0x05, 0xb3, 0x0b, 0xa4, 0x17, 0x9b, 0xe7,
|
||||||
|
0xf0, 0x79, 0x88, 0x54, 0x77, 0x22, 0xb7, 0x3c, 0x06, 0x4d, 0x4b, 0x83,
|
||||||
|
0x90, 0x27, 0x88, 0x69, 0xfd, 0xc3, 0x62, 0xec, 0x3f, 0xc3, 0xd0, 0x05,
|
||||||
|
0x58, 0xdd, 0x8e, 0x92, 0x14, 0x89, 0x2d, 0x71, 0x06, 0x43, 0x18, 0x10,
|
||||||
|
0x72, 0x2b, 0x13, 0xb9, 0x8e, 0x44, 0x6f, 0x0e, 0x91, 0xd3, 0x0c, 0xa2,
|
||||||
|
0x86, 0x19, 0xb8, 0xdc, 0x0f, 0xcb, 0x63, 0xf0, 0xfc, 0x05, 0x52, 0x88,
|
||||||
|
0xaf, 0x29, 0x05, 0x92, 0x07, 0x39, 0x08, 0x57, 0x25, 0x8b, 0x5c, 0xb0,
|
||||||
|
0xe0, 0xb2, 0x94, 0x52, 0xfd, 0xa0, 0x3c, 0x06, 0x32, 0x1b, 0xa9, 0x15,
|
||||||
|
0x82, 0xd1, 0x4b, 0x21, 0xcb, 0x63, 0xf8, 0x8a, 0x76, 0x58, 0x29, 0x89,
|
||||||
|
0xcd, 0xf1, 0xc8, 0x9e, 0x26, 0xc6, 0x0c, 0x5c, 0x01, 0x43, 0x8c, 0xc7,
|
||||||
|
0xc8, 0x2e, 0xee, 0xb1, 0x59, 0x8a, 0xcf, 0x53, 0x20, 0xf5, 0xa0, 0x58,
|
||||||
|
0x86, 0x25, 0x59, 0x5c, 0xd5, 0x04, 0xb5, 0x5a, 0x31, 0x64, 0x79, 0x0c,
|
||||||
|
0x5b, 0x3d, 0x44, 0xc8, 0x53, 0xb0, 0x80, 0xc0, 0xe7, 0x39, 0x62, 0x92,
|
||||||
|
0x31, 0xb1, 0x65, 0x02, 0xd9, 0x85, 0x07, 0xae, 0x4a, 0x96, 0x98, 0x06,
|
||||||
|
0x2e, 0x36, 0x35, 0xd4, 0xf4, 0x14, 0xc8, 0xf3, 0x28, 0x79, 0x0c, 0x24,
|
||||||
|
0x40, 0xc9, 0x98, 0x21, 0xbe, 0x42, 0x01, 0x3d, 0xa4, 0x29, 0xf1, 0x08,
|
||||||
|
0x31, 0x83, 0xab, 0xb0, 0x18, 0xa3, 0x68, 0xd4, 0x15, 0xe6, 0x68, 0x5c,
|
||||||
|
0xb1, 0x48, 0x4d, 0x4f, 0x61, 0x49, 0x8a, 0x58, 0xdd, 0x8e, 0xb5, 0x49,
|
||||||
|
0x05, 0xd2, 0x4c, 0xa8, 0xc8, 0x67, 0x18, 0x20, 0x40, 0x4c, 0x89, 0x08,
|
||||||
|
0x72, 0x1a, 0x13, 0xc3, 0x30, 0x05, 0x18, 0x1e, 0x23, 0xb6, 0xeb, 0x3d,
|
||||||
|
0x90, 0xe1, 0x41, 0x8c, 0x1b, 0x91, 0x3d, 0x86, 0x92, 0x56, 0x61, 0x51,
|
||||||
|
0x3e, 0x98, 0x22, 0x14, 0x8b, 0x9b, 0x70, 0x96, 0x0d, 0x58, 0x93, 0xe2,
|
||||||
|
0x60, 0x8e, 0x35, 0x72, 0x07, 0x73, 0x06, 0x6d, 0xac, 0x91, 0x12, 0x5b,
|
||||||
|
0x78, 0x0b, 0x0f, 0x58, 0xc8, 0x0c, 0x86, 0x24, 0x89, 0xa5, 0x24, 0x24,
|
||||||
|
0x98, 0x43, 0x98, 0x88, 0xa9, 0x17, 0x06, 0xd2, 0x73, 0x38, 0xec, 0x26,
|
||||||
|
0x58, 0xef, 0xe2, 0x52, 0x00, 0xef, 0x95, 0xa2, 0x77, 0xe8, 0xe8, 0x55,
|
||||||
|
0xbf, 0xa1, 0x7b, 0x08, 0x2d, 0x6f, 0x91, 0xed, 0x31, 0x50, 0x44, 0xe2,
|
||||||
|
0xf4, 0x1c, 0x2c, 0x96, 0xa9, 0xed, 0x49, 0x5c, 0x29, 0x83, 0x54, 0x4f,
|
||||||
|
0x81, 0xdc, 0x47, 0xd4, 0xfc, 0x18, 0x48, 0x21, 0x31, 0xc3, 0x06, 0xa4,
|
||||||
|
0x7a, 0x94, 0x98, 0x24, 0x4e, 0x8e, 0xa7, 0x88, 0xf1, 0x18, 0x4a, 0xcc,
|
||||||
|
0x11, 0xeb, 0x41, 0x6a, 0xd4, 0x7d, 0x58, 0x8a, 0x75, 0x46, 0x52, 0xcc,
|
||||||
|
0x25, 0x56, 0x31, 0xd6, 0x91, 0x20, 0x6a, 0x0f, 0xfe, 0x50, 0x73, 0x61,
|
||||||
|
0x0b, 0x29, 0xa1, 0x40, 0x70, 0x88, 0x8e, 0x54, 0x8f, 0x12, 0x59, 0xd9,
|
||||||
|
0x32, 0x92, 0x93, 0x02, 0xc8, 0xd1, 0x44, 0xaf, 0x31, 0x48, 0x46, 0x4a,
|
||||||
|
0x92, 0x34, 0x23, 0x85, 0xf9, 0x81, 0xda, 0x9e, 0x64, 0x64, 0xa0, 0x12,
|
||||||
|
0xa0, 0x9a, 0x41, 0x50, 0xf7, 0x90, 0xea, 0x51, 0x6a, 0xdb, 0xcf, 0x30,
|
||||||
|
0x0a, 0x86, 0x6a, 0x08, 0x50, 0x33, 0x29, 0xfc, 0x1f, 0x4c, 0xd9, 0x83,
|
||||||
|
0x12, 0x8f, 0x0d, 0xea, 0xd2, 0x91, 0x6a, 0xc5, 0x3d, 0x33, 0x33, 0x33,
|
||||||
|
0x03, 0x27, 0x27, 0x27, 0x03, 0xb9, 0xed, 0x47, 0x50, 0xf3, 0xea, 0xfb,
|
||||||
|
0xf7, 0xef, 0x0c, 0x7f, 0xff, 0xfe, 0xc5, 0x15, 0xf1, 0x34, 0x69, 0x79,
|
||||||
|
0x80, 0x2c, 0x43, 0x89, 0x21, 0x4a, 0xc6, 0x1f, 0x89, 0x4d, 0xb2, 0xaf,
|
||||||
|
0xb0, 0x2f, 0xb3, 0x25, 0xca, 0x83, 0xc4, 0x28, 0xa2, 0xbb, 0x87, 0xd0,
|
||||||
|
0x3d, 0x4e, 0x8e, 0x07, 0x09, 0x79, 0x0c, 0xee, 0x29, 0x42, 0x31, 0x84,
|
||||||
|
0x3c, 0x0a, 0x4c, 0xce, 0xbc, 0x34, 0x31, 0xb1, 0x88, 0xc5, 0x83, 0x8c,
|
||||||
|
0xe4, 0xa4, 0x5b, 0xb0, 0xa7, 0xd0, 0x3d, 0x04, 0x9b, 0xfe, 0x41, 0x77,
|
||||||
|
0x3c, 0xf2, 0xb4, 0x10, 0x39, 0x1e, 0xc3, 0x35, 0x3c, 0x8e, 0x6d, 0x28,
|
||||||
|
0x1c, 0xcd, 0x83, 0x58, 0x3d, 0x87, 0x6b, 0xc0, 0x14, 0xab, 0xa7, 0x90,
|
||||||
|
0x43, 0x87, 0xd2, 0xb5, 0x54, 0xe8, 0x66, 0x91, 0xba, 0xae, 0x0a, 0xa9,
|
||||||
|
0xc1, 0x8d, 0xb5, 0x74, 0xc6, 0xb6, 0x96, 0x0a, 0xac, 0x10, 0x54, 0xca,
|
||||||
|
0x61, 0x2b, 0xe1, 0xa8, 0xb1, 0x96, 0x0a, 0xd9, 0x53, 0xc4, 0x4e, 0xf1,
|
||||||
|
0x82, 0xd4, 0x21, 0xaf, 0xfb, 0x00, 0xb9, 0x0d, 0xa9, 0x14, 0x05, 0xb9,
|
||||||
|
0x19, 0x25, 0xe6, 0x70, 0x0e, 0x71, 0x83, 0x8a, 0x6e, 0x5c, 0xe9, 0x17,
|
||||||
|
0xdb, 0xe4, 0x1c, 0xb9, 0xf9, 0x8a, 0xdc, 0x75, 0x55, 0x20, 0xb7, 0xe1,
|
||||||
|
0x73, 0x23, 0xba, 0xc7, 0xf0, 0xc6, 0x16, 0xcc, 0xa3, 0x03, 0xb9, 0x96,
|
||||||
|
0x0a, 0x39, 0xb0, 0x41, 0xb1, 0x06, 0x4a, 0x59, 0x50, 0x31, 0x94, 0x24,
|
||||||
|
0x89, 0x35, 0xc6, 0x70, 0x85, 0x04, 0x6c, 0x96, 0x1f, 0x3d, 0x26, 0xc9,
|
||||||
|
0x59, 0x84, 0xc9, 0x40, 0x22, 0xc0, 0x35, 0x85, 0x8b, 0xcb, 0xad, 0xc8,
|
||||||
|
0x1e, 0x23, 0x58, 0x60, 0x50, 0x6b, 0x2d, 0x15, 0xb2, 0x9f, 0x08, 0xcd,
|
||||||
|
0x39, 0x13, 0x5a, 0x86, 0x84, 0x2b, 0xd6, 0x98, 0x18, 0xc8, 0x00, 0xc8,
|
||||||
|
0x45, 0x30, 0xa5, 0x75, 0x16, 0x35, 0xd6, 0x55, 0x61, 0x8b, 0x35, 0x46,
|
||||||
|
0xe4, 0xf4, 0x49, 0x69, 0x7b, 0x8f, 0x61, 0x80, 0x00, 0x96, 0x76, 0x26,
|
||||||
|
0x23, 0x4a, 0x8c, 0xe1, 0x2b, 0x65, 0xb0, 0xb9, 0x99, 0x1a, 0x2b, 0x6b,
|
||||||
|
0xa8, 0xb5, 0x3a, 0x07, 0xdd, 0xed, 0x28, 0x31, 0x06, 0xab, 0xf4, 0x88,
|
||||||
|
0x69, 0xa1, 0x0f, 0xf4, 0xea, 0x1c, 0xe4, 0x80, 0x86, 0x0d, 0xbc, 0x22,
|
||||||
|
0xaf, 0xd4, 0xc1, 0xea, 0x31, 0x90, 0x26, 0x42, 0x9e, 0x1b, 0xe8, 0xd5,
|
||||||
|
0x39, 0x30, 0x8f, 0x21, 0x8f, 0x26, 0x23, 0x7b, 0x8c, 0x89, 0xdc, 0x6c,
|
||||||
|
0x81, 0xab, 0x34, 0x1b, 0x2c, 0xab, 0x73, 0x50, 0x3c, 0x06, 0x6a, 0xa2,
|
||||||
|
0x60, 0x0b, 0x09, 0x6c, 0x9e, 0x1f, 0x0c, 0xab, 0x73, 0x90, 0x63, 0x0b,
|
||||||
|
0xd9, 0xed, 0x20, 0xf7, 0x22, 0xb7, 0xaf, 0xe0, 0xf5, 0x18, 0x36, 0x8f,
|
||||||
|
0xe0, 0x4a, 0x9a, 0xd8, 0xba, 0x2b, 0xc4, 0xae, 0x0f, 0x86, 0xc5, 0x2e,
|
||||||
|
0x4c, 0x3d, 0x31, 0x8b, 0x5a, 0x88, 0x98, 0x91, 0x61, 0xc4, 0xea, 0x31,
|
||||||
|
0x58, 0x91, 0x4f, 0x28, 0x89, 0x12, 0xe3, 0x51, 0x42, 0x66, 0x50, 0xe2,
|
||||||
|
0x11, 0x64, 0xb3, 0xd1, 0x86, 0x14, 0x30, 0x3c, 0x06, 0x52, 0x0b, 0x6f,
|
||||||
|
0x2b, 0x82, 0x38, 0xa4, 0x16, 0xff, 0x30, 0xcb, 0x7a, 0x7a, 0x7a, 0x18,
|
||||||
|
0x08, 0x35, 0xb3, 0x40, 0x9e, 0x2a, 0x29, 0x29, 0x61, 0xa0, 0x04, 0xc0,
|
||||||
|
0x92, 0x1f, 0xd2, 0x38, 0x09, 0x3c, 0x05, 0x62, 0xeb, 0xa4, 0xc1, 0x1b,
|
||||||
|
0x93, 0x48, 0x0d, 0x4c, 0x06, 0x72, 0x3d, 0xc9, 0x40, 0x65, 0x80, 0x9c,
|
||||||
|
0x97, 0xd0, 0x06, 0x7e, 0x50, 0xfc, 0x82, 0xab, 0x6b, 0x8d, 0xd1, 0x79,
|
||||||
|
0x43, 0xf6, 0x24, 0x25, 0xb1, 0x49, 0xaa, 0x3f, 0xd1, 0x0b, 0x05, 0x1c,
|
||||||
|
0xa3, 0x58, 0x18, 0xfe, 0x20, 0x7a, 0xcc, 0x03, 0xdd, 0x41, 0xe8, 0x1e,
|
||||||
|
0x65, 0xa0, 0x11, 0xc0, 0x33, 0x1c, 0x07, 0xb2, 0x11, 0xa7, 0xfb, 0x19,
|
||||||
|
0x49, 0x70, 0xcf, 0x7f, 0x86, 0xc1, 0x01, 0x88, 0x72, 0x33, 0x23, 0x05,
|
||||||
|
0x6e, 0xa5, 0x97, 0x47, 0x19, 0x19, 0x46, 0x01, 0x22, 0x04, 0x00, 0x79,
|
||||||
|
0x99, 0xa8, 0x4a, 0x64, 0xc2, 0x18, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x49,
|
||||||
|
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr std::string_view ASH_ANM2 = R"ANM2ED_FRIEND(
|
||||||
|
<AnimatedActor>
|
||||||
|
<Info CreatedBy="robot" CreatedOn="05/21/2026 09:25:40 PM" Fps="30" Version="0"/>
|
||||||
|
<Content>
|
||||||
|
<Spritesheets>
|
||||||
|
<Spritesheet Id="0" Path="ash.png">
|
||||||
|
<Region Id="0" Name="1" XCrop="1" YCrop="51" Width="52" Height="28" XPivot="25" YPivot="28"/>
|
||||||
|
<Region Id="1" Name="2" XCrop="1" YCrop="1" Width="48" Height="48" XPivot="24" YPivot="48"/>
|
||||||
|
</Spritesheet>
|
||||||
|
</Spritesheets>
|
||||||
|
<Layers>
|
||||||
|
<Layer Id="0" Name="Main" SpritesheetId="0"/>
|
||||||
|
</Layers>
|
||||||
|
<Nulls/>
|
||||||
|
<Events/>
|
||||||
|
</Content>
|
||||||
|
<Animations DefaultAnimation="Main">
|
||||||
|
<Animation Name="Main" FrameNum="9" Loop="true">
|
||||||
|
<RootAnimation>
|
||||||
|
<Frame XPosition="0" YPosition="0" Delay="9" Visible="true" XScale="100" YScale="100" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="false"/>
|
||||||
|
</RootAnimation>
|
||||||
|
<LayerAnimations>
|
||||||
|
<LayerAnimation LayerId="0" Visible="true">
|
||||||
|
<Frame RegionId="1" XPivot="24" YPivot="48" XCrop="1" YCrop="1" Width="48" Height="48" XPosition="1" YPosition="-4" Delay="3" Visible="true" XScale="95" YScale="105" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="0" XPivot="25" YPivot="28" XCrop="1" YCrop="51" Width="52" Height="28" XPosition="1" YPosition="-4" Delay="5" Visible="true" XScale="105" YScale="95" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
<Frame RegionId="1" XPivot="24" YPivot="48" XCrop="1" YCrop="1" Width="48" Height="48" XPosition="1" YPosition="-4" Delay="1" Visible="true" XScale="90" YScale="110" RedTint="255" GreenTint="255" BlueTint="255" AlphaTint="255" RedOffset="0" GreenOffset="0" BlueOffset="0" Rotation="0" Interpolated="EaseInOut"/>
|
||||||
|
</LayerAnimation>
|
||||||
|
</LayerAnimations>
|
||||||
|
<NullAnimations/>
|
||||||
|
<Triggers/>
|
||||||
|
</Animation>
|
||||||
|
</Animations>
|
||||||
|
</AnimatedActor>
|
||||||
|
|
||||||
|
)ANM2ED_FRIEND";
|
||||||
|
|
||||||
|
struct Info
|
||||||
|
{
|
||||||
|
const char* name{};
|
||||||
|
const unsigned char* png{};
|
||||||
|
std::size_t pngSize{};
|
||||||
|
std::string_view anm2{};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FRIENDS_LIST \
|
||||||
|
X(MEAT_BOY, "Meat Boy", MEAT_BOY_PNG, MEAT_BOY_ANM2) \
|
||||||
|
X(ISAAC, "Isaac", ISAAC_PNG, ISAAC_ANM2) \
|
||||||
|
X(STACY, "Stacy", STACY_PNG, STACY_ANM2) \
|
||||||
|
X(ASH, "Ash", ASH_PNG, ASH_ANM2)
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
#define X(symbol, name, png, anm2) symbol,
|
||||||
|
FRIENDS_LIST
|
||||||
|
#undef X
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr Info FRIENDS[COUNT] = {
|
||||||
|
#define X(symbol, name, png, anm2) {name, png, sizeof(png), anm2},
|
||||||
|
FRIENDS_LIST
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
}
|
||||||
+86682
-30402
File diff suppressed because it is too large
Load Diff
@@ -238,8 +238,7 @@ namespace anm2ed
|
|||||||
X(LABEL_ANIMATION_LENGTH, "Animation Length", "Duracion de Animacion", "Длина анимации", "动画时长", "애니메이션 길이") \
|
X(LABEL_ANIMATION_LENGTH, "Animation Length", "Duracion de Animacion", "Длина анимации", "动画时长", "애니메이션 길이") \
|
||||||
X(LABEL_ANIMATION_PREVIEW_WINDOW, "Animation Preview###Animation Preview", "Vista Previa de Animacion###Animation Preview", "Предпросмотр анимации###Animation Preview", "动画预放###Animation Preview", "애니메이션 프리뷰###Animation Preview") \
|
X(LABEL_ANIMATION_PREVIEW_WINDOW, "Animation Preview###Animation Preview", "Vista Previa de Animacion###Animation Preview", "Предпросмотр анимации###Animation Preview", "动画预放###Animation Preview", "애니메이션 프리뷰###Animation Preview") \
|
||||||
X(LABEL_APPEND_FRAMES, "Append Frames", "Anteponer Frames", "Добавить кадры к концу", "在后面添加帧", "뒷프레임에 추가") \
|
X(LABEL_APPEND_FRAMES, "Append Frames", "Anteponer Frames", "Добавить кадры к концу", "在后面添加帧", "뒷프레임에 추가") \
|
||||||
X(LABEL_APPLICATION_NAME, "Anm2Ed", "Anm2Ed", "Anm2Ed", "Anm2Ed", "Anm2Ed") \
|
X(LABEL_APPLICATION_NAME, "Anm2Ed Version 2.5", "Anm2Ed Version 2.5", "Anm2Ed Версия 2.5", "Anm2Ed 2.5版本", "Anm2Ed 버전 2.5") \
|
||||||
X(LABEL_APPLICATION_VERSION, "Version 2.4", "Version 2.4", "Версия 2.4", "2.4版本", "버전 2.4") \
|
|
||||||
X(LABEL_AUTHOR, "Author", "Autor", "Автор", "制作者", "작성자") \
|
X(LABEL_AUTHOR, "Author", "Autor", "Автор", "制作者", "작성자") \
|
||||||
X(LABEL_AUTOSAVE, "Autosave", "Autoguardado", "Автосохранение", "自动保存", "자동저장") \
|
X(LABEL_AUTOSAVE, "Autosave", "Autoguardado", "Автосохранение", "自动保存", "자동저장") \
|
||||||
X(LABEL_AXES, "Axes", "Ejes", "Оси", "坐标轴", "가로/세로 축") \
|
X(LABEL_AXES, "Axes", "Ejes", "Оси", "坐标轴", "가로/세로 축") \
|
||||||
|
|||||||
@@ -118,6 +118,20 @@ namespace anm2ed::resource
|
|||||||
upload(data);
|
upload(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture::Texture(const unsigned char* pngData, size_t pngSize)
|
||||||
|
{
|
||||||
|
if (!pngData || pngSize == 0) return;
|
||||||
|
|
||||||
|
auto sizeInt = static_cast<int>(pngSize);
|
||||||
|
if (sizeInt <= 0) return;
|
||||||
|
|
||||||
|
if (auto data = stbi_load_from_memory(pngData, sizeInt, &size.x, &size.y, nullptr, CHANNELS); data)
|
||||||
|
{
|
||||||
|
upload(data);
|
||||||
|
stbi_image_free((void*)data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Texture::Texture(const std::filesystem::path& pngPath)
|
Texture::Texture(const std::filesystem::path& pngPath)
|
||||||
{
|
{
|
||||||
File file(pngPath, "rb");
|
File file(pngPath, "rb");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ namespace anm2ed::resource
|
|||||||
Texture& operator=(const Texture&);
|
Texture& operator=(const Texture&);
|
||||||
Texture& operator=(Texture&&);
|
Texture& operator=(Texture&&);
|
||||||
Texture(const uint8_t*, glm::ivec2);
|
Texture(const uint8_t*, glm::ivec2);
|
||||||
|
Texture(const unsigned char*, size_t);
|
||||||
Texture(const char*, size_t, glm::ivec2);
|
Texture(const char*, size_t, glm::ivec2);
|
||||||
Texture(const std::filesystem::path&);
|
Texture(const std::filesystem::path&);
|
||||||
bool write_png(const std::filesystem::path&);
|
bool write_png(const std::filesystem::path&);
|
||||||
|
|||||||
@@ -100,12 +100,25 @@ namespace anm2ed::util::path
|
|||||||
std::filesystem::path make_relative(const std::filesystem::path& path)
|
std::filesystem::path make_relative(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
if (path.empty()) return path;
|
if (path.empty()) return path;
|
||||||
|
if (!path.is_absolute()) return path;
|
||||||
|
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
auto relative = std::filesystem::relative(path, ec);
|
auto relative = std::filesystem::relative(path, ec);
|
||||||
if (!ec) return relative;
|
if (!ec) return relative;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::filesystem::path make_relative(const std::filesystem::path& path, const std::filesystem::path& base)
|
||||||
|
{
|
||||||
|
if (path.empty()) return path;
|
||||||
|
if (base.empty() || !path.is_absolute()) return path;
|
||||||
|
|
||||||
|
std::error_code ec{};
|
||||||
|
auto relative = std::filesystem::relative(path, base, ec);
|
||||||
|
if (!ec) return relative;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
std::filesystem::path lower_case_backslash_handle(const std::filesystem::path& path)
|
std::filesystem::path lower_case_backslash_handle(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
auto newPath = path;
|
auto newPath = path;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace anm2ed::util::path
|
|||||||
std::string to_utf8(const std::filesystem::path&);
|
std::string to_utf8(const std::filesystem::path&);
|
||||||
std::filesystem::path from_utf8(const std::string&);
|
std::filesystem::path from_utf8(const std::string&);
|
||||||
std::filesystem::path make_relative(const std::filesystem::path&);
|
std::filesystem::path make_relative(const std::filesystem::path&);
|
||||||
|
std::filesystem::path make_relative(const std::filesystem::path&, const std::filesystem::path&);
|
||||||
|
|
||||||
bool is_exist(const std::filesystem::path&);
|
bool is_exist(const std::filesystem::path&);
|
||||||
bool is_executable(const std::filesystem::path&);
|
bool is_executable(const std::filesystem::path&);
|
||||||
|
|||||||
Reference in New Issue
Block a user