From da80192d0ff326e6588fa42de6a6f5b8f701e9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Mon, 17 Apr 2023 14:48:27 -0300 Subject: [PATCH] Add UUID type to user properties (fix #3810) --- docs/ase-file-specs.md | 3 +++ src/app/file/ase_format.cpp | 7 +++++++ src/app/file/file_tests.cpp | 18 +++++++++++++++--- src/app/script/engine.h | 2 ++ src/app/script/values.cpp | 19 +++++++++++++++++++ src/dio/aseprite_decoder.cpp | 8 ++++++++ src/doc/user_data.h | 5 ++++- src/doc/user_data_io.cpp | 14 ++++++++++++++ 8 files changed, 72 insertions(+), 4 deletions(-) diff --git a/docs/ase-file-specs.md b/docs/ase-file-specs.md index f97c0942e..d2c7cc03c 100644 --- a/docs/ase-file-specs.md +++ b/docs/ase-file-specs.md @@ -43,6 +43,7 @@ ASE files use Intel (little-endian) byte order. * `TILE`: **Tilemaps**: Each tile can be a 8-bit (`BYTE`), 16-bit (`WORD`), or 32-bit (`DWORD`) value and there are masks related to the meaning of each bit. +* `UUID`: A Universally Unique Identifier stored as `BYTE[16]`. ## Introduction @@ -446,6 +447,8 @@ The data of this chunk is as follows: DWORD Number of properties BYTE[] Nested properties data Structure is the same as indicated in this loop + + If type==0x0013 + UUID ### Slice Chunk (0x2022) diff --git a/src/app/file/ase_format.cpp b/src/app/file/ase_format.cpp index 4cc51b84d..0cbe4c51a 100644 --- a/src/app/file/ase_format.cpp +++ b/src/app/file/ase_format.cpp @@ -1610,6 +1610,13 @@ static void ase_file_write_property_value(FILE* f, } break; } + case USER_DATA_PROPERTY_TYPE_UUID: { + auto& uuid = *std::get_if(&value); + for (int i=0; i<16; ++i) { + fputc(uuid[i], f); + } + break; + } } } diff --git a/src/app/file/file_tests.cpp b/src/app/file/file_tests.cpp index e697b3013..f888f99ff 100644 --- a/src/app/file/file_tests.cpp +++ b/src/app/file/file_tests.cpp @@ -108,6 +108,7 @@ TEST(File, CustomProperties) {"weight", doc::UserData::Fixed{fixmath::ftofix(50.34)}}, {"big_number", int64_t(9223372036854775807)}, {"unsigned_big_number", uint64_t(18446744073709551615ULL)}, + {"my_uuid", base::Uuid::Generate()}, } } }, @@ -121,6 +122,8 @@ TEST(File, CustomProperties) ASSERT_EQ(doc::get_value(sprite->userData().properties()["weight"]).value, fixmath::ftofix(50.34)); ASSERT_EQ(doc::get_value(sprite->userData().properties()["big_number"]), 9223372036854775807); ASSERT_EQ(doc::get_value(sprite->userData().properties()["unsigned_big_number"]), 18446744073709551615ULL); + ASSERT_EQ(doc::get_value(sprite->userData().properties()["my_uuid"]), + doc::get_value(test.propertiesMaps.at("").at("my_uuid"))); } }, { // Test sprite's userData extension's simple properties @@ -130,7 +133,8 @@ TEST(File, CustomProperties) {"number", int32_t(160304)}, {"is_solid", bool(false)}, {"label", std::string("Smoke")}, - {"weight", doc::UserData::Fixed{fixmath::ftofix(0.14)}} + {"weight", doc::UserData::Fixed{fixmath::ftofix(0.14)}}, + {"my_uuid", base::Uuid::Generate()}, } } }, @@ -142,6 +146,8 @@ TEST(File, CustomProperties) ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["is_solid"]), false); ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["label"]), "Smoke"); ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["weight"]).value, fixmath::ftofix(0.14)); + ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["my_uuid"]), + doc::get_value(test.propertiesMaps.at("extensionIdentification").at("my_uuid"))); } }, { // Test sprite's userData custom + extension's simple properties @@ -151,14 +157,16 @@ TEST(File, CustomProperties) {"number", int32_t(560304)}, {"is_solid", bool(true)}, {"label", std::string("Rock")}, - {"weight", doc::UserData::Fixed{fixmath::ftofix(50.34)}} + {"weight", doc::UserData::Fixed{fixmath::ftofix(50.34)}}, + {"my_uuid", base::Uuid::Generate()}, } }, {"extensionIdentification", { {"number", int32_t(160304)}, {"is_solid", bool(false)}, {"label", std::string("Smoke")}, - {"weight", doc::UserData::Fixed{fixmath::ftofix(0.14)}} + {"weight", doc::UserData::Fixed{fixmath::ftofix(0.14)}}, + {"my_uuid2", base::Uuid::Generate()}, } } }, @@ -170,11 +178,15 @@ TEST(File, CustomProperties) ASSERT_EQ(doc::get_value(sprite->userData().properties()["is_solid"]), true); ASSERT_EQ(doc::get_value(sprite->userData().properties()["label"]), "Rock"); ASSERT_EQ(doc::get_value(sprite->userData().properties()["weight"]).value, fixmath::ftofix(50.34)); + ASSERT_EQ(doc::get_value(sprite->userData().properties("")["my_uuid"]), + doc::get_value(test.propertiesMaps.at("").at("my_uuid"))); ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["number"]), 160304); ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["is_solid"]), false); ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["label"]), "Smoke"); ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["weight"]).value, fixmath::ftofix(0.14)); + ASSERT_EQ(doc::get_value(sprite->userData().properties("extensionIdentification")["my_uuid2"]), + doc::get_value(test.propertiesMaps.at("extensionIdentification").at("my_uuid2"))); } }, { // Test sprite's userData complex properties diff --git a/src/app/script/engine.h b/src/app/script/engine.h index 8f491bc5e..e9e64996b 100644 --- a/src/app/script/engine.h +++ b/src/app/script/engine.h @@ -16,6 +16,7 @@ #include "app/color.h" #include "app/commands/params.h" #include "app/extensions.h" +#include "base/uuid.h" #include "doc/brush.h" #include "doc/frame.h" #include "doc/object_ids.h" @@ -182,6 +183,7 @@ namespace app { app::Color convert_args_into_color(lua_State* L, int index); doc::color_t convert_args_into_pixel_color(lua_State* L, int index, const doc::PixelFormat pixelFormat); + base::Uuid convert_args_into_uuid(lua_State* L, int index); doc::Palette* get_palette_from_arg(lua_State* L, int index); doc::Image* may_get_image_from_arg(lua_State* L, int index); doc::Image* get_image_from_arg(lua_State* L, int index); diff --git a/src/app/script/values.cpp b/src/app/script/values.cpp index 91987ac68..5fd7d930a 100644 --- a/src/app/script/values.cpp +++ b/src/app/script/values.cpp @@ -217,6 +217,19 @@ gfx::Rect get_value_from_lua(lua_State* L, int index) { return convert_args_into_rect(L, index); } +// ---------------------------------------------------------------------- +// Uuid + +template<> +void push_value_to_lua(lua_State* L, const base::Uuid& value) { + push_obj(L, value); +} + +template<> +base::Uuid get_value_from_lua(lua_State* L, int index) { + return convert_args_into_uuid(L, index); +} + // ---------------------------------------------------------------------- // tools::InkType @@ -372,6 +385,9 @@ void push_value_to_lua(lua_State* L, const doc::UserData::Variant& value) case USER_DATA_PROPERTY_TYPE_PROPERTIES: push_value_to_lua(L, *std::get_if(&value)); break; + case USER_DATA_PROPERTY_TYPE_UUID: + push_value_to_lua(L, *std::get_if(&value)); + break; } #else // TODO enable this in the future std::visit([L](auto&& v){ push_value_to_lua(L, v); }, value); @@ -461,6 +477,9 @@ doc::UserData::Variant get_value_from_lua(lua_State* L, int index) else if (auto sz = may_get_obj(L, index)) { v = *sz; } + else if (auto uuid = may_get_obj(L, index)) { + v = *uuid; + } break; } } diff --git a/src/dio/aseprite_decoder.cpp b/src/dio/aseprite_decoder.cpp index 415de20c1..002f48b42 100644 --- a/src/dio/aseprite_decoder.cpp +++ b/src/dio/aseprite_decoder.cpp @@ -1412,6 +1412,14 @@ const doc::UserData::Variant AsepriteDecoder::readPropertyValue(uint16_t type) } return value; } + case USER_DATA_PROPERTY_TYPE_UUID: { + base::Uuid value; + uint8_t* bytes = value.bytes(); + for (int i=0; i<16; ++i) { + bytes[i] = read8(); + } + return value; + } } return doc::UserData::Variant{}; diff --git a/src/doc/user_data.h b/src/doc/user_data.h index 3132c990f..cef408c07 100644 --- a/src/doc/user_data.h +++ b/src/doc/user_data.h @@ -9,6 +9,7 @@ #define DOC_USER_DATA_H_INCLUDED #pragma once +#include "base/uuid.h" #include "doc/color.h" #include "fixmath/fixmath.h" #include "gfx/point.h" @@ -42,6 +43,7 @@ #define USER_DATA_PROPERTY_TYPE_RECT 0x0010 #define USER_DATA_PROPERTY_TYPE_VECTOR 0x0011 #define USER_DATA_PROPERTY_TYPE_PROPERTIES 0x0012 +#define USER_DATA_PROPERTY_TYPE_UUID 0x0013 namespace doc { @@ -71,7 +73,8 @@ namespace doc { gfx::Size, gfx::Rect, Vector, - Properties>; + Properties, + base::Uuid>; struct Variant : public VariantBase { Variant() = default; diff --git a/src/doc/user_data_io.cpp b/src/doc/user_data_io.cpp index 94573d256..49b67451b 100644 --- a/src/doc/user_data_io.cpp +++ b/src/doc/user_data_io.cpp @@ -112,6 +112,12 @@ static void write_property_value(std::ostream& os, const UserData::Variant& vari } break; } + case USER_DATA_PROPERTY_TYPE_UUID: { + auto uuid = get_value(variant); + for (int i=0; i<16; ++i) { + write8(os, uuid[i]); + } + } } } @@ -227,6 +233,14 @@ static UserData::Variant read_property_value(std::istream& is, uint16_t type) } return value; } + case USER_DATA_PROPERTY_TYPE_UUID: { + base::Uuid value; + uint8_t* bytes = value.bytes(); + for (int i; i<16;++i) { + bytes[i] = read8(is); + } + return value; + } } return doc::UserData::Variant{};